feat: consolidate legacy workflows into gyxx-flow
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
# GYXX Flow 统一编排平台设计
|
||||
|
||||
## 1. 目标
|
||||
|
||||
把 `D:\yingxiaoyunying`、`D:\shop-data-flow`、
|
||||
`D:\product-collector-analyze-flow` 和 `E:\auto-flow` 的业务源码、启动脚本和工作流
|
||||
完整迁移到 `D:\gyxx-flow`。新系统采用模块化单体、统一 CLI、声明式调度和分层
|
||||
数据目录,同时允许旧任务在迁移期继续运行并能逐任务回滚。
|
||||
|
||||
“完整迁移”的硬性定义是:删除、改名或断开四个旧项目目录后,新项目仍能完成
|
||||
入口发现、导入、dry-run、手工执行和调度执行。旧项目只能作为迁移输入和生产对照,
|
||||
不得成为新项目运行时依赖。仅登记旧入口或通过环境变量调用旧脚本不算迁移完成。
|
||||
|
||||
## 2. 边界
|
||||
|
||||
- 新代码和迁移工具只写入 `D:\gyxx-flow`。
|
||||
- 在生产切换门禁前,不修改四个旧项目或现有计划任务。
|
||||
- 允许从旧项目做一次性只读复制;复制后的代码归属新项目并在新项目内改造、测试。
|
||||
- 运行时代码不得读取 `GYXX_LEGACY_*_ROOT`,不得导入或启动四个旧目录中的文件。
|
||||
- `D:\comment-data-collector` 不在迁移范围内;它与内容模块共享数据库表的字段
|
||||
所有权以外部契约表示。
|
||||
- 真实 Cookie、密码、应用密钥、访问令牌和浏览器 Profile 不进入源码仓库。
|
||||
|
||||
## 3. 方案
|
||||
|
||||
选择模块化单体而不是原样拼目录或直接拆微服务。四个业务模块为:
|
||||
|
||||
1. `content_marketing`:内容指标、评论、达人、周报/月报和登录维护。
|
||||
2. `product_commerce`:ERP、商品、画像、主图、市场排名、分析和告警。
|
||||
3. `shop_intelligence`:店铺及竞店周数据。
|
||||
4. `supply_chain`:采购确认、库存预警、补货和采购单更新。
|
||||
|
||||
共享能力通过端口和适配器提供:文件产物、PostgreSQL、飞书、Hermes、浏览器和
|
||||
平台采集。业务模块不得导入其他业务模块的内部实现。
|
||||
|
||||
每个业务模块包含自己的 `jobs/`、`collectors/`、`services/`、`models/` 和
|
||||
`resources/`。一次性复制阶段可以在模块内保留原相对结构以降低行为变化风险,但
|
||||
所有入口必须改为由模块清单定位,所有数据/日志/Profile/临时文件必须改由
|
||||
`RunContext` 与 `DataLayout` 提供。模块间共享只允许依赖 `core`、`workflow`、
|
||||
`adapters` 和显式契约。
|
||||
|
||||
## 4. 运行模型
|
||||
|
||||
调度器只调用稳定命令 `gyxx run <workflow-id>`。工作流引擎负责:
|
||||
|
||||
- 创建 `run_id` 和 `RunContext`;
|
||||
- 获取工作流及资源锁;
|
||||
- 按依赖顺序执行步骤;
|
||||
- 记录步骤状态、退出码、耗时和错误;
|
||||
- 进行有上限的步骤级重试;
|
||||
- 生成不可变产物清单和 SHA-256;
|
||||
- 在 shadow 模式关闭生产写入和正式通知。
|
||||
|
||||
Windows Task Scheduler 只是一个调度适配器。工作流和时间表的唯一事实来源是仓库
|
||||
内的声明式配置,因此可以生成 Windows、Cron 或其他平台的调度配置。
|
||||
|
||||
## 5. 数据模型
|
||||
|
||||
运行根目录由 `GYXX_DATA_ROOT` 指定,默认是仓库下 `var`:
|
||||
|
||||
```text
|
||||
var/
|
||||
data/raw/<domain>/<source>/<dataset>/business_date=<date>/run_id=<id>/
|
||||
data/normalized/<domain>/<dataset>/schema_vN/
|
||||
data/curated/<domain>/<dataset>/
|
||||
data/exports/<consumer>/<workflow>/<date>/<run_id>/
|
||||
data/evidence/<workflow>/<run_id>/
|
||||
data/legacy/<source_project>/
|
||||
runs/<workflow>/<yyyy>/<mm>/<dd>/<run_id>/
|
||||
state/{browser_profiles,cookies,checkpoints,locks}/
|
||||
logs/<workflow>/<yyyy>/<mm>/<dd>/
|
||||
quarantine/
|
||||
tmp/
|
||||
```
|
||||
|
||||
原始数据只追加。每个产物都有 `artifact_id`、数据集、业务日期、schema 版本、行数、
|
||||
字节数、SHA-256、源路径和上游产物引用。历史文件先原样复制到 `legacy`,校验通过后
|
||||
再生成标准化数据。
|
||||
|
||||
## 6. 安全和幂等
|
||||
|
||||
- 配置只保存环境变量名或凭据引用,不保存密钥值。
|
||||
- 生产写入使用 `workflow + business_date + entity_id + schema_version` 幂等键。
|
||||
- 外部通知使用 outbox/回执,失败重试不会重复发送。
|
||||
- 飞书、数据库和通知都是可替换 Sink;shadow 模式使用测试 Sink。
|
||||
- 浏览器 Profile 使用独立资源锁,禁止不同工作流并发写同一 Profile。
|
||||
|
||||
## 7. 迁移策略
|
||||
|
||||
采用源码接管迁移:基线清单 -> 新基础设施 -> 源码只读复制 -> 新项目内路径与配置
|
||||
改造 -> 无旧目录测试 -> 影子运行 -> 单任务切换 -> 观察 -> 退役。旧命令适配器只
|
||||
用于盘点阶段,不能出现在最终工作流定义中。切换时只禁用一个旧任务,不删除;失败
|
||||
时关闭新任务并重新启用旧任务。旧项目至少保留只读 30 天。
|
||||
|
||||
迁移顺序为 `shop_intelligence`、`supply_chain`、`content_marketing`、
|
||||
`product_commerce`。最后才合并真正重复的适配器,避免因名称相同而过早抽象不同语义
|
||||
的采集器。
|
||||
|
||||
## 8. 验收原则
|
||||
|
||||
工程验收依赖自动化测试、静态扫描、源码哈希清单、入口覆盖、旧根目录引用扫描、
|
||||
隔离旧目录的导入/dry-run、调度生成和历史回放。四模块所有纳入迁移范围的源码必须
|
||||
在新项目中有目标文件和来源哈希;所有真实入口必须标明 scheduled、manual、library
|
||||
或 intentionally-excluded,不能静默遗漏。生产验收必须以真实任务运行记录为证据:
|
||||
日任务连续 7 天,周任务连续 2 个周期,月任务通过历史月份回放。任何缺少证据的
|
||||
项目保持未勾选状态。
|
||||
|
||||
## 9. 统一运行时适配器
|
||||
|
||||
每个可执行脚本以完整 `script_id=<module>:<entry>` 作为运行时隔离主键。
|
||||
`config/runtime-bindings.json` 显式保存 130 个脚本的固定 CDP 端口,范围为
|
||||
`22000..22999`;配置加载时必须同时满足入口 100% 覆盖、端口唯一和回环地址约束。
|
||||
新增脚本只能领取未使用端口,已有脚本端口不得随发现顺序漂移。
|
||||
|
||||
每个脚本的浏览器状态固定落到:
|
||||
|
||||
```text
|
||||
<GYXX_DATA_ROOT>/state/browser/<module>/<script-name>-<id-digest>/
|
||||
profile/
|
||||
cookies.json
|
||||
storage_state.json
|
||||
```
|
||||
|
||||
同一脚本跨运行复用上述目录,不同脚本不共享端口、Profile、Cookie 或 storage state。
|
||||
顶层 workflow 和 `gyxx scripts run` 均由 `ModuleCommandAdapter` 注入绑定;嵌套 Python
|
||||
进程在业务模块导入前由 adapter-owned `sitecustomize` 按真实子脚本路径重新绑定,且会
|
||||
纠正父进程遗留的 `--cdp-port`、`--cdp-url` 和 `--user-data-dir` 参数。PowerShell/BAT
|
||||
需要浏览器时通过 `python -m gyxx_flow.runtime_exec env <script-id>` 读取目标叶子脚本绑定。
|
||||
|
||||
外部系统策略是运行时硬边界,而不是更换原业务后端:
|
||||
|
||||
- 飞书继续使用原来的 lark-cli profile、身份和原 OpenAPI 应用;适配器只透传并禁止误覆盖。
|
||||
- PostgreSQL 继续使用现有云端配置,统一映射 `PG_*`、`DB_*`、`AUTOFLOW_PG_*`,拒绝回环数据库。
|
||||
- Hermes 继续使用本机 HTTP/CLI,所有 HTTP 端点只允许 `localhost`、`127.0.0.1` 或 `::1`。
|
||||
- Cookie 和 storage state 通过原子替换保存;日志和绑定输出只包含路径、端口和计数,不包含值。
|
||||
|
||||
dry-run 只解析和验证绑定,不创建 Profile/Cookie 目录,不探测或启动浏览器,也不触发任何
|
||||
飞书、数据库或 Hermes 调用。
|
||||
|
||||
## 10. 采集数据统一分层
|
||||
|
||||
`GYXX_DATA_ROOT` 表示整套运行数据根,不直接等同于 raw 目录。四个业务模块通过共享的 `ModuleDataPaths` 解析固定目录,模块脚本继续使用原有公开常量,避免业务逻辑与物理目录结构耦合:
|
||||
|
||||
```text
|
||||
<GYXX_DATA_ROOT>/
|
||||
data/
|
||||
raw/<module>/ # 原始 JSON、CSV、Excel、下载文件、原始截图
|
||||
normalized/<module>/ # 清洗并统一字段后的数据
|
||||
curated/<module>/ # 聚合、分析和可供下游复用的数据
|
||||
exports/<module>/ # Markdown、Excel 等面向人员或外部消费的报告
|
||||
evidence/<module>/ # 产物清单、哈希和验收证据
|
||||
state/<module>/ # checkpoint;浏览器状态仍按 script_id 隔离
|
||||
logs/<module>/
|
||||
tmp/<module>/
|
||||
```
|
||||
|
||||
raw 数据保持追加语义;浏览器直接下载的 XLS/XLSX/CSV、接口原始 JSON 和采集截图归 raw,处理过程中的临时下载归 tmp,清洗结果归 normalized,跨来源汇总归 curated,最终 MD/XLSX 报告归 exports。现有 `data/raw/<module>/legacy` 只读保留,不在本次收口中移动或重写。路径对象只负责解析,不在导入或 dry-run 时创建目录,因此项目根和数据根可分别迁移。
|
||||
Reference in New Issue
Block a user