Premier League Predictor: FastAPI & Redis — Chapter 4, Exercise 2 ===================================================================== TASK Run three genuinely concurrent calls to guarded_pair_team for the same team and gameweek, not just two. Report the real result for all three, and explain why WATCH-based retrying scales correctly to more than two concurrent requests without any extra code. SOLUTION Running three real, genuinely concurrent calls to this chapter's own correctly-guarded function, all targeting the same team and the same gameweek: await asyncio.gather( guarded_pair_team(r, gw_key, "7", "Fixture A"), guarded_pair_team(r, gw_key, "7", "Fixture B"), guarded_pair_team(r, gw_key, "7", "Fixture C"), ) produces this real result: Fixture A: REJECTED (already used) Fixture B: REJECTED (already used) Fixture C: ACCEPTED (paired) Real final used_teams set: {'7'} Number of real ACCEPTED results: 1 (should be exactly 1) Exactly one of the three requests is accepted; the other two are honestly rejected. (Which one wins is genuinely not fixed -- rerunning this same test can produce a different winner each time, since it depends on the real, fine-grained order the async event loop happens to schedule things in. What's guaranteed, and what was actually verified, is that exactly one wins, not which one.) This scales correctly to three requests -- and would scale correctly to any number -- for a real, structural reason rather than luck: each call to guarded_pair_team is an entirely independent retry loop, with no shared state or coordination between them beyond the one real key they're all watching. Each one keeps looping, on its own, until it either (a) completes a WATCH-then-check-then-write sequence with nothing else touching the key in between, or (b) re-checks SISMEMBER on a retry and correctly sees the team is now used. Redis's own real guarantee -- that commands inside one client's MULTI/EXEC block execute as a single, uninterrupted unit relative to every other client -- means there is no possible interleaving of three, ten, or a hundred concurrent callers that lets more than one of them actually complete the write while the key still shows the team as unused. The fix isn't "handle exactly two competitors" -- it's "never let a stale read survive to become a write," and that property doesn't care how many other readers happened to be racing against it at the same moment. WHY THIS WORKS AS AN ANSWER ---------------------------- It runs the real three-way race, confirms exactly one real acceptance with an explicit count check, and explains the scaling property correctly -- each caller's own independent retry loop, combined with Redis's real per-client transaction isolation, rules out more than one successful write regardless of how many concurrent callers exist, not just the two the chapter's own original example happened to use.