package message import ( "context" "fmt" "sync" "time" "github.com/gogf/gf/v2/frame/g" ) // MessageType 消息队列类型 type messageType string const ( // MessageRedis Redis 消息队列 MessageRedis messageType = "redis" // MessageRabbitMQ RabbitMQ 消息队列 MessageRabbitMQ messageType = "rabbitmq" // MessageNATS NATS 消息队列 MessageNATS messageType = "nats" ) // configFactory 消息队列配置工厂函数类型 type configFactory func() messageUtil // PluginManager 消息队列插件管理器 type pluginManager struct { mu sync.RWMutex instances map[messageType]messageUtil // 已连接的插件实例 } var ( defaultPluginManager = newPluginManager() // 不再支持默认插件类型,必须显式指定类型 ) // newPluginManager 创建插件管理器 func newPluginManager() *pluginManager { return &pluginManager{ instances: make(map[messageType]messageUtil), } } // RegisterPlugin 注册消息队列插件 // 所有插件必须通过此方法注册,自动进行连接检测 // 只有连接成功的插件才会被注册,连接失败的插件不会被注册 // 异步无限重连,只有连接成功了才注册 func registerPlugin(msgType messageType, factory configFactory) error { if factory == nil { return fmt.Errorf("factory cannot be nil") } // 创建实例 instance := factory() ctx := context.Background() // 开启异步连接,无限重连直到成功 go func() { retryInterval := 2 * time.Second maxInterval := 30 * time.Second for { select { case <-ctx.Done(): g.Log().Errorf(ctx, "❌ [%s] 注册被取消", msgType) return default: // 尝试连接(使用Reconnect方法) if err := instance.reconnect(ctx); err == nil { // 连接成功,注册插件 if err := defaultPluginManager.register(msgType, instance); err != nil { g.Log().Errorf(ctx, "❌ [%s] 注册插件失败: %v", msgType, err) instance.close(ctx) } else { g.Log().Infof(ctx, "✅ [%s] 插件注册成功", msgType) } return } // 连接失败,记录日志并等待重试 g.Log().Warningf(ctx, "⚠️ [%s] 连接失败,%v 后重试...", msgType, retryInterval) select { case <-time.After(retryInterval): // 增加重试间隔,但不超过最大值 retryInterval *= 2 if retryInterval > maxInterval { retryInterval = maxInterval } case <-ctx.Done(): g.Log().Errorf(ctx, "❌ [%s] 注册被取消", msgType) return } } } }() return nil } // register 注册插件(内部方法) func (m *pluginManager) register(msgType messageType, instance messageUtil) error { m.mu.Lock() defer m.mu.Unlock() m.instances[msgType] = instance return nil } // GetMsgPlugin 获取消息队列插件 func GetMsgPlugin(msgType messageType) (messageUtil, error) { defaultPluginManager.mu.RLock() instance, ok := defaultPluginManager.instances[msgType] defaultPluginManager.mu.RUnlock() if !ok { return nil, fmt.Errorf("unsupported message type: %s", msgType) } return instance, nil } // GetSupportedTypes 获取所有已注册的插件类型 func GetSupportedTypes() []messageType { defaultPluginManager.mu.RLock() defer defaultPluginManager.mu.RUnlock() types := make([]messageType, 0, len(defaultPluginManager.instances)) for t := range defaultPluginManager.instances { types = append(types, t) } return types }