Repository navigation
Conversation
mroderick
force-pushed
the
feat/post-close-rsvp-waitlist
branch
from
October 9, 2026 07:55
43cdb71 to
83bc64f
Compare
Adds the two time gates from issue codebar#2990. waitlist_closes_at is the earlier of the custom RSVP close time and the freeze, so new joins stop at the configured close. cancellations_open? tracks the freeze alone, so a member may cancel after the close and until the freeze. The freeze is the hard cutoff 3.5 hours before the start, requirement 4 of the issue, and rsvp_freezes_at owns that offset alone. The RSVP flows that apply these gates follow in the next commit.
A cancel frees a seat only when the invitation held one, so rejecting an invitation that never answered must not consume a waiting-list entry. release_seat claims the seat with a row-locked read-modify-write, so duplicate concurrent cancels free it once. promote_next pops the head in a transaction with FOR UPDATE SKIP LOCKED so concurrent promoters take different entries, and confirms with update! so a failed confirmation rolls the pop back instead of emailing a spot that was never granted. The FIFO order and the seat-freed rule are pinned by specs. The locking behaviour cannot be exercised by the single-threaded suite, so this message is where it is recorded. WaitingList.next_spot still serves the current RSVP flows until the next commit replaces it.
…eeze Once the custom RSVP close time passes, new joins to the main list and the waiting list stay blocked, while main-list members may cancel until the freeze. Each cancel that frees a seat promotes the first auto-RSVP waiting-list entry in created order. Admin removals use the same promotion path while the workshop is in the future. This commit replaces WaitingList.next_spot in the RSVP flows and removes it, now that promote_next covers it. The end-to-end pins cover the reject path, the admin removal path, and the waitlist join and leave gates.
mroderick
force-pushed
the
feat/post-close-rsvp-waitlist
branch
from
October 9, 2026 09:05
83bc64f to
0d1a071
Compare
mroderick
marked this pull request as ready for review
October 9, 2026 09:16
| return unless next_spot | ||
|
|
||
| invitation = next_spot.invitation | ||
| next_spot.destroy |
Contributor
There was a problem hiding this comment.
as we're using update! on line :37 I think it makes sense to also hard error if a record doesn't get destroyed by using destroy! here
Collaborator
Author
There was a problem hiding this comment.
Changed to destroy! in f3f1988. It fixes more than style: promote_next already raises through update! when confirming the invitation fails, so a silent destroy failure would leave the entry on the waiting list while the invitation becomes attending. The entry would stay at the head of the list and a later promotion could confirm the same invitation again. destroy! raises and rolls the transaction back instead.
Thank you 🙏
promote_next already raises through update! when confirming the invitation fails, so a silent destroy failure left the entry on the waitlist while the invitation became attending, allowing a repeat promotion and duplicate attending email. destroy! rolls the whole transaction back instead.
This branch has not been deployed
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.
Once a custom RSVP close time passes, members on the main list can still cancel, and each cancellation fills the freed seat from the waiting list until a hard freeze 3.5 hours before the workshop starts. New joins stay blocked from the close time onward. Closes #2990.
Review notes
release_seatclaims the seat under a row lock, andWaitingList.promote_nextpops the head in a transaction withFOR UPDATE SKIP LOCKED. The two must stay consistent: a repeated cancel must not free the same seat twice, and two promotions must not take the same entry. Test suites cannot prove that interleaving, so this part needs the closest read.Behaviour by action
The cross-role promotion spec calls
promote_next. This change replacesWaitingList.next_spotwithpromote_next, which confirms the invitation and removes the waiting-list entry in one step.