1
0
forked from erp-dev/erp
Files
erpnew/docs/notifier_module_design.md

5.0 KiB
Raw Blame History

Notifier 模块实现说明

本文档面向后端维护者,描述 notifier 模块当前的实现决策、已落地范围与后续扩展注意事项。

1. 当前阶段

notifier 现已从第一阶段的“Notifier 直接绑定 event_key”升级为第二阶段的“Notifier + NotifierRoute”结构。

这样做的原因是:

  • 一个通知器可能需要绑定多个事件
  • 同一事件需要支持按任务分类路由
  • 同一事件可能同时发往多个不同通知器
  • 后续还可能出现更多路由维度

因此当前模块职责被拆成两层:

  • Notifier:通知渠道配置、模板配置、启停控制
  • NotifierRoute:事件匹配与业务路由规则

2. 当前范围

本阶段已实现:

  • 独立 appnotifier
  • Celery task 化投递
  • 企业微信 webhook 渠道
  • message_api 渠道ERP 作为调用方)
  • 模板化内容渲染
  • Admin 可配置
  • NotifierRoute 事件路由
  • mission 相关事件按任务分类路由

本阶段仍未做:

  • 旧模块静态通知逻辑迁移
  • 通知投递明细表
  • 数据库级别审计

3. 核心模型

3.1 Notifier

  • config
  • description

当前 Notifier 已不再直接持有 event_key

NotifierRoute 负责“何时发、发给谁”:

  • merchant

  • notifier 其中:

  • mission_category = null 表示该事件的通配路由

  • Notifier 在同商户下 name 唯一

  • NotifierRoute 在同一 notifier + event_key + mission_category 下唯一

  • NotifierRoute 额外限制同一 notifier + event_key 只能有一条通配路由

当前 dispatch_notification_event(...) 的匹配规则为:

  1. 先按 merchant + event_key + route.is_enabled=True + notifier.is_enabled=True 查路由
    • 也允许匹配通配路由
  2. 如果 payload 中没有 category_id
    • 只匹配通配路由
  3. 如果同一个 Notifier 同时命中专用路由和通配路由
    • 只保留一条
    • 优先保留专用路由
  • 同一通知器不重复发送

5. 当前调用链

通知链路如下:

  1. mission.services 在事务提交后发 signal

6. 已接入的事件

当前 mission 已接入:

  • mission.unreplied
  • mission.unreplied 并非由业务 signal 直接触发,而是由后台每分钟一次的扫描任务按任务对象上的提醒配置触发

7. 日志策略

  • 没有命中任何可用路由
  • 路由命中成功
  • backend 发送成功
  • 单个通知发送失败

当前已增加 route 维度日志,重点字段包括:

  • event_key
  • merchant_id
  • route_id
  • route_mission_category_id
  • notifier_id

8. Admin 现状

当前后台提供两个对象:

并且:

Notifier inline 场景下route 的 merchant 会自动同步为当前 notifier 的商户,避免管理人员重复录入。

11. Mission 上的未回复提醒状态字段

当前未回复提醒的核心状态全部放在 Mission 对象自身:

  • notify_if_unreplied
  • unreplied_notify_interval_minutes
  • unreplied_notify_max_count
  • unreplied_notify_sent_count
  • unreplied_last_notified_at

这样做的原因是:

  • 配置和运行态统一放在任务对象上,最容易排查
  • 不需要额外的提醒计划表或提醒历史表就能支撑当前需求
  • 最大提醒次数和上次提醒时间都能直接在任务详情中观察到 这样旧配置不会因为结构调整而丢失。

10. 测试覆盖重点

当前测试已覆盖:

  • 模板渲染
  • backend 发送
  • 路由按事件匹配
  • 分类专用路由优先于通配路由
  • 无专用路由时回退到通配路由
  • 任务事件 handler 正常入队

11. 当前风险与注意点

11.1 当前只对 mission 做了分类路由

当前 mission_category 是显式写进 NotifierRoute 的业务字段。
这适合当前目标,但如果未来要扩展到其它业务模型的复杂路由,可能需要更抽象的路由条件模型。

11.2 config 仍是自由 JSON

后台录入错误仍可能在发送时才暴露。
当前依赖日志排查,后续可增加更强校验。

11.3 模板校验仍在发送期暴露

template_key 如果写错,会在渲染阶段报错并记录日志。
后续可在 admin 或 model clean 中增强校验。

12. message_api 渠道边界

message_api 的定位是:

  • ERP / notifier 只负责渲染结构化消息模板并调用内部 message_api
  • ERP 不直接管理企业微信 corp_idsecretaccess_token
  • ERP 不直接调用企业微信官方 API

当前实现方式:

  • message_api channel 使用 .json 模板
  • backend 会校验模板渲染结果是否符合 text/news 结构
  • 之后由 notifier 作为 HTTP client 调用 MESSAGE_API_BASE_URL

这意味着:

  • agent_id / agent_ids 仍然属于 channel 级配置
  • 企业微信系统级凭据属于 message_api 服务自身,不属于 ERP 配置

13. 当前结论

当前 notifier 已具备:

  • 通知器配置
  • 路由配置
  • 分类分发
  • 任务事件按分类路由
  • 管理后台操作支持
  • 日志与测试保障

这已经足以支撑你当前提出的“所有任务事件都支持按任务分类路由”的要求。