fix(queue): guard ISSUE_CLOSURE solvedByPr write with state = CLOSED#221
Open
rsnetworkinginc wants to merge 1 commit into
Open
fix(queue): guard ISSUE_CLOSURE solvedByPr write with state = CLOSED#221rsnetworkinginc wants to merge 1 commit into
rsnetworkinginc wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The async
ISSUE_CLOSUREfetch job can writeissues.solved_by_pronto an issuethat has already been reopened.
handleIssueClosurereads issue state once, does aslow GraphQL timeline fetch (
fetchIssueClosingPr), and then writessolvedByPrunconditionally. If an
issues.reopenedwebhook lands during that fetch, itshandler upserts
state = OPENand clearssolved_by_pr, but the in-flight job thenclobbers that clear and leaves an OPEN issue carrying a solver-PR link.
This corrupts issue-discovery scoring inputs: an OPEN issue can be counted as solved
(or skew credibility ratios) until a later webhook/backfill happens to correct it.
Root cause
packages/das/src/queue/fetch.processor.ts—handleIssueClosure()readsissue.stateonce, then performs the slow GraphQL fetch, then writes:with no re-check of state — a classic read-then-write race against the synchronous
reopen path in
IssueHandler.Fix
Guard the final write with
state = 'CLOSED'in the update criteria, so the writebecomes a no-op if the issue was reopened while the GraphQL fetch was in flight:
This is the
UPDATE … WHERE state = 'CLOSED'direction suggested in the issue. It isa single-statement conditional update (no extra round-trip, no schema change) and does
not touch the reopen webhook path. Distinct from #188/#189 (frozen
closed_atattribution) and #24 (the reopen clear itself) — this closes the concurrency window
that lets attribution reappear after that clear.
Tests
Added regression coverage in
fetch.processor.spec.ts, driven through the publicprocess()entry point with an in-memory Issue repository whoseupdatehonours thecriteria like SQL
WHERE:state = OPENmid-flight;asserts the issue stays OPEN with
solved_by_pr = nulland that the final write isguarded by
state: "CLOSED". This test fails on the pre-fix code (the OPEN issuegets
solved_by_pr = 123) and passes with the guard.solved_by_prwritten.Verification
npm run lint— cleannpm run format:check— cleannpm test— 27/27 pass (RED→GREEN on the new race test)npm run build— cleanCloses #199