Skip to content

fix(#5450): bars sync 已是最新时不抛 ValueError 静默 proc=0#6270

Merged
Kaoruha merged 2 commits into
masterfrom
6241-fix/bars-sync-zero
Jun 27, 2026
Merged

fix(#5450): bars sync 已是最新时不抛 ValueError 静默 proc=0#6270
Kaoruha merged 2 commits into
masterfrom
6241-fix/bars-sync-zero

Conversation

@Kaoruha

@Kaoruha Kaoruha commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

修复 #5450POST /api/v1/data/sync {type:bars, codes:["000001.SZ"]} 始终 proc=0/added=0/updated=0,而 600519.SH 正常 proc=1

根因

调用链:sync_databar_service.sync_smart(code, fast_mode=True)_get_fetch_date_rangesync_range_validate_and_set_date_range

fast_mode 下 _get_fetch_date_range(bar_service.py:907-912):

latest_timestamp_result = self.get_latest_timestamp(code, frequency)
if latest_timestamp_result.success and latest_timestamp_result.data:
    start_date = latest_timestamp_result.data + timedelta(days=1)
end_date = datetime.now()

000001.SZ 库中最新 bars 已是今天(高频更新)→ start_date = 明天 > end_date = 今天_validate_and_set_date_range(bar_service.py:1059)抛 ValueError: Start date ... cannot be later than end date → sync_smart 的 except(bar_service.py:303)吞异常 → ServiceResult.error → API _record_sync_resultrecord_fail(processed=0)

600519.SH 最新数据较早 → start ≤ end → 正常 fetch proc=1

影响范围:任何"数据已更新到今天"的 code 同步都会触发(普遍逻辑缺陷,非 000001.SZ 独有)。

修复

sync_smart_get_fetch_date_range 之后加守卫:fast_mode and start_date > end_date 时返回明确的"已是最新"结果,不进 sync_range:

if fast_mode and start_date > end_date:
    up_to_date_result = DataSyncResult.create_for_entity(
        entity_type="bars", entity_identifier=code, sync_strategy="smart")
    up_to_date_result.set_metadata("reason", "already_up_to_date")
    return ServiceResult.success(
        data=up_to_date_result,
        message=f"{code} 数据已是最新,无需同步")

满足验收标准 2("数据已最新时说明为何 0 records")。API 层 _record_sync_resultrecord_fail 改善为 record_complete(partial) + 明确 message,不再有误导性的 "Start date cannot be later than end date" 错误。

Test plan

  • test_fast_mode_data_up_to_date_returns_already_latest:fast_mode + latest=今天 → success + message 含"最新" + data_source 不被调用 + records_processed=0
  • test_fast_mode_data_up_to_date_metadata_reason:metadata(reason=already_up_to_date)
  • 既有 test_bar_service_mock.py 17 测试不回归(19 passed)
GINKGO_DEBUG_MODE=TRUE PYTHONPATH=$(pwd):$(pwd)/src python -m pytest \
  tests/unit/data/services/test_bar_service_mock.py -o "addopts=" -q
# 19 passed

Closes #5450

fast_mode 下库中最新 timestamp 已到今天时,_get_fetch_date_range 算出
start_date=明天 > end_date=今天,_validate_and_set_date_range 抛 ValueError
被 sync_smart except 吞成 ServiceResult.error,sync_history 记 proc=0 无说明。

修复: sync_smart 在 _get_fetch_date_range 后加守卫,start_date>end_date 时
返回 success + '已是最新' message + metadata(reason=already_up_to_date),
不再让空范围 ValueError 冒泡。

@Kaoruha Kaoruha left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

@Kaoruha

Kaoruha commented Jun 22, 2026

Copy link
Copy Markdown
Owner Author

Code review

Found 1 issue:

  1. 验收标准 2 端到端未满足 + body 声明不实 (issue bug: Bars sync for 000001.SZ always processes 0 records despite data existing #5450: "If data is already up-to-date, status message explains why 0 records were processed")

service 层守卫本身正确(返回 ServiceResult.success(message="...已是最新") + set_metadata("reason","already_up_to_date")),但 API 层 _record_sync_result 把这两者都丢弃了:调 record_complete不传 message,也不读 dsr.metadatadsr.records_processed=0/skipped=0has_meaningful_output=Falsestatus="partial"。用户查 sync_history 仍见 status=partial, proc=0无"已是最新"说明 —— issue 核心痛点 "rather than silently reporting 0 records" 在用户可见层未解决。PR body 声称 "API 层 _record_sync_result ... + 明确 message" 与代码现实矛盾(record_complete 签名无 message 参数)。需在 _record_sync_result 透传 result.messagedsr.metadata["reason"] 到 sync_history 记录。

GinkGO/api/api/data.py

Lines 586 to 595 in 00267a3

service.record_complete(
uuid=record_uuid,
status=status,
duration_ms=duration_ms,
records_processed=dsr.records_processed,
records_added=dsr.records_added,
records_updated=dsr.records_updated,
records_failed=dsr.records_failed,
sync_strategy=getattr(dsr, 'sync_strategy', ''),
)


建设性建议(非 blocking,供补全时一并考虑)

  1. DataSyncResult 字段与 tick_service 同型守卫不对齐:tick_service.py:849 的"已是最新"守卫完整设了 sync_range/records_skipped/is_idempotent/sync_duration,本 PR 守卫仅设 entity_type/identifier/strategy + metadata。_record_sync_result 虽不读这些字段,但仪表盘若读 sync_duration/sync_range 此路径会拿 null,建议对齐。

  2. 守卫用 > 而 tick_service 用 >=(tick_service.py:849):end=datetime.now()(时分秒) 与 start=latest+1整天 精确相等概率极低,但建议对齐 >= 消除理论边界缺口。

  3. 测试仅 000001.SZ,缺 600519.SH 对比(issue 验收4 "common codes 000001.SZ, 600519.SH, etc."):建议补"工作正常的 code 仍正常"对比测试防回归。

service 层修复方向正确(不再 ValueError 吞成 fail),3 层分层合规,DataSyncResult API 复用既有模式。补 API 层透传即可端到端满足 #5450

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

service 层(PR #6270 守卫)对"已是最新"返回 ServiceResult.success(message=...,
data=DataSyncResult(metadata reason=already_up_to_date)),但 API 层
_record_sync_result 不读 dsr.metadata.reason 也不透传 result.message,
sync_history 仍记 status=partial/proc=0 无说明,验收标准 2 端到端未满足
(review on PR #6270 定位的 blocking)。

修:_record_sync_result success 分支前置检测 dsr.metadata.reason,
带 reason(如 already_up_to_date)→status=success + result.message 透传到
error_message(model 唯一 Text 字段,get_history 端到端返回),不加 schema
字段避免 DB 安全阀。

测试:tests/api/test_data_sync_result_record.py 2 例(已是最新→success+
说明透传;正常成功→error_message 不污染)。

Co-Authored-By: Claude <noreply@anthropic.com>
@Kaoruha

Kaoruha commented Jun 22, 2026

Copy link
Copy Markdown
Owner Author

续修 review blocking(commit 4ea5844c):service 层守卫返回的 message + metadata(reason=already_up_to_date) 此前在 API 层 _record_sync_result 被丢弃。本次在该函数 success 分支前置检测 dsr.metadata.reason,带 reason→status=success + result.message 透传 error_message(端到端经 get_sync_history 可见)。详见 issue #5450。\n\n权衡:复用 error_message 字段存'已是最新'说明(语义从'失败原因'扩展为'状态说明'),避免加 schema 字段触发 DB 安全阀。3 层 smoke 全绿。

@Kaoruha
Kaoruha merged commit dfde456 into master Jun 27, 2026
2 checks passed
@Kaoruha
Kaoruha deleted the 6241-fix/bars-sync-zero branch June 27, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Bars sync for 000001.SZ always processes 0 records despite data existing

1 participant