- backend: FastAPI + SQLAlchemy 2.0(async) + asyncpg + Alembic - 7 API routes: auth/me/articles/sources/bookmarks/subscriptions/admin - models: User/Source/Article/Bookmark/Subscription/ApiToken - services: RSS fetcher (feedparser) + Tencent TMT translator with quota + cache + local NLLB fallback - workers: APScheduler + asyncio pipeline (fetch -> dedupe -> insert -> translate) - seed scripts: create_user, seed_sources (5 RSS: Reuters/BBC/Al Jazeera/NHK/DW) - frontend: Vue 3 + Vite + Naive UI + Pinia + vue-router - pages: Login, Feed (24h), ArticleDetail, Sources, Bookmarks, AdminSources - deploy: docker-compose (postgres/redis/api/worker/frontend/caddy) - docs: README, DEPLOY, architecture, acceptance
2.3 KiB
2.3 KiB
架构设计
对应方案 v0.1 的实现版本。
模块边界
| 模块 | 路径 | 职责 |
|---|---|---|
| API | backend/app/api/ |
HTTP 路由,处理鉴权 / 入参 / 出参 |
| 业务 | backend/app/services/ |
抓取、翻译、领域逻辑 |
| Worker | backend/app/workers/ |
后台调度、pipeline |
| 数据 | backend/app/models/ |
SQLAlchemy ORM |
| 迁移 | backend/alembic/ |
数据库 schema 版本 |
| 前端 | frontend/src/ |
Vue 3 + Naive UI |
数据流
Source (DB)
│
▼
Scheduler (cron / interval)
│
▼
RSSFetcher.fetch() ── HTTP GET ──► upstream RSS
│
▼
FetchedItem list
│
▼ (url_hash UNIQUE 去重)
Article INSERT
│
▼ (translation_status='pending')
TranslationService.translate()
├─ Redis cache hit → return
├─ quota check
├─ Tencent TMT (主) ──► 30 天 Redis 月度计数
└─ Local NLLB (降级,需启用)
│
▼
Article UPDATE (title_zh / body_zh_* / status)
关键设计决策
- PostgreSQL:UNIQUE 约束 +
ON CONFLICT DO NOTHING做去重,O(1) 写 - Redis 三用:翻译缓存(30 天 TTL)+ 月度配额(INCRBY)+ 后续限流
- AScheduler 重构 jobs:每天 00:30 从 DB 重新读,运行时新增源自动生效
- 翻译分块:按段落切,单段 > 1500 字符按句号再切,单请求 ≤ 4500 字符(腾讯 TMT 上限)
- 失败退避:某源连续失败 3 次,fetch_interval × 2(封顶 720 分钟),成功一次恢复
- API Token 双轨:网页用短期 JWT(15min)+ refresh(14d);Android 用长期 API Token(可独立撤销)
字段保留
articles 表里这些字段已建,MVP 全部 null,后续 enrichment 阶段直接写值不动表:
category/commentary/entities/sentiment/topic_id/bias
安全
- 密码 bcrypt(cost=12)
- JWT 走 HTTPS-only cookie(网页) / Bearer header(APP)
- 数据库/Redis 不暴露到宿主机
- Caddy 做 TLS 终止
- API 限流(MVP 暂未实现,后续加)
不在 MVP
- ❌ 全文搜索(可用 PG
to_tsvector,MVP 先简单 ILIKE) - ❌ PWA 离线缓存
- ❌ Android 客户端
- ❌ 自动分类/点评/实体识别
- ❌ 主题聚类
- ❌ 跨源立场
- ❌ Telegram 推送
- ❌ i18n(只 zh)
见 DEPLOY.md 跑起来,见 ../README.md 看全貌。