Skip to content

Meetups: a join aborted by the crowd waits and tries again - #321

Merged
renrenmimi merged 1 commit into
mainfrom
functions/join-meetup-under-contention
Oct 14, 2026
Merged

renrenmimi merged 1 commit into
mainfrom
functions/join-meetup-under-contention

Conversation

@renrenmimi

Copy link
Copy Markdown
Owner

Everyone joining one meetup reads and writes the same meetup document.

On the test project, 199 people joined a meetup for twenty at once. Two joins were aborted for contention after the client library's own retries, so those two people were told internal instead of that the meetup was full. An earlier run of the same race had no errors, so it comes and goes.

The fix:

  • joinMeetupCallable now runs its transaction through retryOnContention, which waits and tries again.
  • runEventOnce already had that loop; it moves out into shared.ts so both share it.
  • Running a join again is safe, because someone already on the roster is answered as joined.

Tests. Two new emulator tests. Each makes the transactions that read the meetup end as if the library had given up for contention, and leaves the rate limit's transaction alone.

  • After three aborted tries, the person joins once and the count goes up by one.
  • When every try is aborted, the join still fails after the retries, and nothing is written.

Both tests fail on the old code. The full suite passes: 290 tests.

On the test project, with this deployed, the 200-person race: 180 told "Meetup is full.", 0 errors.

🤖 Generated with Claude Code

Everyone joining one meetup reads and writes the same document. On the
test project, 199 people joined a meetup for twenty at once, and two of
the joins were aborted for contention after the client library's own
retries. Those two were told "internal" instead of that the meetup was
full.

The join now runs through retryOnContention, the wait-and-try-again that
runEventOnce already used, moved out so both share it. Running a join
again is safe: someone already on the roster is answered as joined.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pet-note Ready Ready Preview Oct 14, 2026 8:32pm UTC

Copilot AI balanced review requested due to automatic review settings October 14, 2026 20:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T20:34:15.616444Z 3c600bb PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c600bbd18

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +86 to +87
afterAll(async () => {
await purge(MEETUP, `users/${ORGANIZER}`, `users/${JOINER}`, `pets/${petId}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clean up every generated pet after each test

Each beforeEach creates a new random pet, but this afterAll deletes only the ID from the final test, leaving the first test's pet behind. When this test file is rerun against the same emulator, those leaked pets accumulate for jc-joiner until createPetCallable reaches its five-pet limit and the setup starts failing; delete the current pet in afterEach or retain and purge all generated IDs.

Useful? React with 👍 / 👎.

@renrenmimi
renrenmimi merged commit 38006c8 into main Oct 14, 2026
6 checks passed

This branch was successfully deployed

1 active deployment
Preview — 3c600bbd Deployed Oct 14, 2026 by vercel[bot]
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