Files
smartmate/backend/services/active_scheduler/dao/connect.go
Losita 6843c7efac Version: 0.9.71.dev.260504
后端:
1.阶段 5 task 服务边界落地
- 新增 cmd/task 与 services/task/{dao,rpc,sv},承载 task zrpc、tasks 表迁移和 task outbox 消费边界
- 新增 gateway/client/task、shared/contracts/task 和 task port,gateway /api/v1/task/* 切到 task zrpc client
- 将 task.urgency.promote.requested handler / relay / retry loop 迁入 cmd/task,单体 worker 不再消费 task outbox
- 保留单体 Agent 残留 task 查询的 publish-only 写入能力,避免迁移期 task 事件丢失
- active-scheduler task facts / due job scanner 切到 task RPC,并移除启动期 tasks 表依赖检查
- 更新阶段 5 文档,记录 task 切流点、旧实现保留、跨域 DB 依赖缩减和下一轮建议
- 补充 task rpc 示例配置
2026-05-05 00:00:09 +08:00

127 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dao
import (
"fmt"
outboxinfra "github.com/LoveLosita/smartflow/backend/infra/outbox"
coremodel "github.com/LoveLosita/smartflow/backend/model"
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// OpenDBFromConfig 创建 active-scheduler 服务自己的数据库句柄。
//
// 职责边界:
// 1. 只迁移 active-scheduler 拥有的 trigger / preview / job / session 表和本服务 outbox 表;
// 2. 不迁移 task、schedule、agent、notification 或 user/auth 表,避免独立进程越权管理其它服务模型;
// 3. 返回的 *gorm.DB 供服务内主链路、due job scanner 和 outbox consumer 复用。
func OpenDBFromConfig() (*gorm.DB, error) {
host := viper.GetString("database.host")
port := viper.GetString("database.port")
user := viper.GetString("database.user")
password := viper.GetString("database.password")
dbname := viper.GetString("database.dbname")
dsn := fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
user, password, host, port, dbname,
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return nil, err
}
if err = db.AutoMigrate(
&coremodel.ActiveScheduleJob{},
&coremodel.ActiveScheduleTrigger{},
&coremodel.ActiveSchedulePreview{},
&coremodel.ActiveScheduleSession{},
); err != nil {
return nil, fmt.Errorf("auto migrate active-scheduler tables failed: %w", err)
}
if err = autoMigrateActiveSchedulerOutboxTable(db); err != nil {
return nil, err
}
if err = ensureRuntimeDependencyTables(db); err != nil {
return nil, err
}
return db, nil
}
// autoMigrateActiveSchedulerOutboxTable 只迁移 active-scheduler 服务自己的 outbox 物理表。
//
// 职责边界:
// 1. 只负责 active-scheduler.outbox 对应表,不碰其它服务 outbox
// 2. 让独立 active-scheduler 服务可以单独发布 trigger 并消费 active_schedule.triggered
// 3. 若后续调整 outbox 表名,只改 service catalog不在这里硬编码。
func autoMigrateActiveSchedulerOutboxTable(db *gorm.DB) error {
cfg, ok := outboxinfra.ResolveServiceConfig(outboxinfra.ServiceActiveScheduler)
if !ok {
return fmt.Errorf("resolve active-scheduler outbox config failed")
}
if err := db.Table(cfg.TableName).AutoMigrate(&coremodel.AgentOutboxMessage{}); err != nil {
return fmt.Errorf("auto migrate active-scheduler outbox table failed for %s (%s): %w", cfg.Name, cfg.TableName, err)
}
return nil
}
type runtimeDependencyTable struct {
Name string
Reason string
}
// ensureRuntimeDependencyTables 在服务启动期校验迁移期共享主库依赖。
//
// 职责边界:
// 1. 只检查表是否存在,不 AutoMigrate、不补列、不修改任何跨域表
// 2. 把 active-scheduler 运行时仍然需要的 agent / notification outbox 边界显式化;
// 3. 若部署顺序、库权限或表结构归属不满足,启动阶段直接 fail fast避免第一次 trigger 才反复重试。
func ensureRuntimeDependencyTables(db *gorm.DB) error {
if db == nil {
return fmt.Errorf("active-scheduler runtime dependency check failed: db is nil")
}
for _, table := range activeSchedulerRuntimeDependencyTables() {
if err := ensureTableExists(db, table); err != nil {
return err
}
}
return nil
}
// ensureTableExists 只做存在性探测。
//
// 职责边界:
// 1. 不负责判断字段是否兼容,字段级契约由拥有该表的服务迁移脚本保证;
// 2. 不负责自动修复缺失表,避免 active-scheduler 越权创建其它服务的数据模型;
// 3. 返回错误会阻止服务启动,让部署问题尽早显现。
func ensureTableExists(db *gorm.DB, table runtimeDependencyTable) error {
if table.Name == "" {
return fmt.Errorf("active-scheduler runtime dependency table name is empty: %s", table.Reason)
}
if db.Migrator().HasTable(table.Name) {
return nil
}
return fmt.Errorf("active-scheduler runtime dependency table missing: %s (%s)", table.Name, table.Reason)
}
// activeSchedulerRuntimeDependencyTables 列出迁移期运行仍需共享主库访问的外部表。
//
// 说明:
// 1. active-scheduler 自有表在 OpenDBFromConfig 内迁移,这里只放跨域依赖;
// 2. notification outbox 表名来自 service catalog避免和 outbox 多表路由配置漂移;
// 3. schedule 与 task 事实读取已切到 RPC后续切到 agent/notification RPC 或 read model 后,应继续移除对应表依赖。
func activeSchedulerRuntimeDependencyTables() []runtimeDependencyTable {
notificationOutboxTable := "notification_outbox_messages"
if cfg, ok := outboxinfra.ResolveServiceConfig(outboxinfra.ServiceNotification); ok && cfg.TableName != "" {
notificationOutboxTable = cfg.TableName
}
return []runtimeDependencyTable{
{Name: "agent_chats", Reason: "trigger 生成 preview 后预建主动调度会话"},
{Name: "chat_histories", Reason: "trigger 生成 preview 后写入会话首屏消息"},
{Name: "agent_timeline_events", Reason: "trigger 生成 preview 后写入主动调度时间线卡片"},
{Name: notificationOutboxTable, Reason: "ShouldNotify=true 时投递 notification.feishu.requested 事件"},
}
}