111 lines
3.0 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.

---
phase: 5
plan: 1
wave: 1
title: "30 天窗口去重修复DATA-01"
depends_on: []
files_modified:
- app/services/ingest/dedup.py
- tests/ingest/test_dedup.py # NEW
autonomous: true
requirements:
- DATA-01
---
# Phase 5 Plan 01: 30 天窗口去重修复DATA-01
## Objective
`dedup.py``batch_dedup_filter()` 目前查全量历史数据去重,导致同一职位超过 30 天后无法重新入库。
本 Plan 在去重查询 SQL 中加入 30 天时间窗口。
## Must Haves
- [ ] 单字段 dedup SQL 加 `AND created_at > now() - INTERVAL 30 DAY`
- [ ] 双字段 dedup SQL 同样加 30 天窗口
- [ ] 新增 Mock 测试(用 `AsyncMock` 模拟 ClickHouse 客户端)覆盖:
- 30 天内有记录 → 视为重复,过滤
- 30 天外有记录 → 不重复,允许入库
- 无记录 → 允许入库
- [ ] `pipenv run python -m pytest tests/ingest/test_dedup.py -v` 全部通过
- [ ] 全量回归 `pytest tests/ -v` 无失败
---
## Wave 1
### Task 1.1: 修改 dedup.py
<read_first>
- `app/services/ingest/dedup.py`(当前 81 行)
</read_first>
<action>
修改 `batch_dedup_filter()` 中的两个 SQL 查询:
**单字段去重(第 51 行附近):**
```python
# 修改前
query = f"SELECT {key_col} FROM {table} WHERE {key_col} IN {{keys:Array(String)}}"
# 修改后
query = (
f"SELECT {key_col} FROM {table} "
f"WHERE {key_col} IN {{keys:Array(String)}} "
f"AND created_at > now() - INTERVAL 30 DAY"
)
```
**双字段去重(第 65 行附近):**
```python
# 修改前
query = f"SELECT {c1}, {c2} FROM {table} WHERE {c1} IN {{keys:Array(String)}}"
# 修改后
query = (
f"SELECT {c1}, {c2} FROM {table} "
f"WHERE {c1} IN {{keys:Array(String)}} "
f"AND created_at > now() - INTERVAL 30 DAY"
)
```
</action>
<acceptance_criteria>
- `grep "INTERVAL 30 DAY" app/services/ingest/dedup.py` 有两处输出
- `grep "INTERVAL 30 DAY" app/services/ingest/dedup.py | wc -l` 输出为 2
</acceptance_criteria>
---
### Task 1.2: 新增 Mock 测试
<action>
创建 `tests/ingest/__init__.py`(空文件)和 `tests/ingest/test_dedup.py`
测试覆盖:
1. `test_single_field_dedup_within_30_days`30 天内有相同 job_id → 过滤duplicate=1
2. `test_single_field_dedup_outside_30_days`:先不存在 → 允许入库duplicate=0模拟 30 天外无记录)
3. `test_double_field_dedup_within_30_days`:双字段在 30 天内有记录 → 过滤
4. `test_dedup_empty_input`:空输入 → 直接返回,不查 ClickHouse
5. `test_dedup_no_dedup_columns`:无 dedup 字段 → 跳过过滤
6. `test_build_insert_row_has_channel`:验证 build_insert_row 生成的行包含 channel 列
SQL 验证:用 `mock_client.query.call_args[0][0]` 断言 SQL 中包含 `INTERVAL 30 DAY`
</action>
---
## Verification
```bash
# 1. 验证 SQL 变更
grep "INTERVAL 30 DAY" app/services/ingest/dedup.py
# 预期输出2 行
# 2. 运行新增测试
pipenv run python -m pytest tests/ingest/test_dedup.py -v
# 3. 全量回归
pipenv run python -m pytest tests/ -v --tb=short
```