← [ BACK_TO_NOTES ]

MemoFlow · Notification 模块开发笔记

按版本记录从桌面通知到消息事实、投递策略与可靠渠道的设计。

#blog #growing #dev

Notification 模块目标

我希望 Goal、Task、Reminder 等模块产生提醒时,Notification 可以负责把信息呈现给用户。最初先考虑 Windows 右下角通知、声音和应用内弹窗,以后再根据需要接入邮件等渠道。

通知看起来只是“把消息弹出来”,但它实际上还要回答:用户是否应该收到、是否已经投递,以及用户有没有看过。

V1.0.0

先做一个通用通知入口。业务模块不用自己创建 Windows 弹窗,而是把标题、内容和触发信息交给 Notification。

桌面端先比较两种展示方式:

  • 系统通知: 直接利用操作系统的提醒能力,与应用窗口解耦;但用户可能关闭通知权限,交互和样式也受系统限制。
  • 应用自定义弹窗: 样式与交互更可控,适合带按钮的操作;但窗口管理、定位、多显示器和应用关闭后的行为都需要自己处理。

所以 Notification 可以统一内容,具体怎么显示交给设备端。声音、邮件等作为可选渠道,不要求第一版全部实现。

v1.1.0

现在需要让 Notification 与 Schedule 配合。Goal 或 Task 设定提醒时间,由调度侧在时间到达时触发通知请求。

直接“收到事件就弹窗”还存在一个问题:如果用户正好离线,或者事件重复消费,通知可能丢失,也可能被显示两次。单靠 UI 的一次函数调用,不能说明消息已经可靠地产生。

因此准备区分业务发出通知请求和设备实际显示通知。业务请求需要稳定身份与去重依据,界面展示失败也不能反过来删除业务曾经请求过通知这件事。

V2.0.0

这版把 Notification 拆成三个核心层次。

  • Notification Fact: 一条用户能够在消息中心查看、标记已读的消息事实,独立于发送渠道。
  • Workflow / Delivery Policy: 判断这类消息允许通过哪些渠道呈现,应用用户偏好和勿扰时间。
  • Dispatch Outbox / Delivery Attempt: 管实际投递、重试、回执和失败记录。

选择这个结构,是因为通知存在、通知投递成功、用户已读是三个不同状态。例如静默时段禁止弹窗,并不意味着消息中心里不应该有这条提醒。

业务模块只提交受控的 NotificationRequested,Notification 以用户身份和幂等键生成 Fact。Notification Center 展示 Fact 的读取结果,而不是再造一条叫作 “InApp” 的独立消息真值。

v2.1.0

可靠投递还要考虑设备权限、断线和多渠道差异。

后台可以通过 Outbox、lease 和重试推进投递;Desktop 的系统通知需要设备能力与确认反馈;Web 的实时消息需要处理 SSE 断线、游标恢复和补发。一个渠道失败,不代表所有渠道都失败。

勿扰和用户偏好属于投递策略:可以延期或压制某种展示,但不应默认清除 Fact。用户已读只改变收件箱状态,也不证明系统通知真实弹出过。

这些规则需要尽量由 Notification 统一维护,不能由 Goal、Routine 等模块分别写一套“关闭弹窗”的判断。

V3.0.0

现在要让 Notification 只负责通知与用户交互的边界,而不接管原业务状态。

例如用户在提醒里选择“完成任务”,Notification 可以把操作转成有类型的 Action Intent,再交给 Task 的业务命令处理;不能直接修改 Task 表。Schedule / Scheduler 负责触发时机,Routine 决定该不该产生一次提醒,Notification 再判断如何呈现。

这样 Notification Center、桌面通知和 Web 实时入口能共享一条消息事实,又允许每种设备按自己的能力展示。

创建于 2026/3/5 更新于 2026/10/17
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本