7.1 KiB
7.1 KiB
SuperTodo 任务与通知系统
SuperTodo 是一个基于 Gin + PostgreSQL + Redis + Kafka + Vue 的任务管理与定时通知系统。
当前系统不仅支持基础的任务创建、编辑、完成,还支持通知偏好、通知组、到期提醒、过期提醒、每日摘要、重试与死信队列。
项目概览
系统当前由以下几部分组成:
- 后端 API:
Go + Gin - 前端页面:
Vue 3 + Vite - 关系型存储:
PostgreSQL - 会话与缓存:
Redis - 消息中间件:
Kafka - 邮件投递:
SMTP
核心能力包括:
- 用户注册、登录、刷新令牌、会话管理
- 任务 CRUD
- 用户通知偏好管理
- 通知组管理
- 任务创建、状态变化、即将到期、已过期等事件通知
- 定时调度、异步投递、失败重试、DLQ 死信记录
消息中间件说明
本项目中的消息中间件主要使用 Kafka,它不是装饰性组件,而是通知系统可靠性的核心。
为什么要引入消息中间件
如果任务到期、任务状态变化这类业务事件直接在 HTTP 请求里同步发邮件,会有几个明显问题:
- 接口响应时间变长,用户操作会被外部邮件服务拖慢
- 邮件服务短暂失败时,业务请求容易被连带失败
- 突发高峰时,大量通知会集中压垮投递链路
- 难以实现统一重试、削峰、幂等和死信补偿
引入 Kafka 后,系统会把“业务处理”和“通知投递”拆成两个阶段:
- 业务接口先落库并生成通知事件 / 通知任务
- 通知任务进入 Kafka topic,由后台 worker 异步消费并发送邮件
这样做的结果是:
- API 更快返回
- 投递链路与业务链路解耦
- 可以按批次消费,避免瞬时洪峰
- 可以做失败重试与死信记录
- 可以通过幂等键避免重复发送
本项目里的 Kafka 角色
当前用到的 topic 主要有两个:
todo.tasks- 用于任务事件输出
notification.jobs- 用于通知任务分发
通知相关链路如下:
- 用户创建任务或更新任务
- 系统写入
notification_events - 规则引擎根据事件类型、通知组、用户偏好生成
notification_jobs - dispatcher 将可投递任务写入
notification.jobs - worker 消费消息并发送邮件
- 发送成功写回
sent - 临时失败回到
pending并按指数退避重试 - 超过重试次数或不可重试错误进入
notification_dlq
当前可靠性机制
通知系统当前已经实现:
- 幂等控制:同一事件不会重复生成相同通知任务
- 扫描去重:同一
task_id + event_type + due_at不会被调度器反复重发 - 重试机制:失败任务按退避策略重新投递
- 死信队列:无法恢复的任务进入 DLQ
- 状态可观测:支持查看
pending / sent / dead
系统架构
后端模块
cmd/server- HTTP 服务入口
internal/iam- 登录认证、令牌、会话管理
internal/notification- 通知偏好、通知组、调度器、Kafka dispatcher、worker、SMTP 发送、DLQ 与指标
前端模块
web/src/views/TodoView.vue- 任务列表与编辑
web/src/views/UserSettingsView.vue- 通知偏好设置
web/src/views/NotificationGroupsView.vue- 通知组管理
web/src/views/NotificationDlqView.vue- 死信查看
运行方式
方式一:Docker Compose 启动整套系统
推荐本地联调直接使用容器。
docker compose up -d
启动后默认端口:
- API:
http://localhost:8080 - Kafka UI:
http://localhost:8081 - PostgreSQL:
localhost:5432 - Redis:
localhost:6379 - Kafka:
localhost:29092
健康检查:
curl http://localhost:8080/api/health
方式二:本机运行后端
如果你已经单独启动了 PostgreSQL、Redis、Kafka,也可以直接运行后端:
go run ./cmd/server
常用环境变量:
DATABASE_URL=postgres://todo:todo@localhost:5432/todo?sslmode=disable
REDIS_ADDR=localhost:6379
KAFKA_BROKERS=localhost:29092
KAFKA_TOPIC=todo.tasks
NOTIFY_ENABLED=true
NOTIFY_TOPIC=notification.jobs
NOTIFY_DISPATCH_BATCH=200
NOTIFY_SCHED_TICK_SECONDS=60
NOTIFY_MAX_RETRY=5
NOTIFY_BACKOFF_BASE_SECONDS=30
SMTP_HOST=smtp.qq.com
SMTP_PORT=465
SMTP_USER=your_mail@example.com
SMTP_PASS=your_smtp_password
SMTP_FROM=your_mail@example.com
SMTP_USE_TLS=true
前端运行
cd web
npm install
npm run dev
默认访问地址:
- 前端开发服务:通常为
http://localhost:5173 - 前端请求后端 API:
http://localhost:8080/api/v1
主要数据流
通知系统的数据流可以概括为:
- 业务事件产生
- 如任务创建、任务状态变化、任务即将到期、任务已过期
- 事件入库
- 写入
notification_events
- 写入
- 规则判断
- 判断是否需要通知、通知谁、使用哪个模板
- 偏好过滤
- 过滤订阅状态、语言、时区、免打扰时间
- 生成通知任务
- 写入
notification_jobs
- 写入
- 分发到 Kafka
- 写入
notification.jobs
- 写入
- worker 消费并发送邮件
- 回写状态
sent / pending / dead
- 失败补偿
- 重试或进入 DLQ
常用接口
认证
curl -X POST http://localhost:8080/api/v1/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"demo@example.com","password":"secret123","auto_login":true}'
curl -X POST http://localhost:8080/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"demo@example.com","password":"secret123"}'
任务
curl -X POST http://localhost:8080/api/v1/tasks \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"title":"学习通知系统",
"description":"验证 Kafka 通知链路",
"status":"todo",
"due_at":"2026-03-10T15:30:00Z",
"priority":1,
"tags":["demo","notify"],
"notify_group_ids":[1]
}'
curl http://localhost:8080/api/v1/tasks \
-H 'Authorization: Bearer <token>'
通知偏好
curl -X PUT http://localhost:8080/api/v1/notifications/prefs \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"subscribed":true,
"dnd_start":"",
"dnd_end":"",
"locale":"zh",
"timezone":"Asia/Shanghai",
"daily_summary_enabled":true,
"daily_summary_time":"09:30"
}'
通知组
curl -X POST http://localhost:8080/api/v1/notifications/groups \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"name":"项目通知组",
"emails":["a@example.com","b@example.com"]
}'
通知指标
curl http://localhost:8080/api/v1/notifications/metrics \
-H 'Authorization: Bearer <token>'
数据表说明
当前通知系统的关键表包括:
tasks- 任务主体,包含
notify_group_ids
- 任务主体,包含
user_notification_prefs- 用户通知偏好
notification_groups- 通知组
task_notification_groups- 任务与通知组关系
notification_events- 通知事件日志
notification_jobs- 通知任务队列
notification_attempts- 每次投递尝试记录
notification_dlq- 死信记录