Phase 1 — unblocked. Partial fix; full stranger pairing needs the rolling waiting room (blocked upstream).
Two ways a participant currently reaches a dead end where they cannot submit and therefore cannot be paid:
1. Unmatched in the lobby. lobbyTrial (jsPsychMultiplayerSync) is configured with no timeout, and the plugin default is null — so wait() is called unbounded. A participant who arrives and is never matched waits on that screen forever: no timeout, no on_timeout, no exit, no completion code. They close the tab and open a support ticket. Unmatched participants must still be paid; they gave up their time.
2. Spectator overflow. The spectator path shows "This game is already full" for four seconds, calls disconnect(), and ends with no completion code. The odd person out is unpaid and unable to submit.
Work
Note that ghost entries make this worse: entries are only removed on an explicit disconnect() (no heartbeat and no beforeunload in any bundle), so a closed lobby tab leaves an entry that can satisfy wait_for and produce a match with nobody. That aspect is tracked with the waiting-room issue since it mainly bites on Firebase.
See READINESS.md section 1.
Phase 1 — unblocked. Partial fix; full stranger pairing needs the rolling waiting room (blocked upstream).
Two ways a participant currently reaches a dead end where they cannot submit and therefore cannot be paid:
1. Unmatched in the lobby.
lobbyTrial(jsPsychMultiplayerSync) is configured with notimeout, and the plugin default isnull— sowait()is called unbounded. A participant who arrives and is never matched waits on that screen forever: no timeout, noon_timeout, no exit, no completion code. They close the tab and open a support ticket. Unmatched participants must still be paid; they gave up their time.2. Spectator overflow. The
spectatorpath shows "This game is already full" for four seconds, callsdisconnect(), and ends with no completion code. The odd person out is unpaid and unable to submit.Work
timeoutonlobbyTrial. Pick the value from real arrival-rate data in the pilot; start around 5 minutes.on_timeoutleads to an apologetic screen, then a no-match completion code, then prorated payment.Note that ghost entries make this worse: entries are only removed on an explicit
disconnect()(no heartbeat and nobeforeunloadin any bundle), so a closed lobby tab leaves an entry that can satisfywait_forand produce a match with nobody. That aspect is tracked with the waiting-room issue since it mainly bites on Firebase.See
READINESS.mdsection 1.