6.3 KiB
6.3 KiB
需求文档:DWD 第一阶段重构
简介
对 DwdLoadTask(tasks/dwd/dwd_load_task.py)进行低风险重构,统一事实表增量窗口模式、删除回补机制、清理死代码和未使用常量、修复已知 bug。改动集中在单个文件(及删除一个死代码文件),目标是简化代码路径、消除冗余分支,为后续架构重构(第二阶段)打好基础。
术语表
- DwdLoadTask:DWD 层数据装载任务类,负责从 ODS 表读取数据并合并到 DWD 维度表和事实表
- ODS:Operational Data Store,原始数据存储层
- DWD:Data Warehouse Detail,明细数据层
- SCD2:Slowly Changing Dimension Type 2,缓慢变化维度第二类,通过版本号和时间戳追踪历史变更
- 水位线(Watermark):基于 DWD 表中已有数据的最大时间戳来确定增量起点的机制
- 窗口模式(Window Mode):通过
context.window_start/context.window_end明确指定时间范围的增量机制 - 回补机制(Backfill):
_insert_missing_by_pk()方法,在主增量写入后通过 LEFT JOIN 补齐缺失主键记录 - BaseDwdTask:
base_dwd_task.py中定义的死代码基类,从未被任何子类使用 - FACT_MAPPINGS:事实表和维度表的列映射字典,定义 ODS 列到 DWD 列的转换规则
- TaskContext:运行期上下文数据类,包含
store_id、window_start、window_end、window_minutes等字段 - overlap_seconds:自动模式下窗口起点的回退秒数,用于覆盖可能的数据延迟
需求
需求 1:统一事实表增量窗口模式
用户故事: 作为 ETL 开发者,我希望事实表增量加载统一使用窗口模式(window_start / window_end),以消除水位线与窗口两套并行的范围过滤逻辑,降低代码复杂度。
验收标准
- WHEN
DwdLoadTask.load()处理事实表时,THE DwdLoadTask SHALL 始终将context.window_start和context.window_end传递给_merge_fact_increment(),不再根据run.window_override配置判断是否传递 - WHEN
_merge_fact_increment()构建增量 SQL 时,THE DwdLoadTask SHALL 统一使用WHERE fetched_at >= %s AND fetched_at < %s条件过滤,参数为window_start和window_end - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_get_fact_watermark()方法 - WHEN
_merge_fact_increment()被调用时,THE DwdLoadTask SHALL 不再接受watermark参数,方法签名中window_start和window_end为必填参数 - WHEN 自动模式(无
window_override)运行时,THE DwdLoadTask SHALL 通过BaseTask._get_time_window()计算的context.window_start(含overlap_seconds回退)和context.window_end作为窗口范围
需求 2:删除回补机制
用户故事: 作为 ETL 开发者,我希望删除事实表的回补机制(_insert_missing_by_pk),因为统一窗口后回补的 LEFT JOIN 结果集几乎一定为空,且类型转换失败应直接报错而非静默丢失数据。
验收标准
- WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_insert_missing_by_pk()方法 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
FACT_MISSING_FILL_TABLES常量 - WHEN
_merge_fact_increment()执行完主增量 INSERT 后,THE DwdLoadTask SHALL 直接返回插入和更新计数,不再调用回补逻辑 - WHEN 事实表增量 SQL 执行过程中发生类型转换错误时,THE DwdLoadTask SHALL 让异常自然传播,触发该表的事务回滚和错误日志记录
需求 3:清理死代码和未使用常量
用户故事: 作为 ETL 开发者,我希望清理所有已确认的死代码和未使用常量,以减少代码体积、消除维护负担和潜在的误导。
验收标准
- WHEN 重构完成后,THE 代码库 SHALL 不再包含
tasks/dwd/base_dwd_task.py文件 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_pick_order_column()方法 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
FACT_ORDER_CANDIDATES常量 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_upsert_scd2_row()方法 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_close_current_dim()方法 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_insert_dim_row()方法 - WHEN 重构完成后,THE DwdLoadTask SHALL 不再包含
_merge_dim_type1_upsert()方法 - WHEN
_merge_dim()被调用时,THE DwdLoadTask SHALL 直接调用_merge_dim_scd2(),不再检查scd_cols_present条件分支 - WHEN 外部模块(
debug_dwd.py、integrity_checker.py)引用FACT_ORDER_CANDIDATES时,THE 重构 SHALL 同步更新这些引用,将候选列列表内联到各自模块中或提取为共享常量
需求 4:修复 _build_column_mapping() 参数 bug
用户故事: 作为 ETL 开发者,我希望修复 _build_column_mapping() 中引用未定义变量 ods_table 和 cur 的 bug,以防止未来条件变化时触发 NameError。
验收标准
- WHEN
_build_column_mapping()被调用时,THE DwdLoadTask SHALL 通过方法参数接收ods_table和cur,而非依赖外部作用域的未定义变量 - WHEN
_build_column_mapping()的方法签名变更后,THE DwdLoadTask SHALL 同步更新所有调用点,传入正确的ods_table和cur参数
需求 5:保持现有功能行为不变
用户故事: 作为 ETL 开发者,我希望重构后的代码在功能行为上与重构前保持一致(除了移除水位线和回补),以确保生产环境的数据处理不受影响。
验收标准
- WHEN 维度表执行 SCD2 合并时,THE DwdLoadTask SHALL 保持与重构前相同的关闭旧版本和插入新版本行为
- WHEN 事实表执行增量插入时,THE DwdLoadTask SHALL 保持与重构前相同的 UPSERT 逻辑(含
ON CONFLICT和IS DISTINCT FROM变更检测) - WHEN
overlap_seconds配置存在时,THE DwdLoadTask SHALL 保留自动模式下窗口起点的回退机制 - WHEN
dwd.only_tables或DWD_ONLY_TABLES配置存在时,THE DwdLoadTask SHALL 保留表过滤功能 - FOR ALL 有效的
FACT_MAPPINGS配置和 ODS 源数据,重构后的事实表增量插入 SHALL 产生与重构前窗口模式相同的 DWD 写入结果