Public: anyone can read this; the crew can change it.

forked from trevato/cs

A result that did not land says so and is tried again, instead of vanishing #203

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Pushed. `bun run test` (typecheck + 900 tests) passes and the bundles are rebuilt.

shipped production is serving it deploy ae07c2d

opened this

Pushed. bun run test (typecheck + 900 tests) passes and the bundles are rebuilt.

---

A round that did not land now says so and is tried again instead of vanishing. postResult in src/client/main.ts no longer drops everything that is not response.ok: the frame keeps the one round that has not been accepted — the bytes of the newest result, never a queue, so a retry can never put a stale snapshot over newer numbers — and sends it again on the next round's post and from the frame loop once its backoff is up, with at most one attempt in flight and four attempts in all. A fresh round waits for no backoff (a match scores one every few minutes); only retries do, doubling from 2s, which is what keeps a 429 from being answered with a flood.

src/client/pending.ts is the policy alone, plain data in and out: 429, 5xx and a fetch that never answered are this moment and worth another attempt; 422, 409, 400, 403 and 413 are this round and are not retried. It also holds the sentences — three states in four lines: saved, not saved yet and retrying, refused by the server, or unreachable and given up after the cap. src/pages/game.ts renders that line under #stats as role="status" aria-live="polite", outside the section because a saved result replaces that whole section with the leaderboard the server sends back, and it is served holding the sentence that is true before anything is posted, so nothing moves when it is filled in.

What to look at: main.test.ts boots the stub host against a fetch that throws then succeeds, one that answers 429 then 200, one that answers 422, a round that is replaced while it is unsent, and a match that ends offline — each asserting the exact line shown and the number of attempts made, including that thirty frames after a 429 make no request at all. pending.test.ts pins the rules themselves. Two existing tests gained an await between rounds: posts are serialised now (one attempt in flight), and those two stepped frames without ever letting a promise settle — the behaviour they assert is unchanged. The app bundle grew 875 raw / 601 gzipped bytes, mostly the sentences a minifier cannot shorten, and fits its ceiling with 2,286 raw to spare; no ceiling moved. Nothing is kept across a visit: a round that never reaches the server before the tab closes is gone, and the line says that rather than promising a queue in storage.

🤖 Generated with Claude Code

Closes #102

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs