6.2 KiB
6.2 KiB
ARCHITECTURE.md
本文是后端架构入口,说明 Django 项目内部模块边界和调用规则。具体业务需求看 docs/specs/,字段、接口和状态以 docs/contracts/ 为准。
架构原则
- 第一版采用 Django 模块化单体,不拆微服务。
- app 负责边界和数据归属,复杂业务逻辑放 service 层。
- view / serializer 只做请求响应、参数校验和呈现,不承载复杂流程。
- 所有关键动作必须写操作日志或失败记录。
- 飞书回调、AI 输出、定时触发必须幂等。
- 权限必须在接口层和 service 层双重校验。
运行时与依赖版本
第一版新项目采用仍在官方扩展支持期内的 Django 5.2 LTS。Docker / 部署环境固定 Python 3.12.13;本地开发允许 Python 3.11 或 3.12,但提交前必须在部署基线 Python 3.12.13 上跑完整测试。
| 类别 | 版本约定 |
|---|---|
| Python | 部署 3.12.13;本地开发 >=3.11,<3.13 |
| Web 框架 | Django==5.2.15 |
| API 框架 | djangorestframework==3.17.1 |
| ORM / Migration | Django ORM + Django Migrations,跟随 Django==5.2.15 |
| 数据库 | PostgreSQL 18.x,作为唯一数据源;业务表、AI 对话记忆、上下文快照和日志都落同一套 PostgreSQL |
| PostgreSQL 驱动 | psycopg[binary],具体 patch 版本以 requirements.txt 锁定为准 |
| 定时任务 | APScheduler==3.11.2 + django-apscheduler==0.7.0,通过独立 management command 进程运行 |
| AI 接入 | dashscope==1.25.23;百炼管理类 OpenAPI 可选 alibabacloud-bailian20231229==2.13.1 |
| 飞书接入 | lark-oapi==1.6.8 |
| 登录态 / 加解密 | PyJWT==2.13.0 + cryptography==49.0.0 |
| HTTP / 配置 | requests==2.34.2、httpx==0.28.1、python-dotenv==1.2.2 |
| WSGI | gunicorn==26.0.0 |
| Docker 基础镜像 | python:3.12.13-slim-bookworm、postgres:18、nginx:stable-alpine |
Python 依赖基线:
Django==5.2.15
djangorestframework==3.17.1
psycopg[binary]
asgiref==3.11.1
sqlparse==0.5.5
tzdata==2026.2
python-dotenv==1.2.2
requests==2.34.2
httpx==0.28.1
APScheduler==3.11.2
django-apscheduler==0.7.0
dashscope==1.25.23
alibabacloud-bailian20231229==2.13.1
lark-oapi==1.6.8
PyJWT==2.13.0
cryptography==49.0.0
gunicorn==26.0.0
推荐 Django app
| app | 职责 |
|---|---|
accounts |
自定义用户、角色、登录态、飞书身份绑定 |
people |
人员映射、称呼匹配、第一批试用人员 |
drafts |
AiSecretaryAgent、AI 草稿、补充/重说、BotContext、对话消息和草稿状态流转 |
tasks |
事项创建、程经理确认、事项状态流转 |
reminders |
定时提醒、固定周期、触发记录 |
notifications |
飞书通知、通知补发、通知状态 |
feedbacks |
飞书卡片反馈、平台内反馈 |
feishu |
飞书登录、机器人事件、卡片回调、验签 |
prompts |
背景摘要、老板风格提示词、业务规则版本 |
audit |
失败记录、操作日志、模型调用日志 |
分层约定
| 层 | 放什么 | 不放什么 |
|---|---|---|
models |
字段、索引、基础枚举、简单 model 方法 | 跨模块流程、外部 API 调用 |
serializers |
入参出参结构、字段级校验、展示转换 | 状态机、权限决策、飞书调用 |
views |
DRF ViewSet/APIView、权限入口、调用 service | 复杂业务分支、事务主体 |
services |
业务流程、状态流转、事务、幂等、日志 | HTTP 请求细节 |
clients |
阿里百炼、飞书 API 等外部调用封装 | 业务状态修改 |
tasks/commands |
scheduler、补发、批处理命令 | Web 请求上下文依赖 |
核心调用方向
views
-> serializers
-> services
-> models / clients
-> audit logs / failure records
允许:
drafts通过 service 转换为tasks或reminders。tasks/reminders通过 service 创建notifications。notifications通过feishuclient 发送消息。feishu回调通过 service 更新drafts、feedbacks、tasks、reminders。- 所有模块写入
audit。 drafts中的 AI 对话记忆只辅助理解和草稿修订,不替代tasks、reminders、notifications等正式业务表。
避免:
- app 之间直接互相改 model 状态。
- 在 view 里直接调用飞书或模型 API。
- 在 serializer 里做状态流转。
- 在 scheduler 中绕过 service 直接改业务表。
必须写日志的动作
- 飞书登录成功或失败。
- 机器人收到老板消息。
- 非老板私聊机器人。
- AI 生成草稿、解析失败。
- 人工确认、修改、取消草稿。
- 老板点击补充/重说。
- 程经理确认复杂事项。
- 创建事项、创建提醒。
- 发送通知、补发通知、通知失败。
- 接收反馈,尤其是“有问题”反馈。
- 定时提醒触发成功或失败。
- 失败记录处理。
- 背景摘要或老板风格提示词版本启用。
后台任务
定时提醒扫描使用独立进程,不放在 Gunicorn worker 内。生产和测试环境必须保证同一环境同一应用库同时只有一个 scheduler 进程在运行;如果未来多实例部署,需要先引入外部锁、leader election 或数据库级幂等锁。建议命令:
python manage.py run_reminder_scheduler
调度器每次触发前必须检查幂等键:
reminder_id + trigger_time + receiver_id + notification_channel
同一个提醒、同一个触发时间、同一个接收人,只允许生成一条有效通知。