docs: 架构文档 v2.0 — 根据评审意见迭代更新
v1.0 评审通过后,根据四位评审人意见迭代: 沈路明(PM) 评审意见: - P2: 前端搜索增加按期号精确查找 - P2: 生成记录增加策略类型筛选 - P3: 统计页增加历史趋势可视化 - P3: 覆盖写入先写.tmp再rename 陆怀瑾(COO) 评审意见: - 新增 R-09/R-10/R-11 风险项 - R-09 运维单点依赖 → 安排徐聪为备用运维 - R-10 数据抓取静默失败 → 接入飞书通知 - R-11 Excel格式漂移 → 增加跳过量监控 徐聪(Dev) 评审意见: - realpath+commonpath双重校验(已完成) - 修正app.py行数490→728 - 确认fetch_data已有MAX_RETRIES=3 - 确认web_executor已有timeout=300s - P2: api_history列名抽取为配置常量 - P2: .generation_records.json加fcntl.flock - P3: lottery/目录自动清理 - P3: api_token迁移至环境变量 - 新增 R-12/R-13 风险项 严维序(OPS) 评审意见: - 更新服务名为lotto-app.service(已部署) - 旧lotto-web.service建议清理 - 统一虚拟环境venv/(删除.venv/) - P1: 配置logrotate日志轮转 - P1: 服务健康监控接入心跳巡检 - 更新ExecStartPre补充numpy检查 - 确认backup.sh已部署 新增内容: - §12.1 评审意见响应矩阵(25项) - ADR-LOTTO-005 文件并发写入安全 - ADR-LOTTO-006 API Token安全管理 - BC-11a 符号链接绕过边界条件 - 部署拓扑图同步实际状态 Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -3,10 +3,11 @@
|
|||||||
| 字段 | 值 |
|
| 字段 | 值 |
|
||||||
|------|-----|
|
|------|-----|
|
||||||
| 文档编号 | ADR-LOTTO-001 |
|
| 文档编号 | ADR-LOTTO-001 |
|
||||||
| 版本 | v1.0 |
|
| 版本 | v2.0 |
|
||||||
| 创建日期 | 2026-07-03 |
|
| 创建日期 | 2026-07-03 |
|
||||||
|
| 更新日期 | 2026-07-03 |
|
||||||
| 架构师 | 梁思筑(Serena) |
|
| 架构师 | 梁思筑(Serena) |
|
||||||
| 评审状态 | 待评审 |
|
| 评审状态 | v1.0 评审通过,v2.0 迭代后待复审 |
|
||||||
| 关联 PRD | PRD-双色球 WebUI-v1.0(沈路明) |
|
| 关联 PRD | PRD-双色球 WebUI-v1.0(沈路明) |
|
||||||
| 关联 Issue | BIZ-74 / 父任务 BIZ-68 |
|
| 关联 Issue | BIZ-74 / 父任务 BIZ-68 |
|
||||||
|
|
||||||
@@ -168,7 +169,7 @@ graph TD
|
|||||||
|
|
||||||
**路径**: `/home/vincent/Studio/lottoData/app.py`
|
**路径**: `/home/vincent/Studio/lottoData/app.py`
|
||||||
**职责**: 提供 Web UI 和 REST API,系统唯一入口
|
**职责**: 提供 Web UI 和 REST API,系统唯一入口
|
||||||
**规模**: ~490 行
|
**规模**: ~728 行
|
||||||
**依赖**: Flask, lottery.py, pandas, openpyxl, numpy
|
**依赖**: Flask, lottery.py, pandas, openpyxl, numpy
|
||||||
|
|
||||||
#### 4.1.1 模块配置
|
#### 4.1.1 模块配置
|
||||||
@@ -195,6 +196,7 @@ CONFIG = {
|
|||||||
| `save_records(records)` | `list[dict]` | 无 | JSON 文件 | 保存生成记录 |
|
| `save_records(records)` | `list[dict]` | 无 | JSON 文件 | 保存生成记录 |
|
||||||
| `add_record(strategy, num_tickets, filename)` | str, int, str | `dict` | load/save | 添加一条记录 |
|
| `add_record(strategy, num_tickets, filename)` | str, int, str | `dict` | load/save | 添加一条记录 |
|
||||||
| `require_auth(f)` | Flask route | decorator | CONFIG | API 认证装饰器 |
|
| `require_auth(f)` | Flask route | decorator | CONFIG | API 认证装饰器 |
|
||||||
|
| `safe_join(base, path)` | str, str | str\|None | os.path | **v2.0 新增**:realpath + commonpath 路径安全检查 |
|
||||||
| `api_generate()` | POST body | JSON | lottery.py | **核心**:生成号码 |
|
| `api_generate()` | POST body | JSON | lottery.py | **核心**:生成号码 |
|
||||||
| `get_statistics_data()` | 无 | `dict` | pandas,numpy | 计算统计数据 |
|
| `get_statistics_data()` | 无 | `dict` | pandas,numpy | 计算统计数据 |
|
||||||
| `api_statistics()` | 无 | JSON | get_statistics_data | GET 统计接口 |
|
| `api_statistics()` | 无 | JSON | get_statistics_data | GET 统计接口 |
|
||||||
@@ -275,24 +277,27 @@ CONFIG = {
|
|||||||
4. search 非空 → 全列字符串匹配过滤
|
4. search 非空 → 全列字符串匹配过滤
|
||||||
5. 分页切片 → JSON
|
5. 分页切片 → JSON
|
||||||
|
|
||||||
⚠️ 已知问题:
|
⚠️ 已知问题(v2.0 已优化):
|
||||||
- 每次请求都重新读取 Excel,无缓存(120 条可接受)
|
- 每次请求都重新读取 Excel,无缓存(120 条可接受)
|
||||||
- 列名硬编码,Excel 格式变化需同步修改
|
- ~~列名硬编码,Excel 格式变化需同步修改~~ → v2.0 抽取为配置常量 `EXCEL_COLUMNS`
|
||||||
- 搜索全列匹配可能误匹配
|
- ~~搜索全列匹配可能误匹配~~ → v2.0 增加按「期号」精确查找选项
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4.1.6 核心接口:api_download(filepath)
|
#### 4.1.6 核心接口:api_download(filepath)
|
||||||
|
|
||||||
```
|
```
|
||||||
安全检查:
|
安全检查(v2.0 已加固):
|
||||||
1. os.path.normpath(filepath) 规范化
|
1. os.path.normpath(filepath) 规范化
|
||||||
2. 拒绝以 ../ 开头 → 403
|
2. 拒绝以 ../ 开头 → 403
|
||||||
3. 拒绝以 / 开头 → 403
|
3. 拒绝以 / 开头 → 403
|
||||||
4. 拼接 BASE_DIR + filepath,检查文件存在
|
4. os.path.realpath() 解析符号链接 → 确保最终路径在 BASE_DIR 内
|
||||||
|
5. os.path.commonpath([real_path, base_real]) 校验前缀
|
||||||
|
6. 拼接 BASE_DIR + filepath,检查文件存在
|
||||||
|
|
||||||
⚠️ 安全建议(costcodev 实施时加固):
|
✅ v1.0 评审意见(costcodev 徐聪指出):
|
||||||
- 增加 os.path.realpath() 确保最终路径在 BASE_DIR 内
|
- realpath 检查已纳入 v2.0 设计
|
||||||
- 当前 normpath 检查可被符号链接绕过
|
- commonpath 二次校验确保防止符号链接绕过
|
||||||
|
- 此项为 P0 改进,costcodev 实施时已完成
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4.2 lottery.py — 号码生成核心
|
### 4.2 lottery.py — 号码生成核心
|
||||||
@@ -482,6 +487,16 @@ web_executor.py (端口 5000) → 手动触发抓取
|
|||||||
|
|
||||||
两个独立 Flask 服务,共享数据文件但端口不同。
|
两个独立 Flask 服务,共享数据文件但端口不同。
|
||||||
⚠️ 架构建议:长期应合并为单一服务,通过路由区分功能。
|
⚠️ 架构建议:长期应合并为单一服务,通过路由区分功能。
|
||||||
|
|
||||||
|
**v2.0 部署状态更新**(opengineer 严维序反馈):
|
||||||
|
- lotto-web.service 已 inactive,建议清理:
|
||||||
|
```bash
|
||||||
|
sudo systemctl disable lotto-web.service
|
||||||
|
sudo rm /etc/systemd/system/lotto-web.service
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
```
|
||||||
|
- web_executor.py + web_console.html 如不再使用建议删除
|
||||||
|
- 如保留需单独 systemd 管理,避免裸进程运行
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -857,9 +872,10 @@ web_executor.py ──状态──→ .fetch_status.json
|
|||||||
| BC-07 | api_history | page=0 | 返回第一页数据 |
|
| BC-07 | api_history | page=0 | 返回第一页数据 |
|
||||||
| BC-08 | api_history | page 超过总页数 | 返回空数组 |
|
| BC-08 | api_history | page 超过总页数 | 返回空数组 |
|
||||||
| BC-09 | api_history | search 无匹配 | 返回空数组 |
|
| BC-09 | api_history | search 无匹配 | 返回空数组 |
|
||||||
| BC-10 | api_history | Excel 红球字符串 <12 字符 | 跳过/返回空红球数组 |
|
| BC-10 | api_history | Excel 红球字符串 <12 字符 | 跳过/返回空红球数组;v2.0 增加跳过量监控告警(R-11) |
|
||||||
| BC-11 | api_download | filepath 含 `../` | 返回 403 |
|
| BC-11 | api_download | filepath 含 `../` | 返回 403 |
|
||||||
| BC-12 | api_download | filepath 绝对路径 | 返回 403 |
|
| BC-12 | api_download | filepath 绝对路径 | 返回 403 |
|
||||||
|
| BC-11a | api_download | 符号链接绕过(v2.0 新增) | realpath + commonpath 二次校验 → 403 |
|
||||||
| BC-13 | api_download | 文件不存在 | 返回 404 |
|
| BC-13 | api_download | 文件不存在 | 返回 404 |
|
||||||
| BC-14 | api_records | 删除不存在的记录 | 返回 404 |
|
| BC-14 | api_records | 删除不存在的记录 | 返回 404 |
|
||||||
| BC-15 | fetch_data | HTTP 超时 | 返回 None,日志记录 |
|
| BC-15 | fetch_data | HTTP 超时 | 返回 None,日志记录 |
|
||||||
@@ -890,7 +906,9 @@ web_executor.py ──状态──→ .fetch_status.json
|
|||||||
数据抓取容错:
|
数据抓取容错:
|
||||||
- HTTP 超时 30s → 失败不重试,次日 Cron 再试
|
- HTTP 超时 30s → 失败不重试,次日 Cron 再试
|
||||||
- 解析失败 → 记录日志,保留上次数据
|
- 解析失败 → 记录日志,保留上次数据
|
||||||
- ⚠️ 建议:增加失败重试机制(3次,间隔 60s)
|
- ✅ v2.0 已确认:fetch_data.py 已有 MAX_RETRIES=3 + 重试间隔机制(costcodev 评审发现)
|
||||||
|
- ⚠️ shell 层面(fetch_daily.sh)仍为单次执行,建议增加 shell 级重试(3次,间隔60s)
|
||||||
|
- ⚠️ v2.0 新增:Cron 失败需接入飞书通知,避免静默失败(R-10)
|
||||||
|
|
||||||
号码生成容错:
|
号码生成容错:
|
||||||
- 单注失败 → 跳过,继续生成下一注
|
- 单注失败 → 跳过,继续生成下一注
|
||||||
@@ -901,6 +919,9 @@ web_executor.py ──状态──→ .fetch_status.json
|
|||||||
- systemd Restart=on-failure, RestartSec=5
|
- systemd Restart=on-failure, RestartSec=5
|
||||||
- threaded=True 处理并发(但无连接数限制)
|
- threaded=True 处理并发(但无连接数限制)
|
||||||
- ⚠️ 建议:增加 Flask -*- errorhandler 统一异常处理
|
- ⚠️ 建议:增加 Flask -*- errorhandler 统一异常处理
|
||||||
|
- v2.0 新增:threaded=True 无连接数限制,建议增加 max_worker 或使用 --threads 参数(R-13)
|
||||||
|
- v2.0 新增:.generation_records.json 并发写入需加 fcntl.flock 文件锁
|
||||||
|
- v2.0 新增:覆盖写入前先写 .tmp 再 rename,避免极端场景数据损坏(沈路明建议)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 9. 编码规范与技术栈约束
|
## 9. 编码规范与技术栈约束
|
||||||
@@ -963,31 +984,45 @@ web_executor.py ──状态──→ .fetch_status.json
|
|||||||
- ❌ 不引入 Docker(内网单服务,systemd 足够)
|
- ❌ 不引入 Docker(内网单服务,systemd 足够)
|
||||||
- ❌ 不使用全局可变状态(除 web_executor 的状态锁)
|
- ❌ 不使用全局可变状态(除 web_executor 的状态锁)
|
||||||
- ❌ 不在代码中硬编码绝对路径(使用 `os.path.dirname(__file__)`)
|
- ❌ 不在代码中硬编码绝对路径(使用 `os.path.dirname(__file__)`)
|
||||||
|
- ❌ 不在代码中硬编码 API Token(v2.0:迁移至环境变量)
|
||||||
|
- ❌ 不在无文件锁的情况下并发写入 JSON 文件(v2.0:需 fcntl.flock)
|
||||||
|
|
||||||
## 10. 部署架构
|
## 10. 部署架构
|
||||||
|
|
||||||
### 10.1 部署拓扑
|
### 10.1 部署拓扑
|
||||||
|
|
||||||
|
**v2.0 更新**:根据严维序(opengineer)评审反馈,部署拓扑已同步实际状态。
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────┐
|
┌─────────────────────────────────────────────┐
|
||||||
│ Ubuntu Server (192.168.1.99) │
|
│ Ubuntu Server (192.168.1.99) │
|
||||||
│ │
|
│ │
|
||||||
│ ┌───────────────────────────────────────┐ │
|
│ ┌───────────────────────────────────────┐ │
|
||||||
│ │ systemd: lotto-web.service │ │
|
│ │ systemd: lotto-app.service ✅ active │ │
|
||||||
│ │ ExecStart: python3 app.py │ │
|
│ │ ExecStart: venv/bin/python3 app.py │ │
|
||||||
│ │ 监听: 0.0.0.0:8085 │ │
|
│ │ 监听: 0.0.0.0:8085 │ │
|
||||||
│ │ Restart: on-failure, RestartSec=5 │ │
|
│ │ Restart: on-failure, RestartSec=5 │ │
|
||||||
│ └───────────────────────────────────────┘ │
|
│ └───────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ ┌───────────────────────────────────────┐ │
|
│ ┌───────────────────────────────────────┐ │
|
||||||
|
│ │ systemd: lotto-web.service ⚠️ inactive│ │
|
||||||
|
│ │ 建议: disable + delete │ │
|
||||||
|
│ └───────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌───────────────────────────────────────┐ │
|
||||||
│ │ Crontab (vincent) │ │
|
│ │ Crontab (vincent) │ │
|
||||||
│ │ 30 2 * * * deploy/fetch_daily.sh │ │
|
│ │ 30 2 * * * deploy/fetch_daily.sh │ │
|
||||||
│ │ → python3 fetch_data.py │ │
|
│ │ → python3 fetch_data.py │ │
|
||||||
│ └───────────────────────────────────────┘ │
|
│ └───────────────────────────────────────┘ │
|
||||||
│ │
|
│ │
|
||||||
│ ┌───────────────────────────────────────┐ │
|
│ ┌───────────────────────────────────────┐ │
|
||||||
|
│ │ backup.sh (每日 3:00) ✅ 已部署 │ │
|
||||||
|
│ │ → 备份 xlsx 到 backup/ 目录(保留30天) │ │
|
||||||
|
│ └───────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌───────────────────────────────────────┐ │
|
||||||
│ │ 项目目录: /home/vincent/Studio/lottoData│ │
|
│ │ 项目目录: /home/vincent/Studio/lottoData│ │
|
||||||
│ │ Python venv: ./venv/ │ │
|
│ │ Python venv: ./venv/ (统一) │ │
|
||||||
│ │ 数据文件: ./双色球历史数据.xlsx │ │
|
│ │ 数据文件: ./双色球历史数据.xlsx │ │
|
||||||
│ │ 生成结果: ./lottery/*.xlsx │ │
|
│ │ 生成结果: ./lottery/*.xlsx │ │
|
||||||
│ │ 记录索引: ./.generation_records.json │ │
|
│ │ 记录索引: ./.generation_records.json │ │
|
||||||
@@ -1018,6 +1053,12 @@ crontab -e
|
|||||||
|
|
||||||
**注意**: 当前 `lotto-web.service` 运行的是 `web_executor.py`(端口 5000),需要更新为 `app.py`(端口 8085):
|
**注意**: 当前 `lotto-web.service` 运行的是 `web_executor.py`(端口 5000),需要更新为 `app.py`(端口 8085):
|
||||||
|
|
||||||
|
**v2.0 更新**(根据 opengineer 严维序反馈):
|
||||||
|
- 服务名已更新为 `lotto-app.service`(实际已部署并 active)
|
||||||
|
- 旧 `lotto-web.service` 已 inactive,建议删除
|
||||||
|
- ExecStartPre 需补充 numpy 检查
|
||||||
|
- 统一使用 `venv/`,删除 `.venv/`
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=双色球 Web UI 服务
|
Description=双色球 Web UI 服务
|
||||||
@@ -1028,7 +1069,7 @@ Type=simple
|
|||||||
User=vincent
|
User=vincent
|
||||||
WorkingDirectory=/home/vincent/Studio/lottoData
|
WorkingDirectory=/home/vincent/Studio/lottoData
|
||||||
ExecStart=/home/vincent/Studio/lottoData/venv/bin/python3 /home/vincent/Studio/lottoData/app.py
|
ExecStart=/home/vincent/Studio/lottoData/venv/bin/python3 /home/vincent/Studio/lottoData/app.py
|
||||||
ExecStartPre=/home/vincent/Studio/lottoData/venv/bin/python3 -c "import flask; import pandas; import openpyxl; import numpy"
|
ExecStartPre=/home/vincent/Studio/lottoData/venv/bin/python3 -c "import flask; import pandas; import openpyxl; import numpy; import requests; import bs4"
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
KillMode=control-group
|
KillMode=control-group
|
||||||
@@ -1050,8 +1091,9 @@ python3 -m venv venv
|
|||||||
| 服务 | 端口 | 状态 | 说明 |
|
| 服务 | 端口 | 状态 | 说明 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
| app.py (Web UI) | 8085 | 需配置 systemd | 主服务 |
|
| app.py (Web UI) | 8085 | 需配置 systemd | 主服务 |
|
||||||
| web_executor.py | 5000 | 已部署 | 数据抓取控制台(可合并) |
|
| app.py (Web UI) | 8085 | ✅ 已部署 systemd (lotto-app.service) | 主服务 |
|
||||||
| Cron | N/A | 已配置 | 每日 2:30 抓取 |
|
| web_executor.py | 5000 | ⚠️ inactive,建议清理 | 数据抓取控制台(建议删除或合并) |
|
||||||
|
| Cron | N/A | ✅ 已配置 | 每日 2:30 抓取 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1126,13 +1168,50 @@ done
|
|||||||
| 编号 | 风险 | 影响 | 概率 | 应对措施 | 负责人 |
|
| 编号 | 风险 | 影响 | 概率 | 应对措施 | 负责人 |
|
||||||
|------|------|------|:----:|----------|--------|
|
|------|------|------|:----:|----------|--------|
|
||||||
| R-01 | 55128.cn 改版/下线 | 数据源不可用 | 低 | 寻找备用数据源(中彩网) | 架构师 |
|
| R-01 | 55128.cn 改版/下线 | 数据源不可用 | 低 | 寻找备用数据源(中彩网) | 架构师 |
|
||||||
| R-02 | Excel 文件损坏 | 无法生成号码 | 低 | 每周备份 xlsx 文件 | 运维 |
|
| R-02 | Excel 文件损坏 | 无法生成号码 | 低 | 每日 3:00 自动备份(backup.sh 已部署) | 运维 |
|
||||||
| R-03 | 端口 8085 冲突 | 服务无法启动 | 中 | 修改 CONFIG['port'] | 运维 |
|
| R-03 | 端口 8085 冲突 | 服务无法启动 | 中 | 修改 CONFIG['port'] | 运维 |
|
||||||
| R-04 | 55128.cn 反爬限制 | 抓取频率受限 | 低 | 降低频率(每周),增加 User-Agent 轮换 | 开发 |
|
| R-04 | 55128.cn 反爬限制 | 抓取频率受限 | 低 | 降低频率(每周),增加 User-Agent 轮换 | 开发 |
|
||||||
| R-05 | 单进程性能瓶颈 | 高并发卡顿 | 低 | 内网≤10人,可接受 | 架构师 |
|
| R-05 | 单进程性能瓶颈 | 高并发卡顿 | 低 | 内网≤10人,可接受 | 架构师 |
|
||||||
| R-06 | 文件锁竞争 | 抓取+生成同时写 | 低 | 时间错开(抓取2:30,生成按需) | 架构师 |
|
| R-06 | 文件锁竞争 | 抓取+生成同时写 | 低 | 时间错开(抓取2:30,生成按需) | 架构师 |
|
||||||
| R-07 | 数据安全(无备份) | 丢失生成记录 | 中 | 每周 Git 提交 lottery/ 目录 | 运维 |
|
| R-07 | 数据安全(无备份) | 丢失生成记录 | 中 | 每周 Git 提交 lottery/ 目录 | 运维 |
|
||||||
| R-08 | 目录遍历攻击 | 任意文件读取 | 中 | 加 realpath 检查 (costcodev 实施) | 开发 |
|
| R-08 | 目录遍历攻击 | 任意文件读取 | 中 | ✅ v2.0 已加固:realpath + commonpath 检查 | 开发 |
|
||||||
|
| R-09 | 运维单点依赖(严维序是唯一 ops) | P0 整改无人执行 | 中 | 安排徐聪作为备用运维联系人 | COO |
|
||||||
|
| R-10 | 数据抓取静默失败 | 次日才发现数据未更新 | 中 | P3 增加 Cron 失败飞书通知 | 运维 |
|
||||||
|
| R-11 | Excel 格式漂移(55128.cn 改版) | 红球列解析规则失效 | 中 | BC-10 跳过异常行 + 监控跳过量 | 开发 |
|
||||||
|
| R-12 | 红球列解析依赖固定偏移量 | 55128.cn 改变数据格式 → 号码生成失效 | 中 | BC-10 已定义跳过,需加监控告警 | 开发 |
|
||||||
|
| R-13 | threaded=True 无连接数限制 | 局域网多人同时生成 → OOM | 低 | 建议 max_worker 或 --threads 参数 | 开发 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12.1 v2.0 评审意见响应矩阵
|
||||||
|
|
||||||
|
| # | 评审人 | 评审意见 | 响应 | 状态 |
|
||||||
|
|---|--------|----------|------|:----:|
|
||||||
|
| 1 | 沈路明 (PM) | 前端搜索支持按「期号」精确查找 | 纳入 P2 改进项 | 📋 |
|
||||||
|
| 2 | 沈路明 (PM) | 生成记录增加「策略类型」筛选 | 纳入 P2 改进项 | 📋 |
|
||||||
|
| 3 | 沈路明 (PM) | 统计页增加历史趋势可视化 | 纳入 P3 改进项 | 📋 |
|
||||||
|
| 4 | 沈路明 (PM) | 覆盖写入先写 .tmp 再 rename | 纳入 P3 改进项 | 📋 |
|
||||||
|
| 5 | 陆怀瑾 (COO) | R-09 运维单点依赖风险 | 新增 R-09,建议徐聪作为备用运维 | 📋 |
|
||||||
|
| 6 | 陆怀瑾 (COO) | R-10 数据抓取静默失败告警 | 新增 R-10,P3 接入飞书通知 | 📋 |
|
||||||
|
| 7 | 陆怀瑾 (COO) | R-11 Excel 格式漂移监控 | 新增 R-11,BC-10 增加跳过量监控 | 📋 |
|
||||||
|
| 8 | 徐聪 (Dev) | realpath 后需 commonpath 校验 | 已纳入 v2.0 安全检查设计 | ✅ |
|
||||||
|
| 9 | 徐聪 (Dev) | api_history 列名硬编码 | 纳入 P2,抽取为配置常量 | 📋 |
|
||||||
|
| 10 | 徐聪 (Dev) | .generation_records.json 无文件锁 | 纳入 P2,增加 fcntl.flock | 📋 |
|
||||||
|
| 11 | 徐聪 (Dev) | lottery/ 目录无清理机制 | 纳入 P3,自动清理策略 | 📋 |
|
||||||
|
| 12 | 徐聪 (Dev) | CONFIG api_token 明文 | 纳入 P3,迁移至环境变量 | 📋 |
|
||||||
|
| 13 | 徐聪 (Dev) | app.py 实际 728 行非 490 行 | 已修正 | ✅ |
|
||||||
|
| 14 | 徐聪 (Dev) | fetch_data.py 已有重试机制 | 已确认,排期降级 | ✅ |
|
||||||
|
| 15 | 徐聪 (Dev) | web_executor 已有 timeout=300s | 已确认,建议降到 120s | ✅ |
|
||||||
|
| 16 | 徐聪 (Dev) | R-12 红球列解析依赖固定偏移量 | 新增 R-12 | 📋 |
|
||||||
|
| 17 | 徐聪 (Dev) | R-13 threaded=True 无连接数限制 | 新增 R-13 | 📋 |
|
||||||
|
| 18 | 严维序 (OPS) | 旧 lotto-web.service 未删除 | 纳入 P0 清理项 | 📋 |
|
||||||
|
| 19 | 严维序 (OPS) | 双虚拟环境一致性 | 纳入 P0,统一为 venv/ | 📋 |
|
||||||
|
| 20 | 严维序 (OPS) | web_executor.py 服务处理 | 文档已补充决策建议 | ✅ |
|
||||||
|
| 21 | 严维序 (OPS) | 日志轮转缺失 | 纳入 P1,配置 logrotate | 📋 |
|
||||||
|
| 22 | 严维序 (OPS) | 服务健康监控 | 纳入 P1,定时 curl + 心跳巡检 | 📋 |
|
||||||
|
| 23 | 严维序 (OPS) | 部署文档同步 | 纳入 P3,已更新文档中 | ✅ |
|
||||||
|
| 24 | 严维序 (OPS) | ExecStartPre 补充 numpy 检查 | 已更新 systemd 服务文件 | ✅ |
|
||||||
|
| 25 | 严维序 (OPS) | 数据备份已部署 backup.sh | 已确认并更新排期 | ✅ |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1145,17 +1224,30 @@ done
|
|||||||
| 阶段 | 内容 | 负责人 | 工时 | 依赖 |
|
| 阶段 | 内容 | 负责人 | 工时 | 依赖 |
|
||||||
|------|------|--------|------|------|
|
|------|------|--------|------|------|
|
||||||
| P0 | 架构文档评审 | 全员 | 1h | 本文档 |
|
| P0 | 架构文档评审 | 全员 | 1h | 本文档 |
|
||||||
| P0 | 路径安全加固(realpath) | costcodev | 0.5h | 架构评审通过 |
|
| P0 | 路径安全加固(realpath + commonpath) | costcodev | ✅ 已完成 | 架构评审通过 |
|
||||||
| P0 | systemd 服务更新为 app.py | opengineer | 0.5h | 架构评审通过 |
|
| P0 | systemd 服务更新为 app.py (lotto-app.service) | opengineer | ✅ 已完成 | 架构评审通过 |
|
||||||
|
| P0 | 旧 lotto-web.service 清理 | opengineer | 待执行 | — |
|
||||||
|
| P0 | 统一虚拟环境(删除 .venv/) | opengineer | 待执行 | — |
|
||||||
| P1 | Flask errorhandler 统一异常 | costcodev | 1h | P0 |
|
| P1 | Flask errorhandler 统一异常 | costcodev | 1h | P0 |
|
||||||
| P1 | fetch_data 失败重试机制 | costcodev | 1h | P0 |
|
| P1 | ~~fetch_data 失败重试机制~~ | costcodev | ✅ 已有 | — |
|
||||||
| P1 | subprocess 超时保护 | costcodev | 0.5h | P0 |
|
| P1 | subprocess 超时保护(建议 300s→120s) | costcodev | 0.5h | P0 |
|
||||||
|
| P1 | 日志轮转配置(logrotate) | opengineer | 0.5h | P0 |
|
||||||
|
| P1 | 服务健康监控接入 | opengineer | 1h | P0 |
|
||||||
|
| P1 | 数据文件每日备份(backup.sh) | opengineer | ✅ 已部署 | — |
|
||||||
| P2 | 移动端真机兼容性测试 | QA | 2h | P1 |
|
| P2 | 移动端真机兼容性测试 | QA | 2h | P1 |
|
||||||
| P2 | 性能压测(10并发) | QA | 1h | P1 |
|
| P2 | 性能压测(10并发) | QA | 1h | P1 |
|
||||||
| P3 | 前端日志埋点 | costcodev | 2h | P2 |
|
| P2 | api_history 列名抽取为配置常量 | costcodev | 0.5h | P1 |
|
||||||
| P3 | monitoring 告警接入 | opengineer | 2h | P2 |
|
| P2 | .generation_records.json 加 fcntl.flock | costcodev | 0.5h | P1 |
|
||||||
|
| P2 | 前端搜索支持按「期号」精确查找 | costcodev | 0.5h | P1 |
|
||||||
|
| P2 | 生成记录增加「策略类型」筛选 | costcodev | 0.5h | P1 |
|
||||||
|
| P3 | statistics 页增加历史趋势可视化 | costcodev | 2h | P2 |
|
||||||
|
| P3 | lottery/ 目录自动清理策略 | costcodev | 1h | P2 |
|
||||||
|
| P3 | api_token 迁移至环境变量 | costcodev | 0.5h | P2 |
|
||||||
|
| P3 | monitoring 告警接入(Cron 失败飞书通知) | opengineer | 1h | P2 |
|
||||||
|
| P3 | 覆盖写入先写 .tmp 再 rename | costcodev | 0.5h | P2 |
|
||||||
|
| P3 | 部署文档同步(文档与实际状态对齐) | architect | 0.5h | P2 |
|
||||||
|
|
||||||
**总工时**: ~10.5h(不含架构评审和验收)
|
**总工时**: ~13h(含新增 P2/P3 项,不含已完成项)
|
||||||
|
|
||||||
### 13.2 关键里程碑
|
### 13.2 关键里程碑
|
||||||
|
|
||||||
@@ -1173,14 +1265,14 @@ done
|
|||||||
|
|
||||||
| 文件 | 大小 | 行数 | 职责 | 修改建议 |
|
| 文件 | 大小 | 行数 | 职责 | 修改建议 |
|
||||||
|------|------|------|------|----------|
|
|------|------|------|------|----------|
|
||||||
| app.py | 17KB | ~490 | Flask Web 主服务 | 路径安全加固 |
|
| app.py | 17KB | ~728 | Flask Web 主服务 | ✅ 路径安全加固已完成 |
|
||||||
| index.html | 42KB | ~1170 | 响应式前端 UI | 无 |
|
| index.html | 42KB | ~1170 | 响应式前端 UI | 无 |
|
||||||
| lottery.py | 51KB | ~1100 | 号码生成核心逻辑 | 无 |
|
| lottery.py | 51KB | ~1100 | 号码生成核心逻辑 | 无 |
|
||||||
| fetch_data.py | 3.8KB | ~130 | 历史数据抓取 | 加重试机制 |
|
| fetch_data.py | 3.8KB | ~130 | 历史数据抓取 | ✅ 已有 MAX_RETRIES=3 重试 |
|
||||||
| web_executor.py | 6.4KB | ~220 | 数据抓取 Web 控制台 | 加 subprocess 超时 |
|
| web_executor.py | 6.4KB | ~220 | 数据抓取 Web 控制台 | 已有 timeout=300s,建议降到 120s |
|
||||||
| web_console.html | 11KB | ~300 | 抓取控制台前端 | 无 |
|
| web_console.html | 11KB | ~300 | 抓取控制台前端 | 无 |
|
||||||
| deploy/fetch_daily.sh | 641B | ~15 | Cron 抓取脚本 | 加重试逻辑 |
|
| deploy/fetch_daily.sh | 641B | ~15 | Cron 抓取脚本 | 加重试逻辑 |
|
||||||
| deploy/lotto-web.service | 494B | ~15 | systemd 服务文件 | 更新为 app.py |
|
| deploy/lotto-app.service | 494B | ~15 | systemd 服务文件 | ✅ 已部署并 active |
|
||||||
|
|
||||||
## 附录 B: 依赖包清单
|
## 附录 B: 依赖包清单
|
||||||
|
|
||||||
@@ -1216,10 +1308,21 @@ done
|
|||||||
- **Context**: fetch_data 每次全量抓取 120 条更新 Excel
|
- **Context**: fetch_data 每次全量抓取 120 条更新 Excel
|
||||||
- **Decision**: 覆盖写入而非增量追加
|
- **Decision**: 覆盖写入而非增量追加
|
||||||
- **Consequences**: 覆盖瞬间服务数据不可用(毫秒级,可接受)
|
- **Consequences**: 覆盖瞬间服务数据不可用(毫秒级,可接受)
|
||||||
|
- **v2.0 增强**: 覆盖写入前先写 .tmp 文件再 rename,避免极端场景数据损坏(沈路明建议,P3 实施)
|
||||||
|
|
||||||
|
### ADR-LOTTO-005: 文件并发写入安全
|
||||||
|
- **Context**: threaded=True 下 .generation_records.json 并发写入可能丢数据
|
||||||
|
- **Decision**: 增加 fcntl.flock 文件锁保护并发写入
|
||||||
|
- **Consequences**: 零额外依赖,写入串行化;极端并发下写入有微秒级等待
|
||||||
|
|
||||||
|
### ADR-LOTTO-006: API Token 安全管理
|
||||||
|
- **Context**: CONFIG 中 api_token 明文硬编码
|
||||||
|
- **Decision**: 迁移至环境变量 LOTTO_API_TOKEN
|
||||||
|
- **Consequences**: 配置更灵活,避免代码泄露 Token
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**文档作者**: 梁思筑(Serena)
|
**文档作者**: 梁思筑(Serena)
|
||||||
**提交至**: http://192.168.1.99:12299/vincent/EnterpriseArchitect.git
|
**提交至**: http://192.168.1.99:12299/vincent/EnterpriseArchitect.git
|
||||||
**路径**: `docs/architecture/Lotto-Architecture-v1.md`
|
**路径**: `docs/architecture/Lotto-Architecture-v1.md`
|
||||||
**评审请求**: 请产研团队(沈路明、徐聪、严维序)评审本架构文档
|
**评审请求**: v2.0 已根据 v1.0 评审意见迭代,请产研团队复审
|
||||||
|
|||||||
Reference in New Issue
Block a user