Version: 0.9.69.dev.260504

后端:
1. 阶段 4 active-scheduler 服务边界落地,新增 `cmd/active-scheduler`、`services/active_scheduler`、`shared/contracts/activescheduler` 和 active-scheduler port,迁移 dry-run、trigger、preview、confirm zrpc 能力
2. active-scheduler outbox consumer、relay、retry loop 和 due job scanner 迁入独立服务入口,gateway `/active-schedule/*` 改为通过 zrpc client 调用
3. gateway 目录收口为 `gateway/api` + `gateway/client`,统一归档 userauth、notification、active-scheduler 的 HTTP 门面和 zrpc client
4. 将旧 `backend/active_scheduler` 领域核心下沉到 `services/active_scheduler/core`,清退旧根目录活跃实现,并补充 active-scheduler 启动期跨域依赖表检查
5. 调整单体启动与 outbox 归属,`cmd/all` 不再启动 active-scheduler workflow、scanner 或 handler

文档:
1. 更新微服务迁移计划,将阶段 4 active-scheduler 标记为首轮收口完成,并明确下一阶段进入 schedule / task / course / task-class
This commit is contained in:
Losita
2026-05-04 21:01:00 +08:00
parent abe3b4960e
commit 4d9a5c4d30
66 changed files with 2048 additions and 466 deletions

View File

