SuperTodo 任务与通知系统

SuperTodo 是一个基于 Gin + PostgreSQL + Redis + Kafka + Vue 的任务管理与定时通知系统。
当前系统不仅支持基础的任务创建、编辑、完成,还支持通知偏好、通知组、到期提醒、过期提醒、每日摘要、重试与死信队列。

项目概览

系统当前由以下几部分组成:

  • 后端 APIGo + Gin
  • 前端页面:Vue 3 + Vite
  • 关系型存储:PostgreSQL
  • 会话与缓存:Redis
  • 消息中间件:Kafka
  • 邮件投递:SMTP

核心能力包括:

  • 用户注册、登录、刷新令牌、会话管理
  • 任务 CRUD
  • 用户通知偏好管理
  • 通知组管理
  • 任务创建、状态变化、即将到期、已过期等事件通知
  • 定时调度、异步投递、失败重试、DLQ 死信记录

消息中间件说明

本项目中的消息中间件主要使用 Kafka,它不是装饰性组件,而是通知系统可靠性的核心。

为什么要引入消息中间件

如果任务到期、任务状态变化这类业务事件直接在 HTTP 请求里同步发邮件,会有几个明显问题:

  • 接口响应时间变长,用户操作会被外部邮件服务拖慢
  • 邮件服务短暂失败时,业务请求容易被连带失败
  • 突发高峰时,大量通知会集中压垮投递链路
  • 难以实现统一重试、削峰、幂等和死信补偿

引入 Kafka 后,系统会把“业务处理”和“通知投递”拆成两个阶段:

  1. 业务接口先落库并生成通知事件 / 通知任务
  2. 通知任务进入 Kafka topic由后台 worker 异步消费并发送邮件

这样做的结果是:

  • API 更快返回
  • 投递链路与业务链路解耦
  • 可以按批次消费,避免瞬时洪峰
  • 可以做失败重试与死信记录
  • 可以通过幂等键避免重复发送

本项目里的 Kafka 角色

当前用到的 topic 主要有两个:

  • todo.tasks
    • 用于任务事件输出
  • notification.jobs
    • 用于通知任务分发

通知相关链路如下:

  1. 用户创建任务或更新任务
  2. 系统写入 notification_events
  3. 规则引擎根据事件类型、通知组、用户偏好生成 notification_jobs
  4. dispatcher 将可投递任务写入 notification.jobs
  5. worker 消费消息并发送邮件
  6. 发送成功写回 sent
  7. 临时失败回到 pending 并按指数退避重试
  8. 超过重试次数或不可重试错误进入 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

启动后默认端口:

  • APIhttp://localhost:8080
  • Kafka UIhttp://localhost:8081
  • PostgreSQLlocalhost:5432
  • Redislocalhost:6379
  • Kafkalocalhost: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
  • 前端请求后端 APIhttp://localhost:8080/api/v1

主要数据流

通知系统的数据流可以概括为:

  1. 业务事件产生
    • 如任务创建、任务状态变化、任务即将到期、任务已过期
  2. 事件入库
    • 写入 notification_events
  3. 规则判断
    • 判断是否需要通知、通知谁、使用哪个模板
  4. 偏好过滤
    • 过滤订阅状态、语言、时区、免打扰时间
  5. 生成通知任务
    • 写入 notification_jobs
  6. 分发到 Kafka
    • 写入 notification.jobs
  7. worker 消费并发送邮件
  8. 回写状态
    • sent / pending / dead
  9. 失败补偿
    • 重试或进入 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
    • 死信记录
Description
No description provided
Readme 4 MiB
Languages
Go 67.7%
Vue 16.4%
TypeScript 11.5%
CSS 4.2%
HTML 0.2%