go: N-Barrier Pattern

项目结构:

image

 

/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:06
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : config.go
*/
package config

import "time"

// AppConfig 全局生产配置
type AppConfig struct {
	// 生产阶段
	ProductionSteps   int
	ProductionTimeout time.Duration

	// 入库阶段
	WarehouseSteps   int
	WarehouseTimeout time.Duration

	// 发货阶段
	DeliverySteps   int
	DeliveryTimeout time.Duration

	// 重试
	MaxRetryCount int
	RetryInterval time.Duration
}

func Load() *AppConfig {
	return &AppConfig{
		ProductionSteps:   5,
		ProductionTimeout: 10 * time.Second,

		WarehouseSteps:   5,
		WarehouseTimeout: 5 * time.Second,

		DeliverySteps:   1,
		DeliveryTimeout: 3 * time.Second,

		MaxRetryCount: 2,
		RetryInterval: 500 * time.Millisecond,
	}
}




/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:07
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : logger.go
*/
package logger

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var log *zap.Logger

func Init() {
	config := zap.NewProductionConfig()
	config.EncoderConfig.TimeKey = "time"
	config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	config.DisableCaller = true

	l, _ := config.Build()
	log = l
}

func Info(msg string, fields ...zap.Field) {
	log.Info(msg, fields...)
}

func Error(msg string, fields ...zap.Field) {
	log.Error(msg, fields...)
}

func Debug(msg string, fields ...zap.Field) {
	log.Debug(msg, fields...)
}

func With(fields ...zap.Field) *zap.Logger {
	return log.With(fields...)
}

func Sync() {
	_ = log.Sync()
}

  

 

 

/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:06
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : barrier.go
*/
package barrier

import "sync"

// StageBarrier 多阶段屏障
type StageBarrier struct {
	wg    *sync.WaitGroup
	stage string
}

func NewStageBarrier(n int, stage string) *StageBarrier {
	wg := &sync.WaitGroup{}
	wg.Add(n)
	return &StageBarrier{wg: wg, stage: stage}
}

func (s *StageBarrier) Done() {
	s.wg.Done()
}

func (s *StageBarrier) Wait() {
	s.wg.Wait()
}

func (s *StageBarrier) Stage() string {
	return s.stage
}




/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:08
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : model.go
*/
package model

import "time"

// Step 珠宝生产步骤
type Step string

const (
	StepPurchase  = Step("原料采购")
	StepDesign    = Step("款式设计")
	StepProcess   = Step("工艺加工")
	StepQuality   = Step("品质质检")
	StepPackaging = Step("成品包装")
)

// WarehouseStep 入库步骤
type WarehouseStep string

const (
	WarehouseCheck   = WarehouseStep("入库核验")
	WarehouseLabel   = WarehouseStep("贴标入仓")
	WarehouseStock   = WarehouseStep("库存更新")
	WarehousePhoto   = WarehouseStep("成品拍照")
	WarehouseArchive = WarehouseStep("档案归档")
)

// DeliveryStep 发货步骤
type DeliveryStep string

const (
	DeliveryShip = DeliveryStep("批量发货")
)

// TaskResult 任务执行结果
type TaskResult struct {
	Stage   string
	Step    string
	Cost    time.Duration
	Success bool
	Retry   int
	Error   error
}

// GetProductionSteps 获取生产步骤
func GetProductionSteps() []Step {
	return []Step{StepPurchase, StepDesign, StepProcess, StepQuality, StepPackaging}
}

// GetWarehouseSteps 获取入库步骤
func GetWarehouseSteps() []WarehouseStep {
	return []WarehouseStep{WarehouseCheck, WarehouseLabel, WarehouseStock, WarehousePhoto, WarehouseArchive}
}

// GetDeliverySteps 获取发货步骤
func GetDeliverySteps() []DeliveryStep {
	return []DeliveryStep{DeliveryShip}
}

// GetStepDuration 步骤耗时
func GetStepDuration(anyStep any) time.Duration {
	switch s := anyStep.(type) {
	case Step:
		switch s {
		case StepPurchase:
			return 2 * time.Second
		case StepDesign:
			return 3 * time.Second
		case StepProcess:
			return 4 * time.Second
		case StepQuality:
			return 2 * time.Second
		case StepPackaging:
			return 1 * time.Second
		}
	case WarehouseStep:
		return 1 * time.Second
	case DeliveryStep:
		return 2 * time.Second
	}
	return 1 * time.Second
}


