Migrate poo recorder and align Alembic naming
This commit is contained in:
@@ -30,8 +30,10 @@
|
||||
- `api/`
|
||||
- HTTP routes
|
||||
- 当前已迁入 `POST /homeassistant/publish` 第一版入口
|
||||
- 当前已迁入 `POST /poo/record` 与 `GET /poo/latest`
|
||||
- `models/`
|
||||
- SQLAlchemy models
|
||||
- 当前 `location` 与 `poo` 使用各自独立的数据库 base
|
||||
- `schemas/`
|
||||
- Pydantic schemas
|
||||
- `services/`
|
||||
@@ -44,9 +46,13 @@
|
||||
- `static/`
|
||||
- 极简静态资源
|
||||
|
||||
### `alembic/`
|
||||
### `alembic_location/`
|
||||
|
||||
数据库 migration 基础设施。当前尚未迁入业务表,但迁移链路已就绪。
|
||||
Location DB 的 migration 基础设施。
|
||||
|
||||
### `alembic_poo/`
|
||||
|
||||
Poo DB 的 migration 基础设施。
|
||||
|
||||
### `tests/`
|
||||
|
||||
|
||||
+48
-6
@@ -12,6 +12,7 @@
|
||||
- 建立 Docker / Compose 基础骨架
|
||||
- 建立 OpenAPI 导出脚本
|
||||
- 迁入 `location recorder` 第一版
|
||||
- 迁入 `poo recorder` 第一版
|
||||
|
||||
## 数据库配置现状
|
||||
|
||||
@@ -25,13 +26,12 @@
|
||||
其中:
|
||||
|
||||
- `location` 模块已经实际接到 `LOCATION_DATABASE_URL`
|
||||
- `poo` 目前只保留 `POO_DATABASE_URL` 配置占位,等待模块迁入
|
||||
- `poo` 模块已经实际接到 `POO_DATABASE_URL`
|
||||
|
||||
## 当前阶段未做内容
|
||||
|
||||
- 未迁移 TickTick 业务逻辑
|
||||
- 未迁移 Home Assistant 业务逻辑
|
||||
- 未迁移 poo records
|
||||
- 未迁移 Home Assistant inbound / outbound 之外的其他业务逻辑
|
||||
- 未实现真实 OAuth 流程
|
||||
- 未做数据迁移
|
||||
|
||||
@@ -74,15 +74,57 @@ CREATE TABLE location (
|
||||
- DB 尚未被 Alembic 接管时拒绝启动
|
||||
- DB revision 与当前应用预期不一致时拒绝启动
|
||||
|
||||
## Poo recorder 说明
|
||||
|
||||
当前 Python 项目已经接入:
|
||||
|
||||
- `POST /poo/record`
|
||||
- `GET /poo/latest`
|
||||
|
||||
并对齐当前真实 baseline schema:
|
||||
|
||||
```sql
|
||||
CREATE TABLE poo_records (
|
||||
timestamp TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
latitude REAL NOT NULL,
|
||||
longitude REAL NOT NULL,
|
||||
PRIMARY KEY (timestamp)
|
||||
);
|
||||
```
|
||||
|
||||
历史上 legacy Go 实现使用:
|
||||
|
||||
```sql
|
||||
PRAGMA user_version = 1;
|
||||
```
|
||||
|
||||
当前已经补上与 location 一致风格的 Alembic baseline / 接管策略:
|
||||
|
||||
- `poo_records` 当前 schema 被视为 Alembic baseline
|
||||
- 新数据库通过 `alembic_poo upgrade head` 初始化
|
||||
- 已有 legacy SQLite 数据库通过 `alembic stamp` 接管
|
||||
- `PRAGMA user_version = 1` 仅保留为历史事实,不再作为新的主 migration 机制
|
||||
|
||||
同时这一轮明确移除了 Notion:
|
||||
|
||||
- 不迁 Notion sync
|
||||
- 不迁 Notion adapter
|
||||
- `POST /poo/record` 不再依赖 `tableId` 才能写入
|
||||
|
||||
详见:
|
||||
|
||||
- [poo-recorder.md](poo-recorder.md)
|
||||
|
||||
## 后续建议顺序
|
||||
|
||||
建议继续沿用既有迁移文档中的顺序:
|
||||
|
||||
1. 先迁 `location recorder`
|
||||
2. 再迁 Home Assistant 出站适配层
|
||||
3. 再迁 TickTick adapter
|
||||
4. 再迁 Home Assistant 命令网关
|
||||
5. 最后迁 `poo recorder`
|
||||
3. 再迁 Home Assistant 命令网关
|
||||
4. 再迁 `poo recorder`
|
||||
5. 最后迁 TickTick adapter
|
||||
|
||||
## 开发约束提醒
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
# Poo Recorder
|
||||
|
||||
本文档说明 `poo recorder` 在 Python 项目中的当前行为边界,以及 poo SQLite 的 Alembic 接管策略。
|
||||
|
||||
## 当前基线
|
||||
|
||||
当前生产版本中的真实 SQLite schema 为:
|
||||
|
||||
```sql
|
||||
CREATE TABLE poo_records (
|
||||
timestamp TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
latitude REAL NOT NULL,
|
||||
longitude REAL NOT NULL,
|
||||
PRIMARY KEY (timestamp)
|
||||
);
|
||||
```
|
||||
|
||||
历史上 legacy Go 实现使用:
|
||||
|
||||
```sql
|
||||
PRAGMA user_version = 1;
|
||||
```
|
||||
|
||||
当前 Python 迁移以这套 schema 为事实基线,不重新设计表结构。
|
||||
|
||||
## 当前已迁入的 API
|
||||
|
||||
当前 Python 项目已经接入:
|
||||
|
||||
- `POST /poo/record`
|
||||
- `GET /poo/latest`
|
||||
|
||||
### `POST /poo/record`
|
||||
|
||||
用途:
|
||||
|
||||
- 记录一条 poo event
|
||||
- 最佳努力地刷新 Home Assistant sensor
|
||||
- 如果配置了 `POO_WEBHOOK_ID`,最佳努力地触发 Home Assistant webhook
|
||||
|
||||
请求体:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "done",
|
||||
"latitude": "1.23",
|
||||
"longitude": "4.56"
|
||||
}
|
||||
```
|
||||
|
||||
当前策略:
|
||||
|
||||
- unknown field:`400 bad request`
|
||||
- 数值非法:`400 bad request`
|
||||
- 记录成功后,即使 Home Assistant side effect 失败,也不会回滚本地 DB 写入
|
||||
|
||||
### `GET /poo/latest`
|
||||
|
||||
用途:
|
||||
|
||||
- 读取最新一条 poo 记录
|
||||
- 将其重新发布到 Home Assistant sensor
|
||||
|
||||
当前外部行为与 legacy 保持一致:
|
||||
|
||||
- 成功:空响应体,HTTP 200
|
||||
- 如果当前 DB 里还没有任何 poo 记录:仍返回空响应体,HTTP 200,但不会发布 sensor
|
||||
- 真正的发布失败:简洁 `internal server error`
|
||||
|
||||
## Home Assistant side effects
|
||||
|
||||
当前已复用 Python 项目中已有的 Home Assistant outbound adapter。
|
||||
|
||||
当前支持:
|
||||
|
||||
- 发布 / 更新 poo status sensor
|
||||
- 可选触发 webhook
|
||||
|
||||
相关配置:
|
||||
|
||||
- `HOME_ASSISTANT_BASE_URL`
|
||||
- `HOME_ASSISTANT_AUTH_TOKEN`
|
||||
- `HOME_ASSISTANT_TIMEOUT_SECONDS`
|
||||
- `POO_SENSOR_ENTITY_NAME`
|
||||
- `POO_SENSOR_FRIENDLY_NAME`
|
||||
- `POO_WEBHOOK_ID`
|
||||
|
||||
## Alembic 接管策略
|
||||
|
||||
poo 的接管逻辑刻意保持与 location 一致。
|
||||
|
||||
当前 baseline revision:
|
||||
|
||||
- `20260420_01_poo_baseline`
|
||||
|
||||
当前提供的脚本入口:
|
||||
|
||||
```bash
|
||||
python scripts/poo_db_adopt.py
|
||||
```
|
||||
|
||||
或:
|
||||
|
||||
```bash
|
||||
python -m scripts.poo_db_adopt
|
||||
```
|
||||
|
||||
规则如下:
|
||||
|
||||
1. 如果本地不存在 poo DB 文件:
|
||||
- 视为新库初始化
|
||||
- 通过 `alembic_poo upgrade head` 创建新库
|
||||
2. 如果本地已经存在 legacy DB:
|
||||
- 先检查 `poo_records` 表 schema
|
||||
- 再检查 `PRAGMA user_version = 1`
|
||||
- 只有完全匹配,才通过 Alembic `stamp` 接管
|
||||
3. 如果 schema 或 `user_version` 不匹配:
|
||||
- 直接失败
|
||||
- 不自动修复
|
||||
4. 如果数据库已经存在 `alembic_version`:
|
||||
- 只有 revision 与当前 baseline 一致才接受
|
||||
- 否则直接失败
|
||||
|
||||
同时,应用启动时也会对 `POO_DATABASE_URL` 做只读校验:
|
||||
|
||||
- 文件不存在:拒绝启动
|
||||
- DB 尚未被 Alembic 接管:拒绝启动
|
||||
- revision 不匹配:拒绝启动
|
||||
|
||||
## 明确移除 Notion
|
||||
|
||||
这一轮不会迁入任何 Notion 逻辑。
|
||||
|
||||
也就是说,当前 Python 版的 poo recorder:
|
||||
|
||||
- 不保留 Notion adapter
|
||||
- 不保留 Notion sync
|
||||
- 不保留 `tableId` 依赖
|
||||
- 不因为 legacy 中存在 Notion 就继续保留兼容层
|
||||
Reference in New Issue
Block a user