Public pages cacheable again: a signed-out GET never sets g1t_d1; stars, about and public_links are reads
Since 06:42 UTC every project page and Explore set the bookmark cookie, so the public cache refused them and Page speed went from ~150 ms to ~800 ms (incident 58itx49ji5).
3 files+30−50/3 viewed
| 9 | 9 | bookmarkCookie, | |
| 10 | 10 | coveredMs, | |
| 11 | 11 | mayWrite, | |
| 12 | + | setsBookmark, | |
| 12 | 13 | readBookmarks, | |
| 13 | 14 | rpcMethodOf, | |
| 14 | 15 | serverTiming, | |
| ⋯ | |||
| 142 | 143 | ); | |
| 143 | 144 | // Signing in with GitHub writes on a GET; the session it starts says so. | |
| 144 | 145 | const signedIn = answered.headers.getSetCookie().some((cookie) => cookie.startsWith("g1t_session=")); | |
| 145 | − | const wrote = perf.writing || perf.wrote || signedIn; | |
| 146 | − | if (wrote) { | |
| 146 | + | const hasSession = /(?:^|;\s*)g1t_session=/.test(request.headers.get("cookie") ?? ""); | |
| 147 | + | if (setsBookmark({ writing: perf.writing, wrote: perf.wrote, hasSession, signedIn })) { | |
| 147 | 148 | const next: Bookmarks = { | |
| 148 | 149 | at: Math.floor(Date.now() / 1000), | |
| 149 | 150 | services: { ...perf.bookmarks.services, ...perf.returned }, | |
| 13 | 13 | serviceDuration, | |
| 14 | 14 | databaseTime, | |
| 15 | 15 | sessionFor, | |
| 16 | + | setsBookmark, | |
| 16 | 17 | writeBookmarks, | |
| 17 | 18 | } from "./perf.ts"; | |
| 18 | 19 | ||
| ⋯ | |||
| 63 | 64 | }); | |
| 64 | 65 | ||
| 65 | 66 | test("only known reads are taken not to write", () => { | |
| 66 | − | for (const method of ["get_pull", "list_pulls", "counts", "user_for_session", "explore", "usage", "get", "list", "queue", "pulls_for_repos"]) { | |
| 67 | + | for (const method of ["get_pull", "list_pulls", "counts", "user_for_session", "explore", "usage", "get", "list", "queue", "pulls_for_repos", "stars", "about", "public_links"]) { | |
| 67 | 68 | assert.equal(mayWrite(method), false, method); | |
| 68 | 69 | } | |
| 69 | 70 | for (const method of ["merge_pull", "verify_email", "github_finish", "sign_in", "something_new"]) { | |
| ⋯ | |||
| 73 | 74 | assert.equal(rpcMethodOf("https://service/other"), ""); | |
| 74 | 75 | }); | |
| 75 | 76 | ||
| 77 | + | test("a signed-out GET never sets the bookmark cookie, so public pages stay cacheable", () => { | |
| 78 | + | const read = { writing: false, signedIn: false }; | |
| 79 | + | assert.equal(setsBookmark({ ...read, wrote: true, hasSession: false }), false); | |
| 80 | + | assert.equal(setsBookmark({ ...read, wrote: true, hasSession: true }), true); | |
| 81 | + | assert.equal(setsBookmark({ ...read, wrote: false, hasSession: true }), false); | |
| 82 | + | // A form post, or signing in on a GET, always does. | |
| 83 | + | assert.equal(setsBookmark({ writing: true, signedIn: false, wrote: false, hasSession: false }), true); | |
| 84 | + | assert.equal(setsBookmark({ writing: false, signedIn: true, wrote: false, hasSession: false }), true); | |
| 85 | + | }); | |
| 86 | + | ||
| 76 | 87 | test("timings", () => { | |
| 77 | 88 | assert.equal(serviceDuration('svc;dur=12;desc="session"'), 12); | |
| 78 | 89 | assert.equal(serviceDuration("repo;dur=3, svc;dur=7.5"), 7.5); | |
| 99 | 99 | * `get`, `list`, `queue` and `pulls_for_repos` were missing: every project | |
| 100 | 100 | * page called `get` (repos, projects), so every one set the cookie, was | |
| 101 | 101 | * never kept in the public cache, and sent the next 30 s of the person's | |
| 102 | − | * reads to the primary. | |
| 102 | + | * reads to the primary. `stars`, `about` and `public_links` (2026-10-08) | |
| 103 | + | * did the same to every project page and Explore for 13 hours. | |
| 103 | 104 | */ | |
| 104 | 105 | const READS = new Set( | |
| 105 | 106 | ( | |
| ⋯ | |||
| 111 | 112 | "readable ready_issues references registration repo_access resolve resolve_branch resolve_path resolve_slug " + | |
| 112 | 113 | "routes run run_context run_cost runner_groups runner_settings runners runs scorecards search search_memories " + | |
| 113 | 114 | "settings statement statement_entries status status_by_id suggest tree usage usage_meters user_by_username " + | |
| 114 | − | "user_for_session usernames waiting_workspaces workflows workspace workspace_invites github_enabled" | |
| 115 | + | "user_for_session usernames waiting_workspaces workflows workspace workspace_invites github_enabled " + | |
| 116 | + | "stars about public_links" | |
| 115 | 117 | ).split(" "), | |
| 116 | 118 | ); | |
| 117 | 119 | ||
| 120 | + | /** | |
| 121 | + | * Whether a response sets the `g1t_d1` cookie. A signed-out GET never | |
| 122 | + | * does, whatever it called: nobody signed out can write anything their | |
| 123 | + | * next page must read, and a cookie keeps the page out of the public | |
| 124 | + | * cache. Signing in on a GET (GitHub) starts a session, so it does. | |
| 125 | + | */ | |
| 126 | + | export function setsBookmark(request: { writing: boolean; wrote: boolean; hasSession: boolean; signedIn: boolean }): boolean { | |
| 127 | + | if (request.writing || request.signedIn) return true; | |
| 128 | + | return request.wrote && request.hasSession; | |
| 129 | + | } | |
| 130 | + | ||
| 118 | 131 | /** Whether an RPC to `method` may write. */ | |
| 119 | 132 | export function mayWrite(method: string): boolean { | |
| 120 | 133 | if (READS.has(method)) return false; | |