10 Migration Inventory
本文件记录 handlers -> services -> modules 的当前迁移现状,用于支持 10-service-to-module-migration 的 M1 盘点阶段。
当前观察结论
ticket- 已具备较强的模块化基础
handlers/ticket_handler.go通过ticketHandlerService接口工作- 已存在模块交付适配层
modules/ticket/delivery/handler_adapter.go - 但旧
services/TicketService仍保留,并且本身也在包装ticketmodule 与 orchestration - 当前规则:HTTP handler 应依赖
modules/ticket/delivery.HandlerService - 结论:这是最适合优先完成“handler 直接面向 module adapter”的模块
agentservices/AgentService已明显成为兼容层- 核心读写已走
modules/agent/application.Service - handler-facing DTO 与 transfer runtime contract 已回收到
modules/agent/delivery agentQueues已移除;剩余在线客服兼容缓存回填、后台清理调度与 service 装配已拆成独立 runtime helper/adapter/assembly,且后台任务只在 server runtime 装配点显式启动workspace/session transfer等下游 service 已改为依赖窄接口,而不再直接绑定*AgentServiceapp/serverruntime/router 也不再对外暴露*services.AgentService字段,只保留 handler-facing 与业务专用依赖workspace handler与websocket hub进一步切到工作台/转接接口,app/server对WorkspaceService/SessionTransferService的 concrete 暴露继续收缩- 当前规则:HTTP handler 应依赖
modules/agent/delivery.HandlerService - 结论:属于“module 已落地,但 runtime 兼容状态尚未收口”的类型
analyticsservices/StatisticsService基本是 module facade- 核心统计能力已走
modules/analytics/application.Service - 还保留事件总线订阅和 DTO 映射的兼容包装
app/serverruntime 已不再对外暴露*services.StatisticsService字段,仅保留 handler-facing contract 与局部 wiring- 结论:迁移风险低,适合作为后续收口样板
routing / session transferservices/SessionTransferService已注入modules/routing/delivery.SessionTransferAdapter- session assignment 同步已改走
modules/conversation/deliveryruntime adapter,不再直接更新Session - transfer / waiting 的系统消息写入已改走
modules/conversation/deliveryruntime adapter,不再直接写Message - waiting queue 的读取、新增、取消、查询、转态同步,以及 transfer record 写入已收口到 routing module 状态机
- waiting -> transferred 与 transfer record 写入已纳入同一事务,不再依赖事务后的补写同步
- 取消 waiting queue 时的系统消息写入也已切到
modules/conversation/deliveryruntime adapter,减少 legacyMessage直写分支 - 会话转接触发的 ticket assignment 同步已改走
modules/ticket/deliveryruntime adapter,不再直接写Ticket/TicketStatus - agent load 调整已改走
modules/agent/deliveryruntime adapter,原先由 handler contract 反向依赖services引起的 import cycle 已被移除 - websocket 通知依赖已收窄为
sessionTransferNotifier,不再把WebSocketHub作为 service 内部 concrete 字段保存 - 会话读取入口已切到
modules/conversation/delivery.RuntimeService.LoadTransferSession(...),SessionTransferService不再在主流程里直接预加载Session - 默认装配下
LoadTransferSession(...)的 adapter 错误会直接上抛,不再静默回退到 legacy DB 查询,避免掩盖 conversation runtime 故障 - 加入等待队列时的会话 active/unassigned 同步也已切到
modules/conversation/delivery.RuntimeService.SyncWaitingAssignment(...) app/server主运行时已改用NewSessionTransferServiceWithAdapters(...)一次性装配 routing/ticket/conversation/agent runtime adapters,减少可变 setter 装配面- 旧的 setter 式 adapter 注入已从活跃代码路径移除,默认装配方式固定为显式构造
- waiting queue 的公开查询与后台处理读取现已统一复用同一条 service 内部查询路径,减少 adapter/fallback 与默认分页规则分叉
- transfer history 的公开查询也已收口到同一条 service 内部 routing-first 入口,避免顶层重复分支继续扩散
- 当前 waiting record 的读取与“仅 active waiting 才参与后续流程”的判定也已收口到统一 helper,固定
ErrRecordNotFound语义 - waiting record 的取消更新逻辑也已抽成独立 helper,事务主流程继续向 orchestration 收敛
- ticket assignment 的 legacy fallback 分支也已拆出内部 helper,状态迁移与状态历史补写不再直接堆在主同步流程里
- waiting -> transferred 的 legacy 更新也已压到独立 helper,waiting record 状态补写不再散落在主流程分支里
- 转接主流程内剩余的 adapter/fallback 分支已收口到私有 helper,
executeTransfer/addToWaitingQueue现主要保留流程编排职责 - 但主流程仍强依赖
gorm.DB、AgentService和旧会话模型 - 结论:属于“局部接入 module adapter,但主流程仍是 legacy service”的高风险混合区
ai- 同时存在旧
services/AIService、EnhancedAIService、OrchestratedAIService OrchestratedAIService已是modules/ai/application.QueryOrchestrator的适配层- handler 已开始收口到
modules/ai/delivery.HandlerService AIAssembly已去掉未消费的LegacyService *services.AIService暴露,仅保留 handler-facing contract、runtime-facingAIServiceInterface与 WeKnora state- 结论:迁移重点是继续压缩 legacy
AIServiceInterface的 handler 可见面,只保留 runtime 兼容用途
- 同时存在旧
legacy handler-only capabilitiessatisfaction、csat public、macro、app integration、custom field、shift、suggestion、gamification等能力尚未模块化- 这批 handler 现在已改为依赖
handlers包内定义的最小接口,而不再把*services.*concrete type 暴露到app/serverruntime/router surface - 结论:虽然还不属于
services -> modules迁移完成项,但已完成一轮“装配面收口”,可减少 concrete legacy service 在顶层 runtime 的扩散
message router- 轻量 runtime 与主 runtime 都还需要
Start/Stop生命周期,但 HTTP 层只关心平台统计读取 - 现已抽出
services.MessageRouterRuntime,app/server与handlers.MessageHandler不再暴露 concrete*services.MessageRouter MetricsHandler的无用 message router 注入已移除
- 轻量 runtime 与主 runtime 都还需要
realtime runtime internalsWebSocketHub/WebRTCService属于运行态装配细节,不应继续作为Runtime/RealtimeRuntime的公开 concrete 字段暴露- 现已收口为内部
Run()启动依赖与 gateway adapter 装配细节,外部只保留RealtimeGateway/RTCGateway/MessageRouterRuntime
slaSLAHandler早已在内部按最小方法集工作,但此前app/server顶层装配仍暴露*services.SLAService- 现已把 handler contract 显式提升为
handlers.SLAService/handlers.SLATicketReader ticketdelivery.ReaderServiceAdapter直接复用为工单读取依赖,顶层 runtime/router 不再暴露 concrete*services.SLAService
customerservices/CustomerService已经是modules/customer/application.Service的轻量 facade- HTTP handler 只消费请求/响应 DTO 与兼容方法,核心业务已经下沉到 module application + infra repository
app/serverruntime 已不再对外暴露*services.CustomerService字段,且 customer handler 装配已直接切到modules/customer/delivery.NewHandlerService(db),不再经由 legacy facade 中转- 结论:handler 主路径已直接贴近 module;旧 facade 主要只为历史调用者保留 DTO 兼容
automationservices/AutomationService已经把核心触发器与执行查询下沉到modules/automation/application.Service- legacy service 主要保留 event bus subscriber 注册、测试兼容 helper 与 module 装配
app/serverruntime/router 已不再对外暴露*services.AutomationService字段,且 automation handler 装配已直接切到modules/automation/delivery.NewHandlerService(db)- 结论:handler 主路径已直接贴近 module;旧 service 主要只保留 event bus subscriber 与测试兼容 glue
knowledge- 已存在
modules/knowledge/application,但此前缺少 Gorm repository 与 handler-facing delivery contract - 旧
services/KnowledgeDocService主要承接 CRUD 与 tag/category DTO,适合改成 module facade app/serverruntime 已不再对外暴露*services.KnowledgeDocService字段,knowledge handler 装配已直接切到modules/knowledge/delivery.NewHandlerServiceWithProvider(db, ...),不再经由 legacy facade 中转modules/knowledge/infra已补齐KnowledgeIndexJob的 Gorm 持久化仓储,module delivery 也已支持按 runtime 注入 provider- 结论:knowledge 的 handler/runtime 主路径都已贴近 module;legacy facade 仅保留历史调用兼容
- 已存在
按迁移成熟度分组
A. 已有明显 module facade
ticketagentanalytics
这些模块的共同特点:
- 已有
modules/*/application作为核心业务入口 - 旧
services/*更多承担兼容包装、DTO 映射、runtime glue - 适合优先定义“唯一入口”并冻结旧 service 新增逻辑
B. 已局部接入 module adapter,但主流程仍偏旧
routing / session transferconversation相关 websocket/runtime 路径
这些模块的共同特点:
- module 已存在
- 但核心运行时仍由旧 service 或旧 runtime struct 主导
- 需要先画清 runtime 职责边界,再做 handler/adapter 收口
automation的 handler 已可先行收口,但 runtime 仍需要旧 service 持有 event bus subscriberconversation与routing仍是下一轮最重的运行态迁移区域
C. 多实现并存,需要先确定默认主路径
ai
特点:
- legacy AI service 与 orchestrated AI module 并存
- provider、fallback、enhanced 包装已经很多
- 下一步更像“架构收敛”而不是简单替换调用点
推荐迁移顺序
ticketagentanalyticscustomerautomationknowledgerouting / session transferai
当前高风险点
- 同一个业务能力同时存在 handler interface、legacy service、module service、delivery adapter 多层入口
- 旧 service 中仍混有 runtime 状态与 side effects,导致无法简单替换
ai路径下存在多个“看起来都像主实现”的对象,容易继续分叉routing与conversation仍强依赖旧 websocket / session runtime- 若不继续守护,未模块化但较薄的 legacy handler service 仍可能重新把 concrete type 扩散回
app/serverruntime/router
下一步建议
- 先在
ticket上定义唯一 HTTP 入口应该直连哪个 adapter - 明确
services/*中哪些类型属于:- 兼容 facade
- runtime state holder
- 仍未迁出的真实业务层
- 为
ticket、agent、analytics各拆一个最小任务包
已确认的入口规则
ticket- HTTP handler 入口:
modules/ticket/delivery.HandlerService - 旧
services/TicketService定位:兼容 facade + orchestration side effects 组装
- HTTP handler 入口:
agent- HTTP handler 入口:
modules/agent/delivery.HandlerService - 旧
services/AgentService定位:兼容 facade + runtime state holder
- HTTP handler 入口:
analytics- HTTP handler 入口:
modules/analytics/delivery.HandlerService - 旧
services/StatisticsService定位:兼容 facade + event bus subscriber / DTO mapping glue
- HTTP handler 入口:
customer- HTTP handler 入口:
modules/customer/delivery.HandlerService - 旧
services/CustomerService定位:兼容 facade + DTO mapping + module application 装配
- HTTP handler 入口:
automation- HTTP handler 入口:
modules/automation/delivery.HandlerService - 旧
services/AutomationService定位:兼容 facade + event bus subscriber + module application 装配
- HTTP handler 入口:
knowledge- HTTP handler 入口:
modules/knowledge/delivery.HandlerService - runtime 装配入口:
modules/knowledge/delivery.NewHandlerServiceWithProvider(db, ...) - 旧
services/KnowledgeDocService定位:兼容 facade + module application / repository 装配
- HTTP handler 入口:
routing / session transfer- HTTP handler 入口:
modules/routing/delivery.HandlerService - 旧
services/SessionTransferService定位:兼容 facade + runtime glue + legacy transfer orchestration
- HTTP handler 入口:
conversation / websocket runtime- websocket 持久化入口:
modules/conversation/delivery.WebSocketMessageWriter services/WebSocketHub定位:runtime connection hub,不再自定义 conversation 私有持久化接口
- websocket 持久化入口:
ai- HTTP handler 入口:
modules/ai/delivery.HandlerService AIAssembly定位:显式区分 handler-facing AI contract 与 runtime-facingAIServiceInterface
- HTTP handler 入口:
已确认的兼容职责边界
services/TicketService- 允许保留:旧调用方兼容入口、event bus / automation / satisfaction 等 side effect 组装、module command/orchestrator 的装配
- 不应新增:新的 HTTP handler 直接依赖、新业务规则主入口、绕过
modules/ticket/delivery.HandlerService的写路径
services/AgentService- 允许保留:旧调用方兼容入口、少量兼容方法
- 不应新增:新的 HTTP handler 直接依赖、脱离
modules/agent/application.Service的核心业务写路径
services/StatisticsService- 允许保留:旧调用方兼容入口、event bus 订阅注册、DTO 映射、统计后台任务调度
- 不应新增:新的 HTTP handler 直接依赖、绕过
modules/analytics/application.Service的主统计读写路径
services/CustomerService- 允许保留:旧调用方兼容入口、DTO 映射、
modules/customer/application.Service与 repository 的装配 - 不应新增:新的 HTTP handler 直接依赖、绕过
modules/customer/application.Service的核心客户读写路径
- 允许保留:旧调用方兼容入口、DTO 映射、
services/AutomationService- 允许保留:旧调用方兼容入口、event bus subscriber 注册、测试辅助方法、
modules/automation/application.Service的装配 - 不应新增:新的 HTTP handler 直接依赖、绕过
modules/automation/application.Service的触发器和执行记录主入口
- 允许保留:旧调用方兼容入口、event bus subscriber 注册、测试辅助方法、
services/KnowledgeDocService- 允许保留:旧调用方兼容入口、DTO 映射、
modules/knowledge/application.Service与 repository 的兼容装配 - 不应新增:新的 HTTP handler 直接依赖、绕过
modules/knowledge/application.Service的文档 CRUD 主入口
- 允许保留:旧调用方兼容入口、DTO 映射、
services/SessionTransferService- 允许保留:旧调用方兼容入口、AgentService/通知接口/AIService 协调、转接实时通知与 legacy transfer orchestration
- 不应新增:新的 HTTP handler 直接依赖、绕过 routing module 的 waiting/transfer record 读写规则
services/WebSocketHub- 允许保留:连接管理、广播、协议消息分发、对 AI/transfer 的 runtime glue
- 不应新增:新的 conversation 私有持久化接口、绕过
modules/conversation/delivery.WebSocketMessageWriter的消息落库路径
services/AIServiceInterface及 legacy AI types- 允许保留:WebSocketHub、MessageRouter、SessionTransferService 等 runtime 兼容调用面
- 不应新增:新的 HTTP handler 直接依赖、继续扩散为默认 AI 主入口
当前自动化守护
scripts/check-module-boundaries.sh- 校验
ticket/agent/analytics/customer/automation/knowledge/routing/ai的 handler constructor 必须依赖modules/*/delivery.HandlerService - 校验 router/runtime 对这八个模块的注入类型必须停留在 handler-facing contract,并校验
knowledgeruntime 必须直接通过 module delivery 装配,以及conversation的 websocket persistence 入口必须走 module delivery adapter - 校验
satisfaction/macro/app integration/custom field/shift/suggestion/gamification等薄 handler 依赖必须停留在 handler-local contract,避免app/server顶层装配回退暴露 concrete legacy service - 校验
workspace/websocket transfer等新增收窄点必须依赖WorkspaceOverviewReader、SessionTransferRuntime等接口,并禁止app/serverruntime/router 回退暴露若干 concrete legacy service - 目的:先锁住已完成迁移的入口,避免回退到 handler 直连具体旧 service
- 校验