@@ -11,6 +11,7 @@
3. 阶段 1.5 / 1.6 已完成:`backend/services/llm``backend/services/rag` 已经是当前 canonical 入口,`backend/infra/llm``backend/infra/rag``.go` 旧实现已删除。
4. 阶段 2 已完成:`user/auth` 已经从 Gin 单体抽成 `cmd/userauth` + `services/userauth` 的 go-zero zrpc 服务边界gateway 只保留 user HTTP 入口、鉴权、额度门禁和轻量转发。
5. 阶段 3 `notification` 服务化已完成实现、code review 修复和真实 smoke不要再把 outbox、llm-service、rag-service 或 user/auth 当成未完成待办。
6. 阶段 4 `active-scheduler` 服务化已完成首轮收口独立进程、zrpc、服务级 outbox consumer / relay / retry loop、gateway 门面和代码归属已经切到新边界。
本计划遵守两个硬原则:
@@ -68,11 +69,12 @@ Gin Gateway 只做边缘层职责:
4. 直接维护服务内部重试与投递状态。
5. 直接维护用户黑名单、JWT 签发、token 额度账本这类 user/auth 内部状态。
当前阶段 2 切流点:
当前 gateway 切流点:
1. `/api/v1/user/*``backend/gateway/userapi` 承载 HTTP 入口,核心能力通过 `backend/gateway/userauth``cmd/userauth` zrpc。
1. `/api/v1/user/*``backend/gateway/api/userauth` 承载 HTTP 入口,核心能力通过 `backend/gateway/client/userauth``cmd/userauth` zrpc。
2. `gateway/middleware` 的 JWT 鉴权和 token quota guard 只调 `userauth`,不直接读写 `users`、Redis 黑名单或额度缓存。
3. zrpc client 放在 gateway/service 调用侧目录,不放进 `cmd``cmd` 只负责进程入口和装配,不承载跨服务 client 语义
3. `notification``active-scheduler` 等跨服务 zrpc client 统一放在 `backend/gateway/client/<service>`HTTP 门面统一放在 `backend/gateway/api`
4. zrpc client 不放进 `cmd``cmd` 只负责进程入口和装配,不承载跨服务 client 语义。
### 3.2 服务层
@@ -96,9 +98,11 @@ gozero 服务负责领域能力:
>
> 当前状态:`llm-service` / `rag-service` 这两个边界已经先做成 `backend/services/*` 的服务内模块,调用仍由 `backend/cmd/start.go` 在同一进程内装配,不是 gozero 独立进程。
>
> 当前状态:`user/auth` 已经完成 go-zero zrpc 独立进程拆分,是阶段 2 样板。服务端在 `backend/services/userauth`,进程入口在 `backend/cmd/userauth`gateway client 在 `backend/gateway/userauth`。
> 当前状态:`user/auth` 已经完成 go-zero zrpc 独立进程拆分,是阶段 2 样板。服务端在 `backend/services/userauth`,进程入口在 `backend/cmd/userauth`gateway HTTP 门面在 `backend/gateway/api/userauth`gateway client 在 `backend/gateway/client/userauth`。
>
> 当前状态:`notification` 已经完成阶段 3 拆分。服务端在 `backend/services/notification`,进程入口在 `backend/cmd/notification`gateway client 在 `backend/gateway/notification`,服务级 outbox consumer 和 retry loop 已随服务入口迁出。
> 当前状态:`notification` 已经完成阶段 3 拆分。服务端在 `backend/services/notification`,进程入口在 `backend/cmd/notification`gateway client 在 `backend/gateway/client/notification`,服务级 outbox consumer 和 retry loop 已随服务入口迁出。
>
> 当前状态:`active-scheduler` 已经完成阶段 4 首轮收口。服务端在 `backend/services/active_scheduler`,进程入口在 `backend/cmd/active-scheduler`gateway HTTP 门面在 `backend/gateway/api`gateway client 在 `backend/gateway/client/activescheduler`。
### 3.3 事件层
@@ -145,7 +149,7 @@ gozero 服务负责领域能力:
| 1.6 | 再抽 rag-service已完成 | 已完成,`backend/services/rag` 作为当前 canonical 入口 | `go test ./...` + memory retrieve / rerank smoke |
| 2 | 先拆 user/auth已完成 | 已完成,阶段 2 样板 commit 点userauth zrpc、gateway userapi、JWT/黑名单/额度治理、启动与迁移边界已收口 | 已完成注册/登录/刷新/并发 refresh/登出/鉴权/token quota smoke |
| 3 | 再拆 notification已完成 | 已完成,`cmd/notification` + `services/notification` zrpc / outbox consumer / retry loop 已收口,旧单体实现已删除;是否 commit 等用户明确要求 | 已完成 notification E2E smoke + worker-only smoke |
| 4 | 再拆 active-scheduler | 预览生成和确认链路通过 gozero 服务跑通后 commit | dry-run / preview / confirm smoke |
| 4 | 再拆 active-scheduler(已完成首轮收口) | 已完成,`cmd/active-scheduler` + `services/active_scheduler` zrpc / outbox consumer / retry loop / gateway 门面已收口;是否 commit 等用户明确要求 | 已完成 dry-run / trigger / preview ready smokeconfirm 仍建议单独做写入型 smoke |
| 5 | 再拆 schedule / task / course / task-class | 每个领域完成一次切流就 commit 一次 | schedule/task/course/task-class 回归 + 全链路 smoke |
| 6 | 再拆 agent / memory | agent 编排服务、memory 支撑服务和后台 worker 独立后 commit | agent chat / SSE / memory extract / memory retrieve smoke |
| 7 | Gin Gateway 收口 | 网关不再直接碰核心业务表后 commit | Gateway 路由、鉴权、组合逻辑 smoke |
@@ -311,8 +315,8 @@ flowchart LR
1. 新增 `backend/cmd/userauth/main.go` 作为 userauth 独立进程入口。
2. 新增 `backend/services/userauth/**`,承载注册、登录、刷新 token、登出、JWT 签发/校验、黑名单、token 额度治理和 token 记账幂等。
3. 新增 `backend/gateway/userapi/**`,承载 `/api/v1/user/register``/api/v1/user/login``/api/v1/user/refresh-token``/api/v1/user/logout` 的 HTTP handler。
4. 新增 `backend/gateway/userauth/**`,承载 gateway 侧 zrpc client 和 gRPC 错误反解。
3. 新增并归档到 `backend/gateway/api/userauth/**`,承载 `/api/v1/user/register``/api/v1/user/login``/api/v1/user/refresh-token``/api/v1/user/logout` 的 HTTP handler。
4. 新增并归档到 `backend/gateway/client/userauth/**`,承载 gateway 侧 zrpc client 和 gRPC 错误反解。
5. 新增 `backend/gateway/middleware/**`,把 JWT 鉴权和 token quota guard 改成调用 userauth不再直接碰 users 表或 Redis 黑名单细节。
6. 新增 `backend/shared/contracts/userauth``backend/shared/ports`,只放跨层契约和端口接口。
7. 拆分 MySQL / Redis 初始化和 AutoMigrate 边界:`cmd/all``ConnectCoreDB` / `InitCoreRedis`,只迁单体残留域;`cmd/userauth` 自己迁 `users``user_token_usage_adjustments`
@@ -379,7 +383,7 @@ flowchart LR
本轮收口状态2026-05-04
1. `cmd/notification` 已承载 notification zrpc 启动、DB 迁移、服务级 outbox consumer 和重试扫描。
2. `backend/services/notification` 已收进 DAO、model、sv、rpc、飞书 provider 和 outbox handlergateway 通过 `backend/gateway/notification` zrpc client 调用。
2. `backend/services/notification` 已收进 DAO、model、sv、rpc、飞书 provider 和 outbox handlergateway 通过 `backend/gateway/client/notification` zrpc client 调用。
3. 主动调度侧只写入 `notification.feishu.requested`publisher 侧只注册事件归属到 `notification`,不再启动单体 notification consumer。
4.`backend/notification`、旧 DAO/model 和旧 `service/events/notification_feishu.go` 已删除review 发现的 sending 租约恢复和 RPC timeout 边界已修复。
5. 真实 smoke 已通过:`notification_outbox_messages.id=3` 已从 `pending` 推进到 `consumed``smartflow.notification.outbox` 已出现 `outbox_id=3`,对应 `notification_records` 生成并按未启用通道进入 `skipped`
@@ -413,6 +417,15 @@ flowchart LR
3. confirm / apply smoke。
4. `mock_now` 和幂等回归测试。
本轮收口状态2026-05-04
1. `cmd/active-scheduler` 已承载 active-scheduler zrpc 启动、DB 迁移、服务级 outbox consumer、relay、retry loop 和 due job scanner。
2. `backend/services/active_scheduler` 已收进 DAO、sv、rpc 和主动调度核心逻辑;复杂领域流程统一下沉到 `backend/services/active_scheduler/core`,旧 `backend/active_scheduler` 活跃实现已移除。
3. gateway HTTP 门面已统一到 `backend/gateway/api`active-scheduler、notification、userauth 的 zrpc client 已统一到 `backend/gateway/client/*`
4. 单体 `cmd/start.go` 不再启动 active-scheduler workflow / scanner / handlergateway 的 `/api/v1/active-schedule/*` 只做鉴权、参数绑定、超时和 zrpc 转发。
5. 迁移期仍共享主库读取 / 写入 task、schedule、agent 会话与 notification outbox 相关表active-scheduler 启动时会显式检查这些运行时依赖表,后续阶段 5/6 再逐步切成 RPC 或 read model。
6. 已完成真实 smoke`trigger -> active_scheduler_outbox_messages -> consume -> preview ready` 闭环通过,当前 trigger 没有出现单体误消费导致的 dead handler。
---
### 4.9 阶段 5再拆 schedule / task / course / task-class
@@ -509,15 +522,14 @@ flowchart LR
当前建议按这个顺序推进:
注:阶段 1.5 / 1.6 / 2 / 3 已完成`notification` 已完成实现、code review 修复和真实 smoke不再作为下一轮待办。
注:阶段 1.5 / 1.6 / 2 / 3 / 4 已完成首轮收口`notification` `active-scheduler` 都不再作为“未拆服务”待办。
1. 以阶段 1 的服务级 outbox 为当前基线,不再回头做共享 outbox 方案。
2. 保持 `backend/services/llm``backend/services/rag` 为 canonical 入口,不再把它们写成待办。
3. 保持 `backend/services/userauth` + `cmd/userauth` 为阶段 2 样板,不再回头恢复 Gin 单体 user/auth。
4. 下一步进入阶段 4,优先切 `active-scheduler`
5. 然后切 schedule / task / course / task-class
6. 再切 agent / memory把聊天编排和记忆链路独立出去
7. 最后把 Gin 收口成纯 Gateway。
4. 下一步进入阶段 5,优先切 schedule / task / course / task-class逐步替换 active-scheduler 当前的跨域 DB 依赖
5. 再切 agent / memory把聊天编排、主动调度会话复跑和记忆链路独立出去
6. 最后把 Gin 收口成纯 Gateway
一句话总结:
@@ -702,11 +714,11 @@ SmartFlow-Agent/
> 当前目录到目标目录的映射:
>
> 1. `backend/services/userauth/*` 已经是阶段 2 终态样板;旧 `backend/api/user.go`、`backend/service/user.go`、`backend/dao/user.go`、`backend/model/user.go`、`backend/model/auth.go`、`backend/auth/jwt_handler.go`、`backend/middleware/token_handler.go`、`backend/middleware/token_quota_guard.go`、`backend/routers/routers.go` 不再作为活跃实现。
> 2. `backend/gateway/userapi/*` 是 user HTTP 入口,`backend/gateway/userauth/*` 是 userauth zrpc client二者都属于 gateway 边缘层。
> 2. `backend/gateway/api/userauth/*` 是 user HTTP 入口,`backend/gateway/client/userauth/*` 是 userauth zrpc client二者都属于 gateway 边缘层。
> 3. `backend/service/*.go` 这批现有业务逻辑,后面要分别迁到各自服务根目录下的 `sv/`。
> 4. `backend/service/agentsvc/*` 和 `backend/newAgent/*`,后面要收束到 `backend/services/agent/sv/` + `internal/{prompt,graph,stream,tool,session,router}`。
> 5. `backend/services/notification/*` 已经是阶段 3 终态样板;`backend/cmd/notification` 是独立进程入口,`backend/gateway/notification` 是 gateway 侧 zrpc client`backend/shared/contracts/notification` 只放跨层契约;旧 `backend/notification/*`、旧 DAO/model 和旧 `service/events/notification_feishu.go` 不再作为活跃实现。
> 6. `backend/active_scheduler/*`,后面要收束到 `backend/services/active-scheduler/`,其中 `graph/selection/feedbacklocate/apply/job` 归入 `internal/`
> 5. `backend/services/notification/*` 已经是阶段 3 终态样板;`backend/cmd/notification` 是独立进程入口,`backend/gateway/client/notification` 是 gateway 侧 zrpc client`backend/shared/contracts/notification` 只放跨层契约;旧 `backend/notification/*`、旧 DAO/model 和旧 `service/events/notification_feishu.go` 不再作为活跃实现。
> 6. `backend/services/active_scheduler/*` 已经是阶段 4 当前样板;`backend/cmd/active-scheduler` 是独立进程入口,`backend/gateway/client/activescheduler` 是 gateway 侧 zrpc client`backend/services/active_scheduler/core` 承载迁移期领域核心;旧 `backend/active_scheduler/*` 不再作为活跃实现
> 7. `backend/memory/*`,后面要收束到 `backend/services/memory/`;当前 `memory/service/*` 只是迁移过渡态,终态还是按 `sv/` 或 `internal/` 拆开。
>
> 说明 4`shared` 先保留 `events` 和少量跨服务底座型 `infra`。以后如果真的出现跨服务 DTO / 枚举 / 常量,再新增 `contracts` 一类目录,但不要把 `dao`、`model`、`sv`、`handler` 这类服务私有层塞进去。
@@ -751,7 +763,7 @@ SmartFlow-Agent/
### 6.6 `notification` / `active-scheduler` 的服务内结构
1. `notification` 建议直接收束成更标准的服务内单体壳:外层统一成 `dao/``model/``sv/``handler.go``start.go`,当前的 `runner.go``provider.go``dedupe.go``channel_service.go` 这类细节先保留在服务内部,但后面要逐步并入 `sv/``internal/notification/`,不要长期挂成一串平级文件。
2. `active-scheduler` 建议收束成同类服务壳,外层只保留 `dao/``model/``sv/``handler.go``start.go`,把 `graph``selection``feedbacklocate``apply``job` 这些复杂流程统一下沉到 `internal/`
2. `active-scheduler` 已先收束成 `cmd/active-scheduler` + `services/active_scheduler/{dao,rpc,sv,core}``core` 是迁移期领域核心承载处,后续若不再被单体 agent 会话复跑路径引用,可继续改成 `internal/{graph,selection,preview,feedbacklocate,apply,job,trigger}`
3. 这样做的目标,是让后续每个服务的阅读方式都更接近你熟悉的 seckill 风格,而不是把一个服务拆成十几个平级目录。
### 6.7 每个服务的典型用例
@@ -760,11 +772,11 @@ SmartFlow-Agent/
| 服务 | 典型用例 | 结构收束建议 | 不允许的改法 |
| --- | --- | --- | --- |
| `user/auth` | 注册、登录、刷新、登出、JWT 签发、黑名单、token 额度门禁、token 记账幂等 | 已完成:`cmd/userauth` + `services/userauth/{sv,dao,model,internal/auth,rpc}`gateway 侧是 `gateway/userapi` + `gateway/userauth` | 不要恢复旧 Gin user/auth 实现;不要让 gateway 直连 users 表、Redis 黑名单或额度缓存;不要把 zrpc client 放进 `cmd` |
| `user/auth` | 注册、登录、刷新、登出、JWT 签发、黑名单、token 额度门禁、token 记账幂等 | 已完成:`cmd/userauth` + `services/userauth/{sv,dao,model,internal/auth,rpc}`gateway 侧是 `gateway/api/userauth` + `gateway/client/userauth` | 不要恢复旧 Gin user/auth 实现;不要让 gateway 直连 users 表、Redis 黑名单或额度缓存;不要把 zrpc client 放进 `cmd` |
| `course` | 课程导入、图片解析、课表校验、课程落表,图片解析走 `llm-service` | `handler.go` / `sv/` / `dao/` / `model/` / `internal/{parse,import,conflict,adapter}/` | 不要把课程解析代码写成网关临时脚本 |
| `task-class` | 任务类创建/更新、items 批量 upsert、嵌入时间同步 | `handler.go` / `sv/` / `dao/` / `model/` / `internal/{convert,batch,item}/` | 不要把批处理拼装沉到 handler 里,也不要让 agent 直接改库 |
| `notification` | 消费 `notification.feishu.requested`、写通知记录、幂等、重试、provider 投递 | `start.go` / `handler.go` / `sv/` / `dao/` / `model/` / `internal/{provider,runner,dedupe,channel,retry}/` | 不要把通知投递逻辑散回 worker 或 gateway |
| `active-scheduler` | `trigger -> dry-run -> preview -> confirm`、建议生成、反馈定位;候选选择走 `llm-service` | `start.go` / `handler.go` / `sv/` / `dao/` / `model/` / `internal/{graph,selection,preview,feedbacklocate,apply,job,trigger}/` | 不要把 graph/selection 继续长成对外平级框架 |
| `active-scheduler` | `trigger -> dry-run -> preview -> confirm`、建议生成、反馈定位;候选选择走 `llm-service` | 已完成首轮收口:`cmd/active-scheduler` + `services/active_scheduler/{dao,rpc,sv,core}`;下一步把跨域 DB 访问替成服务契约后,可把 `core` 进一步改为 `internal/{graph,selection,preview,feedbacklocate,apply,job,trigger}` | 不要把 graph/selection 散回 gateway 或旧根目录 |
| `schedule` | 正式日程所有权、查询、删除、应用命令 | `start.go` / `handler.go` / `sv/` / `dao/` / `model/` / `internal/{command,event,conflict}/` | 不要让 gateway 直接写 schedule 表 |
| `task` | 任务新增、完成/撤销、任务池查询、紧急性平移 | `start.go` / `handler.go` / `sv/` / `dao/` / `model/` / `internal/{policy,event,urgency}/` | 不要把 task 的状态机塞进 agent 或 schedule |
| `llm-service` | 统一模型调用、provider 路由、流式输出、重试、限流、审计 | `start.go` / `handler.go` / `sv/` / `model/` / `internal/{provider,router,stream,quota,audit}/` | 不要把业务 prompt、状态机、工具编排塞进模型出口 |
@@ -866,10 +878,10 @@ graph TD
3. 阶段 1 已完成,当前 outbox 基线是服务级表、服务级 topic、服务级 consumer groupworker 仍在单体内装配,后续随对应服务迁出。
4. 阶段 2 已完成,`user/auth` 已经是样板服务,不要再把它当成下一轮待办。
5. 阶段 3 `notification` 已完成实现、code review 修复和真实 smoke`llm-service``rag-service` 也已完成,不要重新当成待办。
6. 下一轮默认从阶段 4 `active-scheduler` 开始;它后续要回到更像 seckill 的服务内单体壳
6. 阶段 4 `active-scheduler` 已完成首轮收口;后续不要再把它当成“未拆服务”,除非是在补契约测试或继续替换跨域 DB 访问
7. `shared` 只保留跨进程契约和少量跨服务底座不承载业务逻辑、DAO、模型或状态机。
8. 如果后续要改目录,必须先回答“这个文件属于哪一个典型用例”,回答不清楚就先别动结构。
9. 当前文档已经可以作为切对话基线;后续代理默认按本文件推进。现阶段的迁移基线入口是 `backend/cmd/api``backend/cmd/worker``backend/cmd/all`,它们只是当前仓库的启动壳,不是终态。`backend/cmd/userauth` 是阶段 2 的独立服务入口,`backend/cmd/notification` 是阶段 3 的独立服务入口。终态仍然是“一个服务一个独立 `main.go`”,只在出现新的契约风险、边界变化或业务语义变化时再重新讨论架构。
9. 当前文档已经可以作为切对话基线;后续代理默认按本文件推进。现阶段的迁移基线入口是 `backend/cmd/api``backend/cmd/worker``backend/cmd/all`,它们只是当前仓库的启动壳,不是终态。`backend/cmd/userauth` 是阶段 2 的独立服务入口,`backend/cmd/notification` 是阶段 3 的独立服务入口`backend/cmd/active-scheduler` 是阶段 4 的独立服务入口。终态仍然是“一个服务一个独立 `main.go`”,只在出现新的契约风险、边界变化或业务语义变化时再重新讨论架构。
### 6.10 启动方式与进程模型
@@ -992,7 +1004,7 @@ graph TD
这段用于避免后续代理重复踩阶段 2 已经纠偏过的问题。
1. 阶段 3 `notification` 已完成;后续起步默认是阶段 4 `active-scheduler`,不是 outbox、llm-service、rag-service、user/authnotification。
1. 阶段 3 `notification` 和阶段 4 `active-scheduler` 已完成首轮收口;后续起步默认是阶段 5 `schedule / task / course / task-class`,不是 outbox、llm-service、rag-service、user/authnotification 或 active-scheduler
2. 主代理负责 leader先读必要文档和代码拆任务关键阻塞任务自己做子代理只能承担并行、明确、非阻塞的侧翼任务。
3. 如果确实有会影响切分方向的不确定点,先总结成拍板点问用户;文档已经写清楚的内容不要重复问。
4. 查库一律用 `docker exec`。MySQL / Redis 都按这个规则走;不直接用本机客户端绕过容器。
@@ -1036,7 +1048,7 @@ graph TD
1. `backend/cmd/userauth/main.go` 是 userauth 独立进程入口。
2. `backend/services/userauth` 拥有 user/auth 核心业务、DAO、模型、JWT、黑名单、额度治理、zrpc server 和 token 记账幂等表。
3. `backend/gateway/userapi` 是 HTTP user 入口,`backend/gateway/userauth` 是 zrpc client`backend/gateway/middleware` 只调 userauth 做鉴权和额度门禁。
3. `backend/gateway/api/userauth` 是 HTTP user 入口,`backend/gateway/client/userauth` 是 zrpc client`backend/gateway/middleware` 只调 userauth 做鉴权和额度门禁。
4. `backend/shared/contracts/userauth``backend/shared/ports` 只承载跨层契约,不承载服务私有业务实现。
5. `cmd/all` 不再迁 `users``cmd/userauth` 自己迁 `users``user_token_usage_adjustments`
6. 完整本地 smoke 需要同时启动 `cmd/all``cmd/userauth`
@@ -1045,13 +1057,22 @@ graph TD
1. `backend/cmd/notification/main.go` 是 notification 独立进程入口,负责 DB 迁移、zrpc server、notification outbox consumer 和 retry loop 的统一生命周期。
2. `backend/services/notification` 拥有 notification 核心业务、DAO、模型、飞书 provider、幂等、投递记录状态机、重试扫描和 outbox handler。
3. `backend/gateway/notification` 是 gateway 侧 zrpc clientgateway 只保留 notification HTTP 入口、鉴权和轻量组合逻辑,不再直连 notification DAO/service。
3. `backend/gateway/client/notification` 是 gateway 侧 zrpc clientgateway 只保留 notification HTTP 入口、鉴权和轻量组合逻辑,不再直连 notification DAO/service。
4. `backend/shared/contracts/notification``backend/shared/ports` 只承载跨层契约和端口接口,不承载服务私有业务实现。
5. notification 内部是 `userauth` 同款最小手搓 zrpc 框架,不使用 goctl 自动脚手架;`rpc` 只保留 `NewServer``cmd/notification` 管理 signal、outbox consumer、retry loop 和 server 生命周期。
6.`backend/notification/*`、旧 `backend/dao/notification_channel.go`、旧 `backend/model/notification_channel.go` 和旧 `backend/service/events/notification_feishu.go` 已删除;若 `backend/notification` 目录壳仍存在,它不参与编译,也不作为活跃实现。
7. notification outbox consumer 已迁入独立服务边界并处理 `notification.feishu.requested`,覆盖 payload/version 校验、dead/retry/consumed 状态推进和毒消息回退。
8. 已完成真实 smoke`notification_outbox_messages` 可从 `pending` 推进到 `consumed`Kafka `smartflow.notification.outbox` 可看到对应 outbox 消息,`notification_records` 可生成幂等记录并按通道状态进入预期状态。
阶段 4 当前基线:
1. `backend/cmd/active-scheduler/main.go` 是 active-scheduler 独立进程入口,负责 DB 迁移、zrpc server、active-scheduler outbox consumer、relay、retry loop 和 due job scanner 的统一生命周期。
2. `backend/services/active_scheduler` 拥有 active-scheduler DAO、rpc、sv 和领域核心;核心流程当前在 `backend/services/active_scheduler/core`,旧 `backend/active_scheduler` 不再作为活跃实现存在。
3. `backend/gateway/api` 是 HTTP 门面统一目录,`backend/gateway/client/activescheduler` 是 gateway 侧 zrpc client。
4. `backend/shared/contracts/activescheduler``backend/shared/ports` 只承载跨层契约和端口接口,不承载服务私有业务实现。
5. `cmd/all` 不再启动 active-scheduler workflow / scanner / handler完整本地 smoke 需要同时启动 `cmd/all``cmd/userauth``cmd/notification``cmd/active-scheduler`
6. 迁移期仍共享主库访问 task、schedule、agent 会话和 notification outbox 相关表active-scheduler 启动时做依赖表检查,后续由 schedule/task/agent 拆分继续缩小这条共享边界。
---
## 7. 风险与回退
@@ -1121,6 +1142,6 @@ graph TD
处理:
1. 以当前编译入口和路由装配为准:`gateway/userapi` + `gateway/userauth` + `services/userauth` 是阶段 2 当前样板。
1. 以当前编译入口和路由装配为准:`gateway/api/userauth` + `gateway/client/userauth` + `services/userauth` 是阶段 2 当前样板。
2. 任何 user/auth 新能力先放进 `services/userauth`gateway 只做 HTTP 适配和 respond 响应。
3. 如果 user/auth 调用失败,先查 `cmd/userauth` 是否启动、zrpc endpoint 是否正确、服务内 MySQL/Redis 是否可连,不要把逻辑搬回 gateway。