fix: stream cold-start history into decision state

This commit is contained in:
CoolBoy
2026-09-04 11:20:51 +08:00
parent d60551e130
commit 54ed4351a0
7 changed files with 538 additions and 58 deletions

View File

@@ -537,31 +537,33 @@ class OutcomeTracker:
< FAILURE_ENRICHMENT_MAX_ATTEMPTS
)
]
candidates.sort(key=_outcome_record_timestamp, reverse=True)
# The current streamed page must be classified before it is folded
# into the checkpoint. Older retryable rows are secondary; otherwise
# they could consume the batch budget and make the backfill forget a
# newly imported failure without ever inspecting its log.
candidates.sort(
key=lambda record: (
str(record.get("taskId") or "") in seen_task_ids,
_outcome_record_timestamp(record),
),
reverse=True,
)
if enrichment_limit > 0:
candidates = candidates[:enrichment_limit]
self._last_sync_time = utc_now()
self._rebuild_failed_index()
if imported or refreshed:
self.save()
candidate_task_ids = [
str(record["taskId"])
for record in candidates
if record.get("taskId") is not None
]
enrichment_attempts = 0
classified_total = 0
errors_total = 0
batch_size = 200
total_candidates = len(candidate_task_ids)
total_candidates = len(candidates)
for offset in range(0, total_candidates, batch_size):
batch_ids = candidate_task_ids[offset : offset + batch_size]
batch_records = [
self._by_task_id[task_id]
for task_id in batch_ids
if task_id in self._by_task_id
]
# Keep direct references until classification completes. Calling
# save() may compact terminal rows into the aggregate checkpoint;
# looking them up by task ID afterwards would silently drop older
# failure logs from a large import batch.
batch_records = candidates[offset : offset + batch_size]
def progress(
completed: int,
@@ -590,6 +592,8 @@ class OutcomeTracker:
errors_total += sum(
1 for record in batch_records if record.get("failureEnrichmentError")
)
if imported or refreshed or candidates:
self._rebuild_failed_index()
self.save()
@@ -612,6 +616,11 @@ class OutcomeTracker:
"recoveredFrameworks": recovered_frameworks,
}
def compact_decision_state(self) -> bool:
"""Fold terminal rows into the bounded aggregate checkpoint now."""
self.save()
return self._compact_if_needed(force=True)
@staticmethod
def _enrich_history_task(
task: dict[str, Any],