/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:09
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : collector.go
*/
package result

import (
	"godesginpattern/nbarrier/jewelry/model"
	"sync"
)

type Collector struct {
	mu      sync.Mutex
	results []model.TaskResult
}

func NewCollector() *Collector {
	return &Collector{}
}

func (c *Collector) Add(res model.TaskResult) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.results = append(c.results, res)
}

func (c *Collector) All() []model.TaskResult {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.results
}

func (c *Collector) SuccessCount() int {
	c.mu.Lock()
	defer c.mu.Unlock()
	count := 0
	for _, r := range c.results {
		if r.Success {
			count++
		}
	}
	return count
}

  

/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:09
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : worker.go
*/
package worker

import (
	"context"
	"go.uber.org/zap"
	"godesginpattern/nbarrier/barrier"
	"godesginpattern/nbarrier/common/logger"
	"godesginpattern/nbarrier/jewelry/model"
	"godesginpattern/nbarrier/result"
	"time"
)

type Task interface {
	Run(ctx context.Context) (model.TaskResult, error)
}

func RunWithRetryAndTimeout(
	ctx context.Context,
	task Task,
	b *barrier.StageBarrier,
	collector *result.Collector,
	maxRetry int,
	retryInterval time.Duration,
) {
	go func() {
		defer b.Done()

		stepLog := logger.With(zap.String("stage", b.Stage()))
		var res model.TaskResult

		for retry := 0; retry <= maxRetry; retry++ {
			select {
			case <-ctx.Done():
				stepLog.Error("任务超时取消", zap.Int("retry", retry))
				return
			default:
			}

			result, err := task.Run(ctx)
			result.Retry = retry
			result.Stage = b.Stage()

			if err == nil {
				res = result
				stepLog.Info("步骤完成",
					zap.String("step", result.Step),
					zap.Duration("cost", result.Cost),
					zap.Int("retry", retry))
				break
			}

			stepLog.Error("步骤执行失败",
				zap.String("step", result.Step),
				zap.Int("retry", retry),
				zap.Error(err))

			if retry == maxRetry {
				res = result
				break
			}

			time.Sleep(retryInterval)
		}

		collector.Add(res)
	}()
}

  

/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:11
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : service.go
*/
package service

import (
	"context"
	"go.uber.org/zap"
	"godesginpattern/nbarrier/common/logger"
	"godesginpattern/nbarrier/jewelry/model"
	"time"
)

type JewelryService struct{}

func NewJewelryService() *JewelryService {
	return &JewelryService{}
}

// ---------------- 生产任务 ----------------
type ProductionTask struct {
	Step model.Step
}

func (t *ProductionTask) Run(ctx context.Context) (model.TaskResult, error) {
	start := time.Now()
	dur := model.GetStepDuration(t.Step)

	logger.Info("开始生产步骤", zap.String("step", string(t.Step)))
	time.Sleep(dur)

	return model.TaskResult{
		Step:    string(t.Step),
		Cost:    time.Since(start),
		Success: true,
	}, nil
}

// ---------------- 入库任务 ----------------
type WarehouseTask struct {
	Step model.WarehouseStep
}

func (t *WarehouseTask) Run(ctx context.Context) (model.TaskResult, error) {
	start := time.Now()
	dur := model.GetStepDuration(t.Step)

	logger.Info("开始入库步骤", zap.String("step", string(t.Step)))
	time.Sleep(dur)

	return model.TaskResult{
		Step:    string(t.Step),
		Cost:    time.Since(start),
		Success: true,
	}, nil
}

// ---------------- 发货任务 ----------------
type DeliveryTask struct {
	Step model.DeliveryStep
}

func (t *DeliveryTask) Run(ctx context.Context) (model.TaskResult, error) {
	start := time.Now()
	dur := model.GetStepDuration(t.Step)

	logger.Info("开始发货步骤", zap.String("step", string(t.Step)))
	time.Sleep(dur)

	return model.TaskResult{
		Step:    string(t.Step),
		Cost:    time.Since(start),
		Success: true,
	}, nil
}

  

调用:

/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:N-Barrier Pattern 屏障模式  go get -u go.uber.org/zap
#
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/26 22:30
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : nbarrierbll.go

