Repository navigation
Crews: start one, invite people, compete as a group - #114
Conversation
A crew is a name, an invite link and the people who chose to join. Each crew page has its own weekly board of members, and crews are ranked against each other on /crews by their members' verified ships, the same ship_events rows the leaderboard reads, so a crew can never show a ship the main board does not. A ship counts for a crew in any week its author was a member, joining and leaving weeks included. Memberships are never deleted, so a week that has been shown keeps the members who earned it, and rejoining in the same week cannot count a ship twice. Joining needs the invite link, or one click on an open crew. Up to 3 crews per person and 50 per crew, both enforced inside the insert so parallel joins cannot pass them. A crew needs 2 members to be ranked. Owners can open or close the crew, rename it, reset the link, remove a member, hand it over, or delete it; an owner cannot leave without handing over first. The top bar gains crews, and profiles list the crews someone is in. No CLI change.
The board walked every ship for every crew and checked membership row by row: 1.6s for all time at five times today's data. It now starts from the memberships and reads each person's ships through the (user, day) index, 80ms on the same data and identical totals for all 150 crews in every window. Someone outside a crew was offered a leave page; a crew link typed in capitals was a JSON 404; and the remove confirmation said a removed member needs a new invite, when the current link still lets them back.
|
Pre-prod review, fixed in a38c42e: Speed. Measured at about 5x production size (20k ship_events, 150 crews, 2.5k memberships). The board walked every ship for every crew. It now starts from memberships and reads ships through the
For comparison, the leaderboard takes 25ms on the same data. The old and new queries were compared on that dataset and give identical totals for all 150 crews in the all-time, this-week and this-month windows (0 mismatches). Behaviour fixes:
Checks: each new scenario failed before its fix. e2e passes 51/51 and Remote D1 has only Known deviation from the prototype: signing in from "join with GitHub" brings you back to the crew or invite page with the join button, so joining takes one more click. Joining on the way back would mean a GET that changes data, which is the thing the same-origin checks exist to prevent. |
Second of two PRs for crews, following #113 (web sign-in). It is all server and web, with no CLI change and no npm release, so it works for every user on every version.
What it adds
/crewsopentag./crews/new/crew/<slug>/join/<code>/@handleThe top bar gains crews. On screens 420px wide or narrower the bar shows only ◆, so it fits with the account controls.
Rules
ship_eventsrows as the leaderboard, so a crew can never show a ship the main board doesn't.left_at), so a week that has been shown never changes. The check usesEXISTS, so rejoining in the same week cannot count a ship twice.INSERT ... SELECTitself, so parallel requests can't get past them. A crew needs 2 members to be ranked.default-src 'self'.Tests
server/e2e/crews.mjsruns against a local worker and a stand-in GitHub; the file header has the command line. 48 of 48 pass, and the run was repeated 6 times clean. Againstmainit fails from the first check.Other checks:
e2e/web-signin.mjsstill passes 26 of 26.npm testpasses 149/149, and the server typecheck is clean.Limits of the testing:
INSERT ... SELECT(D1 runs statements one at a time), not from the test's timing.ship_eventsrows in production. The board uses correlated subqueries, so revisit it if the crew count grows into the hundreds.Deploy
If the code goes out before the migration, profiles and the leaderboard still render, but
/crewserrors until the migration runs.