chore: baseline — ORM migration + systemd deploy + MCP server + daily check

- ORM migration: models/ops 重构
- deploy: 标准化 systemd timer/service 部署体系
- MCP server: 5 个只读工具(任务/状态/数据集)
- daily check: 数据一致性巡检
- watch: task_watch 后台监控
- kline_daily: 麦蕊优先,时间门禁15:00
- 删除: task_industry_sector, task_sector_features
This commit is contained in:
gao
2026-07-21 16:37:00 +08:00
parent 91e83a3b0b
commit 8f016f25df
94 changed files with 4117 additions and 1176 deletions
+99 -28
View File
@@ -2,7 +2,7 @@
A 股市场数据**定时同步与管理**框架。
`akshare` / `baostock` / 新浪 / 雪球 / 麦蕊智数 等多个数据源接入到 MySQL 库,提供:
`akshare` / `baostock` / 新浪 / 雪球 / 麦蕊智数 等多个数据源接入到 PostgreSQL 库,提供:
- 后台线程调度器(time-based + interval-based,交易日感知)
- 多数据源 + 自动降级 + 健康度监控
- `dataset_registry` 同步状态机(运行中 / 成功 / 失败 / 中断恢复)
@@ -11,15 +11,69 @@ A 股市场数据**定时同步与管理**框架。
> 📖 详细架构说明见 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
## 快速开始
## 运行模式
项目支持两种互斥的运行模式,由环境变量 `RUNTIME_MODE` 控制:
| 模式 | 值 | 适用场景 | 调度方式 |
|---|---|---|---|
| **Docker 模式** | `docker` | `docker compose up` 单容器部署 | 进程内 scheduleruvicorn + daemon thread |
| **systemd 模式** | `systemd` | Linux 宿主机长期运行 | systemd timer/service |
> ⚠️ 两种模式**不能同时启用**,否则同一个 task 会被两边各触发一次,造成状态机抖动和重复 IO。
### Docker 模式
```bash
# 1. 准备环境(首次)
cp .env.example .env # 编辑 .env 填写真实 MySQL 凭据 + XUEQIU_TOKEN
chmod +x start.sh
./start.sh # 自动创建 .venv + 装依赖 + 启动 APIhttp://localhost:8100
cp .env.example .env # 编辑 .env 填写真实 PG 凭据 + XUEQIU_TOKEN + MAIRUI_LICENCE
# 2. 常用命令
# 2. 启动(包含 postgres + market_sync 服务)
docker compose up -d
# 3. 查看日志
docker compose logs -f market_sync
# 4. 手动触发一次任务
docker compose exec market_sync python -m app.entrypoints.cli sync kline_daily
```
Docker 模式下 `RUNTIME_MODE=docker` 已写在 `deploy/docker/docker-compose.yml` 中,容器内会启动进程内 scheduler 负责所有同步任务。
### systemd 模式
```bash
# 1. 准备环境(首次)
cp .env.example .env # 编辑 .env 填写真实 PG 凭据
# 并在 .env 中加上 RUNTIME_MODE=systemd
# 2. 部署 systemd units
sudo bash deploy/systemd/deploy.sh
# 3. 查看 timer
systemctl list-timers market-sync*
# 4. 查看 worker / 任务日志
journalctl -u market-sync -f
journalctl -u market-sync-moneyflow -f
```
systemd 模式下:
- 所有 14 个 task 都由 systemd timer 触发
- `market-sync-worker.service` 会被部署脚本自动 **stop / disable / mask**,避免进程内 scheduler 与 systemd timers 重叠
- 每日 23:00 `market-sync-daily-check.timer` 跑巡检,失败时 POST webhook
### 本地开发模式
```bash
# 1. 准备环境(首次)
cp .env.example .env # 编辑 .env 填写凭据
chmod +x start.sh
# 2. 启动 API + scheduler(默认 docker 行为,等价于本地单进程)
./start.sh # http://localhost:8100
# 3. 常用命令
./start.sh worker # 仅启动调度器(无 web
./start.sh list # 列出所有同步任务
./start.sh sync kline_daily # 手动触发一次(dataset_id 即可)
@@ -27,39 +81,54 @@ chmod +x start.sh
./start.sh datasources # 查看数据源健康度
./start.sh reseed # 重新 seed 默认配置到 config 表
# 3. 一键全量同步(首次接入)
# 4. 一键全量同步(首次接入)
python bin/runall_once.py
# 4. 跑测试
# 5. 跑测试
.venv/bin/pytest tests/ -v
```
## 项目结构
```
app/
├── core/ # 核心抽象(config / db / sync / scheduler / datasource base
├── sources/ # 数据源实现5 个)
├── tasks/ # 同步任务实现(8 个)
├── api/ # FastAPI 管理接口
└── entrypoints/ # 进程入口(cli + worker
bin/ # 一次性脚本
docs/ # 架构文档
tests/ # 单元测试
app/ # 应用源码
├── core/ # 核心抽象(config / db / sync / scheduler / datasource base
├── sources/ # 数据源实现
├── tasks/ # 同步任务实现(14 个)
├── api/ # FastAPI 管理接口
└── entrypoints/ # 进程入口(cli + worker
bin/ # 通用脚本(运行入口、CLI、一次性任务)
config/ # 配置文件、secrets
deploy/ # 部署相关
├── docker/ # Dockerfile + docker-compose.yml
└── systemd/ # systemd units + 部署脚本
│ ├── units/ # *.service / *.timer
│ └── deploy.sh # 一键部署脚本
docs/ # 架构文档
logs/ # 日志输出
tests/ # 单元测试
Dockerfile -> deploy/docker/Dockerfile
docker-compose.yml -> deploy/docker/docker-compose.yml
bin/deploy_systemd.sh -> deploy/systemd/deploy.sh
bin/systemd_deploy.sh -> deploy/systemd/deploy.sh
```
## 内置同步任务
| dataset_id | 触发时间 | 说明 |
|---|---|---|
| `stock_basic` | 交易日 09:00 | 全市场股票基础信息 + 股本 |
| `kline_daily` | 交易日 15:40 | 增量日 K 线(OHLCV,多源交叉) |
| `kline_index` | 交易日 15:50 | 六大指数日线 |
| `kline_5min` | 交易日 16:00 | 增量 5 分钟 K 线 |
| `moneyflow` | 交易日 16:30 | 资金流(主力/大/中/小单净额 |
| `industry_sector` | 周一 09:30 | 股票-行业映射(Baostock |
| `share_snapshot` | 交易日 09:30 | 股本快照(雪球 |
| `market_regime` | 交易日 16:00 | 市场情绪(衍生源 |
| dataset_id | systemd 触发时间 | Docker scheduler 时间 | 说明 |
|---|---|---|---|
| `stock_basic` | 工作日 09:00 | 09:00 | 全市场股票基础信息 + 股本 |
| `kline_index` | 工作日 15:30 | 15:30 | 六大指数日线 |
| `kline_daily` | 工作日 15:30runall| 15:40 | 增量日 K 线(OHLCV,多源交叉) |
| `kline_5min` | 工作日 15:30runall| 16:00 | 增量 5 分钟 K 线 |
| `market_regime` | 工作日 15:30runall| 16:15 | 市场情绪(衍生源 |
| `share_snapshot` | 工作日 15:30runall| 16:20 | 股本快照(雪球 |
| `mairui_ma_daily` | 工作日 16:30 | 16:30 | 日 K MA5/10/20/60(本地派生 |
| `mairui_indicators` | 工作日 16:40 | 16:40 | 日 K MACD/KDJ/BOLLmairui |
| `moneyflow` | 工作日 21:35 | 21:35 | 资金流(主力/大/中/小单净额) |
| `tick_trade` | 工作日 21:05 | 21:05 | 当天逐笔成交(mairui |
| `longhubang` | 工作日 22:00 | 22:00 | 龙虎榜(akshare / 东方财富) |
| `stock_node` | 周六 11:30 | 周六 11:30 | 股票-节点映射(mairui |
## 添加新数据源
@@ -70,7 +139,9 @@ tests/ # 单元测试
1.`app/tasks/` 新建 `task_xxx.py`,继承 `SyncTask`,设置 `dataset_id`
2.`app/tasks/__init__.py``TASKS` 字典注册
3. (可选)`app/core/sync/registry.py``SYNC_DEFINITIONS` 加条目
3.`app/core/sync/registry.py``SYNC_DEFINITIONS` 加条目
4. 如果使用 systemd 模式,在 `deploy/systemd/units/` 新增对应的 `.service``.timer`
5. 如果使用 Docker 模式,在 `app/core/scheduler/scheduler.py``DEFAULT_SCHEDULES` 新增调度项
## License