barrier/
├── go.mod
├── go.sum
├── main.go    # 入口:依赖注入+启动
├── config/
│   └── config.go             # 全局配置
├──
│   ├── barrier/              # 多阶段屏障核心
│   │   └── barrier.go
│   ├── jewelry/              # 珠宝业务域
│   │   ├── model/            # 模型+枚举
│   │   └── service/          # 业务逻辑
│   ├── pkg/                  # 内部公共包
│   │   ├── logger/           # zap日志
│   │   └── worker/           # 并发+重试+超时
│   └── result/               # 结果收集器
└── scripts/                  # 部署脚本(预留)
*/
package bll

import (
	"context"
	"go.uber.org/zap"
	"godesginpattern/nbarrier/barrier"
	"godesginpattern/nbarrier/common/logger"
	"godesginpattern/nbarrier/common/worker"
	"godesginpattern/nbarrier/config"
	"godesginpattern/nbarrier/jewelry/model"
	"godesginpattern/nbarrier/jewelry/service"
	"godesginpattern/nbarrier/result"
	"os/signal"
	"syscall"
	"time"
)

func NbarrierMain() {
	// 初始化日志
	logger.Init()
	defer logger.Sync()

	// 加载配置
	cfg := config.Load()

	// 优雅关闭
	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()

	logger.Info("=== 珠宝全流程生产系统启动 ===")
	logger.Info("配置加载完成",
		zap.Int("生产步骤", cfg.ProductionSteps),
		zap.Int("入库步骤", cfg.WarehouseSteps),
		zap.Int("重试次数", cfg.MaxRetryCount))

	// 结果收集器
	collector := result.NewCollector()

	// ==========================================
	// 阶段1:生产屏障
	// ==========================================
	prodCtx, cancel1 := context.WithTimeout(ctx, cfg.ProductionTimeout)
	defer cancel1()

	prodBarrier := barrier.NewStageBarrier(cfg.ProductionSteps, "生产")
	steps := model.GetProductionSteps()

	for _, step := range steps {
		task := &service.ProductionTask{Step: step}
		worker.RunWithRetryAndTimeout(
			prodCtx, task, prodBarrier, collector,
			cfg.MaxRetryCount, cfg.RetryInterval)
	}

	logger.Info("=== 等待所有生产步骤完成 ===")
	prodBarrier.Wait()
	logger.Info("=== 【生产屏障通过】 ===")

	// ==========================================
	// 阶段2:入库屏障
	// ==========================================
	whCtx, cancel2 := context.WithTimeout(ctx, cfg.WarehouseTimeout)
	defer cancel2()

	whBarrier := barrier.NewStageBarrier(cfg.WarehouseSteps, "入库")
	whSteps := model.GetWarehouseSteps()

	for _, step := range whSteps {
		task := &service.WarehouseTask{Step: step}
		worker.RunWithRetryAndTimeout(
			whCtx, task, whBarrier, collector,
			cfg.MaxRetryCount, cfg.RetryInterval)
	}

	logger.Info("=== 等待所有入库步骤完成 ===")
	whBarrier.Wait()
	logger.Info("=== 【入库屏障通过】 ===")

	// ==========================================
	// 阶段3:发货屏障
	// ==========================================
	deliverCtx, cancel3 := context.WithTimeout(ctx, cfg.DeliveryTimeout)
	defer cancel3()

	dlBarrier := barrier.NewStageBarrier(cfg.DeliverySteps, "发货")
	dlSteps := model.GetDeliverySteps()

	for _, step := range dlSteps {
		task := &service.DeliveryTask{Step: step}
		worker.RunWithRetryAndTimeout(
			deliverCtx, task, dlBarrier, collector,
			cfg.MaxRetryCount, cfg.RetryInterval)
	}

	logger.Info("=== 等待发货完成 ===")
	dlBarrier.Wait()
	logger.Info("=== 【发货屏障通过】 ===")

	// ==========================================
	// 最终汇总
	// ==========================================
	time.Sleep(300 * time.Millisecond)
	logger.Info("========================================")
	logger.Info("✅ 全流程完成",
		zap.Int("总任务数", len(collector.All())),
		zap.Int("成功数", collector.SuccessCount()))
	logger.Info("✅ 珠宝成品 → 生产 → 入库 → 发货 全流程完成")
	logger.Info("========================================")
}

  

输出:

image

 

posted @ 2026-05-26 22:48  ®Geovin Du Dream Park™  阅读(7)  评论(0)    收藏  举报