Skip to content

fix(requests): serialize requests for the same title - #3380

Open
fallenbagel wants to merge 1 commit into
fix/put-season-availabilityfrom
fix/cross-user-request-lock
Open

fix(requests): serialize requests for the same title#3380
fallenbagel wants to merge 1 commit into
fix/put-season-availabilityfrom
fix/cross-user-request-lock

Conversation

@fallenbagel

@fallenbagel fallenbagel commented Aug 12, 2026

Copy link
Copy Markdown
Member

Description

Duplicate requests are already rejected and seasons another request holds are already filtered out, but both checks run well before the insert, and nothing stops a second request for the same title passing them in between. Two users asking for the same movie at the same moment both got a request, and two users asking for overlapping seasons both got the season.

Creation now takes a second lock keyed on the title, inside the per-user one. The user lock is always the outer one so the two can never be taken in opposite orders.

Unlike the per-user lock, which only ever blocks somebody racing themselves, this makes unrelated users requesting the same title wait for each other, and on auto approve that wait covers the subscriber's Radarr and Sonarr work. It is also not a quota bypass being fixed, since every user is charged correctly for what they asked for, so what this removes is duplicate rows and double-booked seasons rather than a limit anyone could exceed.

This depends on the per-user lock PR below it, where the first lock lives.

How Has This Been Tested?

  • Via the unit tests attached

Screenshots / Logs (if applicable)

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy)
  • I have updated the documentation accordingly.
  • All new and existing tests passed.
  • Successful build pnpm build
  • Translation keys pnpm i18n:extract
  • Database migration (if required)

Summary by CodeRabbit

  • Bug Fixes
    • Improved request handling to prevent duplicate movie requests from being created concurrently.
    • Prevented overlapping TV season requests from being granted to multiple people at the same time.
    • Added safeguards for concurrent requests across different video quality options.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

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

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 625b3fcd-e1b1-45fc-a0f4-5ddf6613f06d

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1d942fae-3b08-493f-aa59-5cc8119d63f6

📥 Commits

Reviewing files that changed from the base of the PR and between 97e5636 and 3931ba3.

📒 Files selected for processing (3)
  • server/entity/MediaRequest.test.ts
  • server/entity/MediaRequest.ts
  • server/utils/requestLock.ts

📝 Walkthrough

Walkthrough

The request flow now applies a media-keyed lock inside the existing user lock. Tests cover concurrent movie requests and overlapping TV season requests across users.

Changes

Media request concurrency

Layer / File(s) Summary
Media-level request locking
server/utils/requestLock.ts, server/entity/MediaRequest.ts
Adds an exported media-keyed AsyncLock. Request creation uses the media type, media ID, and 4K status as the lock key.
Concurrent movie and TV request tests
server/entity/MediaRequest.test.ts
Adds requester setup and API mock data. Tests verify duplicate movie handling and unique overlapping TV season requests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: gauthier-th

Poem

A rabbit guards each media key,
While seasons queue in harmony.
One movie request takes the prize,
Duplicate paws receive replies.
Three TV seasons safely land—
Locked with care by bunny band.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: serializing concurrent requests for the same media title.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

Copilot AI lite review requested due to automatic review settings August 12, 2026 06:02
@fallenbagel
fallenbagel force-pushed the fix/cross-user-request-lock branch from 6ff527b to 1c091ce Compare August 12, 2026 06:02

Copilot AI left a comment

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.

Pull request overview

This PR addresses cross-user concurrency issues in media requesting by adding an additional lock keyed by media identity, ensuring that “check/create/save” request flows for the same title are serialized even when initiated by different users.

Changes:

  • Introduces a new mediaLock AsyncLock keyed by media type/id/4K to serialize requests per media.
  • Wraps MediaRequest.request() with a nested media-based lock inside the existing per-user request lock.
  • Extends MediaRequest tests with cross-user concurrent-duplicate and overlapping-season scenarios.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
server/utils/requestLock.ts Exports a new mediaLock to support per-media serialization.
server/entity/MediaRequest.ts Nests a per-media lock inside the existing per-user lock when creating requests.
server/entity/MediaRequest.test.ts Adds test coverage for cross-user concurrency cases (duplicate media + overlapping seasons).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread server/entity/MediaRequest.ts Outdated
Comment thread server/utils/requestLock.ts
@fallenbagel fallenbagel changed the title fix/cross user request lock fix(requests): serialize requests for the same title Aug 12, 2026
@github-actions github-actions Bot added the merge conflict Cannot merge due to merge conflicts label Aug 12, 2026
@github-actions

This comment was marked as outdated.

@fallenbagel
fallenbagel force-pushed the fix/cross-user-request-lock branch from 1c091ce to 3931ba3 Compare August 12, 2026 06:38
@github-actions github-actions Bot removed the merge conflict Cannot merge due to merge conflicts label Aug 12, 2026
@github-actions

This comment was marked as outdated.

@github-actions github-actions Bot added the merge conflict Cannot merge due to merge conflicts label Aug 13, 2026
Copilot AI review requested due to automatic review settings August 13, 2026 05:34
@fallenbagel
fallenbagel force-pushed the fix/cross-user-request-lock branch from 3931ba3 to 7744584 Compare August 13, 2026 05:34
@github-actions github-actions Bot removed the merge conflict Cannot merge due to merge conflicts label Aug 13, 2026

This comment was marked as low quality.

Duplicates and overlapping seasons are already rejected, but both checks run
well before the insert, so two users asking for the same title at the same
moment both got through. Creation now takes a second lock keyed on the title
inside the per-user one, always in that order so the two cannot deadlock.

is4k is normalized at the same time. It is optional, and an undefined one
binds as null in the duplicate query, so an API caller that omitted it could
request the same title repeatedly.
@fallenbagel fallenbagel added this to the v3.5.0 milestone Aug 13, 2026
Copilot AI review requested due to automatic review settings August 13, 2026 05:47
@fallenbagel
fallenbagel force-pushed the fix/cross-user-request-lock branch from 7744584 to 498d920 Compare August 13, 2026 05:47
@fallenbagel
fallenbagel marked this pull request as ready for review August 13, 2026 05:47
@fallenbagel
fallenbagel requested a review from a team as a code owner August 13, 2026 05:47

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

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.

3 participants