Files
Neo-ZQYY/.kiro/specs/etl-task-documentation/design.md

286 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设计文档ETL 任务说明文档
## 概述
本设计描述如何为飞球 ETL 系统生成一套完整的任务说明文档,放置于 `docs/etl_tasks/` 目录下。文档以 Markdown 格式编写按数据层ODS / DWD / DWS / INDEX / Utility分文件组织并提供一个总览 README 作为入口。
文档的目标读者是开发者和运维人员,需要覆盖:
- 每个任务的代码标识、Python 类、数据来源与目标
- Extract / Transform / Load 各阶段的处理逻辑
- CLI 参数与管道执行方式
- BaseTask 公共机制
## 架构
文档为纯静态 Markdown 文件,不涉及运行时代码变更。整体结构如下:
```
docs/etl_tasks/
├── README.md # 总览:任务清单 + 跳转链接 + 执行方式
├── ods_tasks.md # ODS 层任务详解
├── dwd_tasks.md # DWD 层任务详解
├── dws_tasks.md # DWS 层任务详解
├── index_tasks.md # INDEX 层任务详解
├── utility_tasks.md # 工具类任务详解
└── base_task_mechanism.md # BaseTask 公共机制与执行参数
```
```mermaid
graph TD
README["README.md<br/>总览入口"] --> ODS["ods_tasks.md"]
README --> DWD["dwd_tasks.md"]
README --> DWS["dws_tasks.md"]
README --> IDX["index_tasks.md"]
README --> UTL["utility_tasks.md"]
README --> BASE["base_task_mechanism.md"]
```
## 组件与接口
本 spec 不涉及代码组件。产出物为 7 个 Markdown 文件,各文件的内容范围如下:
### README.md总览
| 章节 | 内容 |
|------|------|
| 系统简介 | 飞球 ETL 系统概述、数据流向API → ODS → DWD → DWS |
| 任务清单 | 按层分组的表格任务代码、Python 类、简要说明、跳转链接 |
| 管道类型 | 7 种管道api_ods / api_ods_dwd / api_full / ods_dwd / dwd_dws / dwd_dws_index / dwd_index的层组合 |
| 处理模式 | increment_only / verify_only / increment_verify 的区别 |
| 数据源模式 | online / offline / hybrid 的区别 |
| CLI 参数速查 | 所有 CLI 参数的表格(参数名、类型、默认值、说明) |
| 常见命令示例 | 典型使用场景的命令行示例 |
### ods_tasks.mdODS 层)
每个 ODS 任务一个小节,包含:
- 任务代码与 Python 类
- API 端点与请求参数
- 字段解析逻辑transform 阶段)
- 目标 ODS 表与写入策略
- 特殊说明如分页、去重、content_hash 等)
需区分两种 ODS 任务模式:
1. 独立任务类(如 OrdersTask、MembersTask继承 BaseTask有独立的 E/T/L 实现
2. 通用 ODS 任务(由 `ods_tasks.py` 中 OdsTaskSpec + BaseOdsTask 动态生成):通过声明式配置定义端点、列映射等
已注册的 ODS 任务14 个独立 + N 个通用):
| 任务代码 | Python 类 | API 端点 | 目标表 |
|----------|-----------|----------|--------|
| ORDERS | OrdersTask | /Site/GetAllOrderSettleList | billiards_ods.fact_order |
| PAYMENTS | PaymentsTask | 支付相关端点 | billiards_ods.fact_payment |
| MEMBERS | MembersTask | /MemberProfile/GetTenantMemberList | billiards_ods.dim_member |
| PRODUCTS | ProductsTask | 商品相关端点 | billiards_ods 商品表 |
| TABLES | TablesTask | 台桌相关端点 | billiards_ods 台桌表 |
| ASSISTANTS | AssistantsTask | 助教相关端点 | billiards_ods 助教表 |
| PACKAGES_DEF | PackagesDefTask | 套餐相关端点 | billiards_ods 套餐表 |
| REFUNDS | RefundsTask | 退款相关端点 | billiards_ods 退款表 |
| COUPON_USAGE | CouponUsageTask | 优惠券相关端点 | billiards_ods 优惠券表 |
| INVENTORY_CHANGE | InventoryChangeTask | 库存变动端点 | billiards_ods 库存表 |
| TOPUPS | TopupsTask | 充值相关端点 | billiards_ods 充值表 |
| TABLE_DISCOUNT | TableDiscountTask | 台费折扣端点 | billiards_ods 折扣表 |
| ASSISTANT_ABOLISH | AssistantAbolishTask | 助教取消端点 | billiards_ods 取消表 |
| LEDGER | LedgerTask | 台账端点 | billiards_ods 台账表 |
通用 ODS 任务由 `ODS_TASK_CLASSES` 字典动态注册,每个任务通过 `OdsTaskSpec` 声明:
- `endpoint`API 端点路径
- `table`:目标 ODS 表名
- `columns`列定义列表ColumnSpec
- `page_size``data_path``list_key`:分页参数
- `pk_columns`:主键列
- `snapshot_mode`快照模式content_hash 去重)
### dwd_tasks.mdDWD 层)
DWD 层有 5 个已注册任务:
| 任务代码 | Python 类 | 说明 |
|----------|-----------|------|
| DWD_LOAD_FROM_ODS | DwdLoadTask | 核心装载任务:遍历 TABLE_MAP维度走 SCD2事实走增量 |
| TICKET_DWD | TicketDwdTask | 结账小票明细 → fact_order / fact_order_goods / fact_table_usage / fact_assistant_service |
| PAYMENTS_DWD | PaymentsDwdTask | ODS 支付记录 → fact_payment |
| MEMBERS_DWD | MembersDwdTask | ODS 会员记录 → dim_member |
| DWD_QUALITY_CHECK | DwdQualityTask | ODS 与 DWD 行数/金额核对,输出 JSON 报表 |
核心任务 DWD_LOAD_FROM_ODS 的处理逻辑:
- TABLE_MAP 定义了 40+ 对 DWD→ODS 表映射
- 维度表dim_*):检测 SCD2 列是否存在,有则执行 SCD2 合并(关闭旧版+插入新版),无则执行 Type1 Upsert
- 事实表dwd_*、fact_*):按 fetched_at 水位线增量插入,支持 upsert 或 insert-only
- FACT_MAPPINGS 定义了列名映射ODS 驼峰命名 → DWD 下划线命名)
- 每张表独立事务,单表失败不影响后续表
SCD2 处理流程:
1. 从 ODS 取最新快照DISTINCT ON 按业务主键 + fetched_at DESC
2. 与 DWD 当前版本scd2_is_current=1逐列对比
3. 有变更关闭旧版scd2_end_time=now, scd2_is_current=0+ 插入新版version+1
4. 无变更:跳过
### dws_tasks.mdDWS 层)
DWS 层有 15 个已注册任务,按业务域分组:
**助教业绩域:**
| 任务代码 | Python 类 | 目标表 | 粒度 |
|----------|-----------|--------|------|
| DWS_ASSISTANT_DAILY | AssistantDailyTask | dws_assistant_daily_detail | 日期+助教 |
| DWS_ASSISTANT_MONTHLY | AssistantMonthlyTask | dws_assistant_monthly_summary | 月份+助教 |
| DWS_ASSISTANT_CUSTOMER | AssistantCustomerTask | dws_assistant_customer_stats | 日期+助教+会员 |
| DWS_ASSISTANT_SALARY | AssistantSalaryTask | dws_assistant_salary_calc | 月份+助教 |
| DWS_ASSISTANT_FINANCE | AssistantFinanceTask | dws_assistant_finance_analysis | 日期+助教 |
**会员分析域:**
| 任务代码 | Python 类 | 目标表 | 粒度 |
|----------|-----------|--------|------|
| DWS_MEMBER_CONSUMPTION | MemberConsumptionTask | dws_member_consumption_summary | 日期+会员 |
| DWS_MEMBER_VISIT | MemberVisitTask | dws_member_visit_detail | 日期+会员+结账单 |
**财务统计域:**
| 任务代码 | Python 类 | 目标表 | 粒度 |
|----------|-----------|--------|------|
| DWS_FINANCE_DAILY | FinanceDailyTask | dws_finance_daily_summary | 日期 |
| DWS_FINANCE_RECHARGE | FinanceRechargeTask | dws_finance_recharge_summary | 日期 |
| DWS_FINANCE_INCOME_STRUCTURE | FinanceIncomeStructureTask | dws_finance_income_structure | 日期+收入类型 |
| DWS_FINANCE_DISCOUNT_DETAIL | FinanceDiscountDetailTask | dws_finance_discount_detail | 日期+折扣类型 |
**运维任务:**
| 任务代码 | Python 类 | 说明 |
|----------|-----------|------|
| DWS_BUILD_ORDER_SUMMARY | DwsBuildOrderSummaryTask | 构建订单汇总中间表 |
| DWS_RETENTION_CLEANUP | DwsRetentionCleanupTask | 按时间分层清理历史数据 |
| DWS_MV_REFRESH_FINANCE_DAILY | DwsMvRefreshFinanceDailyTask | 刷新财务日报物化视图 |
| DWS_MV_REFRESH_ASSISTANT_DAILY | DwsMvRefreshAssistantDailyTask | 刷新助教日报物化视图 |
所有 DWS 任务继承 BaseDwsTask共享以下机制
- 时间分层范围计算TimeLayer: LAST_2_DAYS / LAST_1_MONTH / LAST_3_MONTHS / LAST_6_MONTHS / ALL
- 配置缓存ConfigCache业绩档位、等级价格、奖金规则、区域分类、技能类型
- delete-before-insert 更新策略(按日期范围先删后插,保证幂等)
- bulk_insert / upsert 写入方法
### index_tasks.mdINDEX 层)
INDEX 层有 4 个已注册任务:
| 任务代码 | Python 类 | 目标表 | 指数类型 |
|----------|-----------|--------|----------|
| DWS_WINBACK_INDEX | WinbackIndexTask | dws_member_winback_index | WBI回流指数 |
| DWS_NEWCONV_INDEX | NewconvIndexTask | dws_member_newconv_index | NCI新客转化指数 |
| DWS_RELATION_INDEX | RelationIndexTask | dws_relation_index | RS关系指数 |
| DWS_ML_MANUAL_IMPORT | MlManualImportTask | dws_ml_manual_ledger | ML手动台账导入 |
所有指数任务继承 BaseIndexTask共享
- 参数从 `billiards_dws.cfg_index_parameters` 表加载
- 百分位历史记录PercentileHistory
- 标准化的指数计算流程
### utility_tasks.md工具类
| 任务代码 | Python 类 | 用途 |
|----------|-----------|------|
| INIT_ODS_SCHEMA | InitOdsSchemaTask | 执行 ODS + etl_admin DDL创建必要目录 |
| INIT_DWD_SCHEMA | InitDwdSchemaTask | 执行 DWD DDL |
| INIT_DWS_SCHEMA | InitDwsSchemaTask | 执行 DWS DDL |
| MANUAL_INGEST | ManualIngestTask | 从本地 JSON 文件手动入库到 ODS |
| ODS_JSON_ARCHIVE | OdsJsonArchiveTask | 归档 ODS JSON 文件 |
| CHECK_CUTOFF | CheckCutoffTask | 检查数据截止时间 |
| SEED_DWS_CONFIG | SeedDwsConfigTask | 初始化 DWS 配置种子数据 |
| DATA_INTEGRITY_CHECK | DataIntegrityTask | 数据完整性校验 |
### base_task_mechanism.md公共机制
覆盖内容:
- BaseTask 模板方法流程execute → build_context → [分段] → extract → transform → load → commit
- TaskContext 字段说明
- 时间窗口计算逻辑(优先级:手动覆盖 > 游标 > 闲忙时段默认值)
- 窗口分段build_window_segments
- TaskRegistry 注册方式与元数据TaskMeta: task_class, requires_db_config, layer, task_type
- PipelineRunner 管道执行流程
- 校验框架Verifier概述
## 数据模型
本 spec 不涉及数据模型变更。文档中引用的数据模型均为现有系统中的表结构,包括:
**ODS 层表**billiards_ods schema
- settlement_records, table_fee_transactions, assistant_service_records, member_profiles, payment_transactions, refund_transactions 等 20+ 表
**DWD 层表**billiards_dwd schema
- 维度表dim_site, dim_table, dim_assistant, dim_member, dim_member_card_account, dim_tenant_goods, dim_store_goods, dim_goods_category, dim_groupbuy_package各含 _ex 扩展表)
- 事实表dwd_settlement_head, dwd_table_fee_log, dwd_table_fee_adjust, dwd_store_goods_sale, dwd_assistant_service_log, dwd_assistant_trash_event, dwd_member_balance_change, dwd_groupbuy_redemption, dwd_platform_coupon_redemption, dwd_recharge_order, dwd_payment, dwd_refund各含 _ex 扩展表)
**DWS 层表**billiards_dws schema
- 助教域dws_assistant_daily_detail, dws_assistant_monthly_summary, dws_assistant_customer_stats, dws_assistant_salary_calc, dws_assistant_finance_analysis
- 会员域dws_member_consumption_summary, dws_member_visit_detail
- 财务域dws_finance_daily_summary, dws_finance_recharge_summary, dws_finance_income_structure, dws_finance_discount_detail
- 指数域dws_member_winback_index, dws_member_newconv_index, dws_relation_index, dws_ml_manual_ledger
- 配置表cfg_index_parameters, cfg_skill_type, cfg_performance_tier, cfg_level_price, cfg_bonus_rule, cfg_area_category
## 正确性属性
*正确性属性是一种在系统所有有效执行中都应成立的特征或行为——本质上是关于系统应该做什么的形式化陈述。属性是人类可读规范与机器可验证正确性保证之间的桥梁。*
由于本 spec 的产出物是文档Markdown 文件),而非运行时代码,正确性属性主要关注文档的完整性和一致性——即文档是否覆盖了所有已注册任务。
Property 1: ODS 任务文档覆盖完整性
*对于所有*在 `task_registry.py` 中注册且 layer="ODS" 的任务代码,`ods_tasks.md` 中应包含该任务代码的说明章节,并列出其目标表。
**Validates: Requirements 2.1, 2.4**
Property 2: DWD 任务文档覆盖完整性
*对于所有*在 `task_registry.py` 中注册且 layer="DWD" 的任务代码,`dwd_tasks.md` 中应包含该任务代码的说明章节,并列出其源表和目标表。
**Validates: Requirements 3.1**
Property 3: DWS 任务文档覆盖完整性
*对于所有*在 `task_registry.py` 中注册且 layer="DWS" 的任务代码,`dws_tasks.md` 中应包含该任务代码的说明章节,并标注其更新策略。
**Validates: Requirements 4.1, 4.4**
Property 4: INDEX 任务文档覆盖完整性
*对于所有*在 `task_registry.py` 中注册且 layer="INDEX" 的任务代码,`index_tasks.md` 中应包含该任务代码的说明章节。
**Validates: Requirements 5.1**
Property 5: Utility 任务文档覆盖完整性
*对于所有*在 `task_registry.py` 中注册且 task_type="utility" 的任务代码,`utility_tasks.md` 中应包含该任务代码的说明章节。
**Validates: Requirements 6.1**
Property 6: CLI 参数文档覆盖完整性
*对于所有*在 `cli/main.py``parse_args()` 中定义的 CLI 参数,`README.md``base_task_mechanism.md` 中应包含该参数的说明。
**Validates: Requirements 7.1**
Property 7: 管道类型文档覆盖完整性
*对于所有*在 `PipelineRunner.PIPELINE_LAYERS` 中定义的管道类型,`README.md` 中应包含该管道类型的层组合说明。
**Validates: Requirements 7.2**
## 错误处理
本 spec 为文档生成任务,不涉及运行时错误处理。文档编写过程中需注意:
1. 若源代码中的任务类或注册信息发生变更,文档可能过时——应在 README.md 中注明"最后更新日期"和"基于代码版本"
2. 若某个任务的 API 端点或参数无法从代码中直接读取(如动态配置),应在文档中标注"参见配置文件"
## 测试策略
**单元测试(示例验证):**
- 验证所有 7 个 Markdown 文件存在于 `docs/etl_tasks/` 目录下
- 验证 README.md 包含指向其他 6 个文件的链接
- 验证每个分层文件中包含对应层的所有已注册任务代码
**属性测试(覆盖完整性验证):**
- 使用 pytest 编写脚本,从 `task_registry.py` 动态读取已注册任务列表
- 解析对应的 Markdown 文件,检查每个任务代码是否出现在文档中
-`cli/main.py` 解析 CLI 参数列表,检查文档中是否覆盖
- 属性测试库pytest本项目已使用配合 parametrize 实现参数化验证
- 每个属性测试标注对应的设计属性编号
**测试标注格式:**
```python
# Feature: etl-task-documentation, Property 1: ODS 任务文档覆盖完整性
def test_ods_task_coverage():
...
```
由于本 spec 的产出物是静态文档,属性测试的核心价值在于确保文档与代码的一致性,防止文档遗漏任务。测试应在文档生成后运行一次即可,无需持续集成。