Skip to content

feat: 670 per reviewer skip - #893

Open
calebmcquaid wants to merge 3 commits into
caleb/670-weighted-job-priorityfrom
caleb/670-per-reviewer-skip
Open

feat: 670 per reviewer skip#893
calebmcquaid wants to merge 3 commits into
caleb/670-weighted-job-priorityfrom
caleb/670-per-reviewer-skip

Conversation

@calebmcquaid

Copy link
Copy Markdown
Contributor

Context & Requests for Reviewers

Part 3 of 3 for #670. Previously, skipping a job just released the lock. The job came right back to the same reviewer, and skip was two separate client calls (logSkip + releaseJobLock) that could partially fail.

  • Skip is now one server-side operation: logSkip atomically logs the skip, records the job in a per-reviewer Redis skip set (sorted set scored by expiry, with a TTL backstop), and releases the lock. The client's separate ReleaseJobLock call is removed.
  • Dequeue steps past skipped jobs for that reviewer only: the scan holds skipped jobs aside under the reviewer's lock token and releases them in a finally, so they return to the shared pool immediately for everyone else.
  • getNextJob now uses block: false, so a drained queue returns null immediately instead of long-polling and hanging the reviewer's request.
  • UI: skip failures show a retry modal instead of failing silently; when no reviewable job remains (drained, or everything left is skipped by this reviewer), the reviewer is redirected to the queue list instead of a perpetual spinner.

Review focus: the held-aside-then-release pattern in dequeueNextJobWithLock, particularly lock-token semantics (the token is the reviewer's userId) and what happens if the release in finally partially fails.

Tests

  • QueueOperations.reviewerSkips.test.ts — skip set recording/expiry, dequeue filtering per reviewer, held-aside jobs released for other reviewers.

Checklist

  • If you changed anything user-facing (i.e. user interface or APIs):
    Did you update the CHANGELOG.md and related docs?

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ffdcf871-af86-423f-a014-b5c92d6798c6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch caleb/670-per-reviewer-skip

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@calebmcquaid calebmcquaid changed the title Caleb/670 per reviewer skip feat: 670 per reviewer skip Jul 7, 2026
);
selectedRelatedActionsSetter(actions);
};
const setSelectedRelatedActions = useCallback(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

are you adding useCallback in response to an observed performance issue, or is it hypothetical?

);
selectedRelatedActionsSetter(actions);
},
[actionStore],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should we not have selectedRelatedActionsSetter in the dependency array, too?

setSelectedRelatedActions([]);
setDecisionReason(undefined);
};
}, [setSelectedRelatedActions]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why does this dependency array only have one of the functions?

Comment thread CHANGELOG.md

**Full Changelog**: https://github.com/roostorg/coop/compare/1.0.2...main

## Review Console

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(as in another PR) we should probably decide how we want to handle the changelog, i.e. writing to it per-PR or manually writing it all once in a while

cc @cassidyjames

});
// Release the reviewer's lock (the lock token is the reviewer's userId)
// so the job returns to the shared pool immediately for everyone else.
await this.releaseJobLock({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

are there any cases where we'd want to record a skip and not release the job lock? i can't think of any!

so if that's the case, can we call releaseJobLock from inside recordReviewerSkip? that way, callers won't have to remember to also release the lock manually each time they call it

jobId: held.data.id,
lockToken,
jobId: convertedJob.data.id,
}).catch(() => {});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

the silent error catching is a little worrying! seems like we should at the very least log that, but i think it's fine to raise an exception here.

return null;
}

static readonly REVIEWER_SKIP_TTL_MS = 30 * 60 * 1000;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmm, how come we only skip for 30 minutes?

i guess in general -- what's the user story we imagine when someone skips a job? is it "i am not qualified to review this", "this is a hard job and i don't wanna deal with it / lower my average handling time by taking it", or something else? cc @julietshen

queue,
user,
mrtService: container.ManualReviewToolService,
cleanup: async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you use the new transactional-backed test setup so we don't need to do the cleanup manually?

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.

2 participants