package outbox import ( "context" "errors" kafkabus "github.com/LoveLosita/smartflow/backend/infra/kafka" ) // EventPublisher 是通用事件发布能力接口。 // // 职责边界: // 1. 只暴露“发布事件”这一件事,隐藏底层 outbox/kafka 实现细节; // 2. 业务层只依赖该接口,避免直接耦合具体引擎结构体; // 3. 该接口不承诺“立即消费成功”,只承诺“事件已入队或返回错误”。 type EventPublisher interface { Publish(ctx context.Context, req PublishRequest) error } // EventBus 是 outbox 异步总线的门面对象。 // // 设计目的: // 1. 对外提供“发布 + 注册处理器 + 启停”三类最小能力; // 2. 对内复用 Engine,不重复实现状态机和调度逻辑; // 3. 为后续引入更多事件类型提供统一扩展点。 type EventBus struct { engine *Engine } // NewEventBus 创建通用事件总线。 // // 说明: // 1. 当 kafka.enabled=false 时返回 nil,调用方可直接降级为同步模式; // 2. 该方法只创建基础设施对象,不自动注册任何业务事件处理器; // 3. 业务事件处理器注册应由上层在启动阶段显式完成,避免隐式副作用。 func NewEventBus(repo *Repository, cfg kafkabus.Config) (*EventBus, error) { engine, err := NewEngine(repo, cfg) if err != nil { return nil, err } if engine == nil { return nil, nil } return &EventBus{engine: engine}, nil } // RegisterEventHandler 注册事件处理器。 // // 失败语义: // 1. bus 未初始化时直接返回错误; // 2. event_type 为空或 handler 为空时返回错误; // 3. 重复注册时采用“后者覆盖前者”并打日志(由 Engine 负责)。 func (b *EventBus) RegisterEventHandler(eventType string, handler MessageHandler) error { if b == nil || b.engine == nil { return errors.New("event bus is not initialized") } return b.engine.RegisterEventHandler(eventType, handler) } // Publish 发布事件到 outbox 队列。 // // 关键语义: // 1. 返回 nil 仅表示“已写入 outbox 成功”; // 2. 真正 Kafka 投递与业务消费由后台异步循环完成; // 3. 若返回 error,表示本次入队失败,调用方应按业务策略决定是否重试/降级。 func (b *EventBus) Publish(ctx context.Context, req PublishRequest) error { if b == nil || b.engine == nil { return errors.New("event bus is not initialized") } return b.engine.Publish(ctx, req) } // Start 启动事件总线后台循环(dispatch + consume)。 func (b *EventBus) Start(ctx context.Context) { if b == nil || b.engine == nil { return } b.engine.Start(ctx) } // Close 关闭事件总线资源(producer/consumer)。 func (b *EventBus) Close() { if b == nil || b.engine == nil { return } b.engine.Close() }