fix(tests): wait for provider embedding batch completion before assertions - #1044
fix(tests): wait for provider embedding batch completion before assertions#1044seonghobae wants to merge 4 commits into
Conversation
…tions
test_unknown_tokenizer_byte_bound_never_becomes_recorded_usage and
test_unknown_tokenizer_uses_authoritative_provider_usage each build a
CostRoutingCoordinator with a non-mock ("https://...") embedding agent,
which selects the async ProviderEmbeddingBatchBackend
(CostRoutingCoordinator.__init__, remote_embedding_agents branch). That
backend executes its runner in a background ThreadPoolExecutor thread
(ProviderEmbeddingBatchBackend._run_job).
complete_embeddings_batch()'s docstring is explicit: "Local backends
complete immediately. Callers that require a synchronous provider result
pass wait_timeout." Both tests called it with no wait_timeout, so nothing
blocked the calling thread until the background job finished. Most runs
win the race because the synthetic runner is near-instant, but under load
the calling thread can reach embeddings_batch_document() while the job is
still "running" -- _embeddings_batch_document_locked's not-is_complete
early return omits total_tokens (and embeddings, cost_micro_usd, etc.)
entirely, which is exactly the reported
KeyError: 'total_tokens' on PR #992's "Full unit and contract suite"
check (base c594b68, head 0e48301).
Deterministically reproduced the race locally (blocking runner + no
wait_timeout => total_tokens missing; same call + wait_timeout => complete
document), and confirmed the failure is present identically with or
without this diff on unmodified main -- it is unrelated to any particular
input's Unicode content (any of the three parametrize cases could lose the
race). The fix passes wait_timeout=1, matching the pattern every other
provider-backed complete_embeddings_batch() call in this file already
uses (e.g. test_runtime_added_remote_embedding_member_uses_provider_backend,
test_provider_embedding_requests_are_sharded_by_the_existing_token_limit).
No production code changed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughProvider 임베딩 배치 테스트가 백그라운드 작업 완료까지 대기하도록 수정되었습니다. 관련 테스트에는 비동기 완료와 문서 기록 사이의 스케줄링 경합을 설명하는 주석이 추가되었습니다. ChangesProvider 임베딩 배치 테스트
Estimated code review effort: 1 (매우 간단) | ~5분 Merge Risk: ⚪ Minimal · up to Provider embedding batch tests now wait for asynchronous work to complete before checking recorded token usage, eliminating the timing-related test failure without changing production behavior. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…tions Ports the identical fix from #1044 (not yet merged) into this PR's head, per the standing PR-governance rule to port the same change now rather than wait on a separate PR to merge. PR #1002's "Full unit and contract suite" check failed on its current head with exactly one failure, unrelated to this PR's own diff: FAILED tests/test_provider_embedding_batch_backend.py::test_unknown_tokenizer_byte_bound_never_becomes_recorded_usage[한글🙂é] - KeyError: 'total_tokens' 1 failed, 3400 passed, 2 skipped Root cause (from #1044): both test_unknown_tokenizer_uses_authoritative_provider_usage and test_unknown_tokenizer_byte_bound_never_becomes_recorded_usage call complete_embeddings_batch() on a provider-backed (non-mock) embedding agent without wait_timeout. That backend completes asynchronously in a background ThreadPoolExecutor thread, so without wait_timeout the calling thread can read the document before the job finishes, hitting the not-is_complete early-return branch that omits total_tokens entirely. Under CI load this triggers intermittently; the failing Unicode parametrize case is incidental, not causal. Test-only change, no production code touched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
Hourly loop check-in — 2026-09-04Progress toward green: none since creation ( Duplicate-effort note: PR #1025 ( Generated by Claude Code |
|
Adjudication evidence (host 1 session, 2026-09-06 KST; full report with commands in #1080). Nothing here closes, flips, or retargets anything — the decision is the opener's. Near-duplicate of #1025 (same |
|
CI note and push: head The two red checks on the previous head were org-wide classes, not this diff's: Local gate on the merged tree ( Generated by Claude Code |
|
CI note on head Generated by Claude Code |
|
CI note on head
Supporting evidence from artifact
Neither is this diff's, so nothing to push. The Noema verdict is a content rejection on a specific model output, not a defect in the embedding-batch change; a fresh run may well produce a valid verdict from the same pool, but this PR's re-run allowance stays unspent until the queue is shallower — the run took 32 minutes and the pool is now rate-limited again. Generated by Claude Code |
What
Fixes a race condition in two tests in
tests/test_provider_embedding_batch_backend.py:test_unknown_tokenizer_uses_authoritative_provider_usageandtest_unknown_tokenizer_byte_bound_never_becomes_recorded_usage.What surfaced it
PR #992 ("docs(gap): record isolated application service boundary" — a docs-only PR that does
not touch any embedding/token-counting code) failed its "Full unit and contract suite" check on
head
0e483013ced2705a027576717c5dd5e0fd1609e9(basemain@c594b682) with exactly one failure:Only one of the three parametrized inputs was reported as failed, which looked at first like a
Unicode-specific bug in the "unavailable tokenizer byte-bound" fallback path.
Root cause
It is not content-dependent — it is a genuine race condition, unrelated to which parametrize
case runs.
Both tests build a
CostRoutingCoordinatorwith a non-mock (https://...) embedding agent.CostRoutingCoordinator.__init__'sremote_embedding_agentsbranch selects the asyncProviderEmbeddingBatchBackend, whose_run_jobexecutes the runner in a backgroundThreadPoolExecutorthread rather than inline.complete_embeddings_batch()'s own docstring says so explicitly: "Local backends completeimmediately. Callers that require a synchronous provider result pass
wait_timeout; a timed-outqueued job is cancelled so the synchronous surface does not leave orphaned work." Both tests
called
complete_embeddings_batch(...)with nowait_timeout, so nothing blocked the callingthread until the background job actually finished.
Most runs "win" the race because the synthetic runner returns near-instantly, but under CI load
(a 710s, 3389-test run) the calling thread can reach
embeddings_batch_document()while the jobis still
"running".CostRoutingCoordinator._embeddings_batch_document_locked'snot-
is_completeearly return produces a document with onlybatch_id/status/backend/model/embeddings—total_tokens(andcost_micro_usd, etc.) is simply absent — which isexactly the reported
KeyError: 'total_tokens'.Every other provider-backed
complete_embeddings_batch()call in the same test file alreadypasses
wait_timeoutfor this reason (e.g.test_runtime_added_remote_embedding_member_uses_provider_backend,test_provider_embedding_requests_are_sharded_by_the_existing_token_limit), andtest_unknown_tokenizer_rejects_missing_provider_usageexplicitly polls instead of relying onsynchronous completion — these two tests were the only outliers.
Verification
wait_timeout,complete_embeddings_batch()returns a document missingtotal_tokenswhilethe job is still
"running"; withwait_timeout=1, the document is"completed"with thecorrect
total_tokens. Confirmed the input text's specific Unicode content is irrelevant tothe mechanism.
main(git stashbefore/after) —not introduced or masked by this diff, and unrelated to PR docs(gap): record isolated application service boundary #992's own (docs-only) changes.
tests/test_provider_embedding_batch_backend.py(all 20 tests) — passing, repeated 5x.pytest -k "embedding or token_counting or cost_router"— 261 passed, 1 skipped.python -m pytest -q, Python 3.12) — 3388 passed, 2 skipped, 2 failed; bothfailures (
test_psychometric_routing.py::test_fast_mlsirm_fit_uses_judge_acceptance_item_for_context_score,test_spend_analytics.py::test_exact_output_without_prompt_usage_is_explicitly_unavailable) arepre-existing local-sandbox artifacts unrelated to this change (this sandbox's git proxy could
not fetch the
fast-mlsirmRust wheel through the normaluv run --lockedpath, so the venvused here was hand-assembled and is missing native pieces real CI has); both reproduce
identically on vanilla
mainwith this diff stashed out, so they are not caused by this PR.No production code changed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
Generated by Claude Code
Summary by CodeRabbit