fix(perf): keep failure isolation and drain in-flight writes in fix_build_errors (review follow-up to #1336) - #1340
Conversation
…uild_errors Two correctness gaps flagged by both Copilot and CodeRabbit on #1336: 1. UnicodeDecodeError isolation. _read_source() caught only OSError, so a non-UTF-8 source file raised UnicodeDecodeError (a UnicodeError, not an OSError). It escaped _fix_one and made gather(return_exceptions=False) re-raise and cancel the sibling fixes, breaking the PR's headline failure-isolation guarantee. Broaden the read except to (OSError, UnicodeError). 2. Cancellation drain. A write already running in a worker thread via asyncio.to_thread cannot be interrupted, so cancelling mid-write returned CancelledError while the write was still live, racing a caller's cleanup or retry. Shield the write and drain it on cancellation before propagating. Adds two regression tests, both prove-failed against the pre-change source. Change is confined to fix_build_errors; the public return shape is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015F7qZu4PsmYyLtt6QbCUtQ
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Agent Completion Truth Gate: BLOCKEDReasons: Machine-readable verdict{
"details": {
"collection_errors": [
"incomplete_linked_issue_contract",
"missing_linked_issue",
"missing_closing_issue_reference",
"missing_agent_run_id",
"missing_agent_login"
],
"invalid_fields": [
"issue.number",
"policy.agent_login",
"policy.run_id"
]
},
"reasons": [
"invalid_payload"
],
"verdict": "blocked"
} |
|
CI status: the only red check is Why it's red — and why I'm not forcing it green. The gate flags this as an agent task because the branch is This PR is a review-fix stacked onto #1336, not a canonical-issue agent task, so I'm deliberately not synthesizing completion evidence to satisfy an evidence gate — that would game the exact thing the gate verifies. My branch name is fixed by the harness, so I also can't route around it the way The code itself is verified and green on the checks that test it: both reviewer-confirmed bugs are fixed, the two regression tests prove-failed against the pre-change source, and Recommendation (human governance call): merge #1285 (it improves this gate's diagnostics and is itself green/merge-ready), and either exempt harness-constrained agent follow-up branches from Generated by Claude Code |
|
Closing as superseded — the two fixes here landed directly on Genuinely useful convergence though, and one thing here was better than what I wrote, which I've adopted:
One divergence worth recording: this PR explicitly scoped out CodeRabbit's third finding (the per-invocation semaphore not bounding process-wide provider traffic) as shared-infra work. I did fix it, in Net effect: Thanks for the review pass — the handshake was a real catch. |
Canonical issue
Follow-up to #1336 (which closes #1335). This PR targets the
perf/ai-fix-parallelbranch so its diff is only the two correctness fixes below — merging it updates #1336 in place rather than opening a competing PR againstmain. No new canonical issue: it remediates review findings on #1336 raised independently by bothcopilot-pull-request-reviewerand@coderabbitai.Outcome
Two production-correctness gaps in
AICodeGenerator.fix_build_errorsare closed, restoring the failure-isolation and cancellation-safety guarantees #1336 claims:_read_source()caught onlyOSError. A non-UTF-8 source file raisesUnicodeDecodeError(aUnicodeError, not anOSError), which escaped_fix_one, madeasyncio.gather(return_exceptions=False)re-raise, and cancelled the sibling fixes. The readexceptis broadened to(OSError, UnicodeError), so an undecodable file is skipped like any other per-file read failure.await asyncio.to_thread(file_path.write_text, …)starts a write in a worker thread that a cancellation cannot interrupt. Cancelling mid-write previously returnedCancelledErrorwhile the write was still running, racing a caller's cleanup/retry. The write is now wrapped in a task,asyncio.shield-ed, and drained on cancellation beforeCancelledErrorpropagates.Scope
src/youtube_extension/backend/ai_code_generator.py(fix_build_errorsreadexcept+ write path; newimport contextlib);tests/unit/test_ai_code_generator.py(two regression tests).asyncio.Semaphoredoes not bound process-wide provider traffic, since eachAICodeGeneratorinstance gets its own 4-permit semaphore. That is an architectural change to shared router/provider infrastructure and is out of scope for this perf PR. It does not affect perf: fix build errors concurrently with bounded fan-out #1336's actual guarantee (exactly onegeneratecall per readable error file — billed LLM spend unchanged); only the "rate-limit protection" framing is broader than the per-call bound delivers. Left for a follow-up that owns shared-infra rate limiting.Risk
CancelledErrorunchanged. The public return shape (success,fixed_files,total_errors) and the one-call-per-file contract are untouched.fix_build_errorsreturns to prior behaviour. No schema or data migration.Verification
Against head
d4a510b:test_undecodable_file_does_not_abort_siblings— one file'sread_textraisesUnicodeDecodeError; asserts the other two files are still fixed and no exception escapes.test_cancellation_drains_inflight_write— blocks a write in a worker thread, cancels the task, asserts the task stays pending until the write drains (buggy code finishes immediately), then thatCancelledErrorpropagates and the drained write landed.ruff/black/mypy: added lines clean; pre-existing whole-fileF841/format/[index]findings (lines 668–711, 2057) are not touched, matching perf: fix build errors concurrently with bounded fan-out #1336's tight-diff posture.Production evidence
Not applicable — backend change to an internal code-repair path with no HTTP surface.
DeploymentManager.verify_and_fix_projectis the caller; its suite (test_deployment_manager.py) is green in the run above.Agent handoff
mainis left to a humanGenerated by Claude Code