Skip to content

Commit

A doc saved before g1t kept documents with the page opens as fast as any other from its second open: the page asks its room for the document once, sends it with the page and keeps it on the row, instead of leaving the editor to wait for the room's first message. The artifacts guide says so, and CONTRIBUTING's Speed section has today's measurements on g1t.sh and what is still to cut.

syntaqxcommitted Parentb96b1a8Browse files
3 files+41−70/3 viewed
+11−3
130130 (1,049 KB) in three waves and the editor appeared at 2.8–3.3 s; a doc
131131 now fetches 71 files (1,026 KB) in one wave, and against the deployed
132132 services the editor appears at 2.1 s, of which the room's answer is
133− 0.65 s and the editor's own start 0.4 s. The room's part (the saved
134− document in the page, one call to the room, the context in one round)
135− is measured after deploy.
133+ 0.65 s and the editor's own start 0.4 s. With the saved document in the
134+ page, measured on g1t.sh signed in (2026-10-10, warm, 1440×900), the
135+ editor appears at 1.5 s: first byte 0.53 s, scripts by 0.75 s, the
136+ editor's own start the rest. A doc without a saved document (one last
137+ saved before documents were kept) waited for its room's first message
138+ instead, 0.9 s after the socket opened, and appeared at 2.0–2.5 s; the
139+ page now asks the room once and keeps the answer, so only its first
140+ open pays. Still to cut: the live socket's four service calls before
141+ the room answers, the page and sidebar's 27 database round trips in two
142+ calls, the root loader's billing and identity calls (0.7–1.3 s and
143+ 0.45 s inside), and the 3.4 MB of script a doc page decodes.
136144
137145 ## Rate limits
138146
+4−1
197197 editor together, and the editor opens on the document the page carried: you
198198 can read and type at once, and the room only sends what changed since the
199199 doc was last saved. Anything you type before the room answers is kept and
200−sent then, so nothing is lost. The dot in the header says where things stand:
200+sent then, so nothing is lost. A doc saved before g1t kept documents this way
201+is asked of its room the first time it opens, and kept from then on, so it
202+opens as fast as any other from the second time. The dot in the header says
203+where things stand:
201204
202205 | Dot | Meaning |
203206 | --- | --- |
+26−3
110110 } from "./access-store.ts";
111111 import { agentMayFind, agentReach, audienceRule, type AgentReach, type AudienceRule } from "./agents.ts";
112112 import { publishFolioEvent } from "./events.ts";
113−import { MAX_DEPTH, cleanCover, cleanIcon, cleanNote, cleanSource, cleanTarget, cleanTitle, decodeCursor, depthOf, encodeCursor, listLimit, pageState, sharedTops, slugOf, subtreeHeight, treeNodes } from "./list.ts";
113+import { MAX_DEPTH, MAX_PAGE_STATE, cleanCover, cleanIcon, cleanNote, cleanSource, cleanTarget, cleanTitle, decodeCursor, depthOf, encodeCursor, listLimit, pageState, sharedTops, slugOf, subtreeHeight, treeNodes } from "./list.ts";
114114 import { REQUEST_RECIPIENTS, claimAccessRequest } from "./requests.ts";
115115 import type { FolioRoom } from "./room.ts";
116116 import { builtinFolioTemplate, builtinFolioTemplates } from "./templates.ts";
584584 ]);
585585 const parents = above.map((id) => aboveRows.get(id)).filter((r): r is FolioRow => !!r);
586586 const others = [...parents, ...childRows.results, ...linkRows.results.filter((r) => r.id !== row.id)];
587− const { roles } = await this.roles(ctx, others);
587+ const [{ roles }, state] = await Promise.all([this.roles(ctx, others), this.stateFor(ctx.workspace, row)]);
588588 const readable = (list: FolioRow[]) => list.filter((r) => roles.get(r.id)).map((r) => this.ref(ctx.workspace.slug, r));
589589 return ok({
590590 folio: folio!,
591591 text: row.text,
592− state: pageState(row.state),
592+ state,
593593 breadcrumbs: readable(parents),
594594 children: readable(childRows.results),
595595 backlinks: readable(linkRows.results.filter((r) => r.id !== row.id)),
597597 });
598598 }
599599
600+ /**
601+ * The document the page carries, so the editor opens on it before the
602+ * room answers. A folio saved before its state was kept (or whose last
603+ * save was too large for a row) has none in D1: its room is asked once,
604+ * the state goes out with this page, and it is written back so the next
605+ * open reads it from the row like any other. A room that cannot answer
606+ * costs the page nothing: the editor waits for the room as before.
607+ */
608+ private async stateFor(workspace: Workspace, row: FolioRow): Promise<string | null> {
609+ const saved = pageState(row.state);
610+ if (saved || row.trashed_at) return saved;
611+ try {
612+ const room = await this.ready(workspace, row);
613+ const state = await room.state();
614+ if (!state.byteLength || state.byteLength > MAX_PAGE_STATE) return null;
615+ this.defer(this.db.prepare("UPDATE folios SET state = ? WHERE id = ? AND state IS NULL").bind(state, row.id).run());
616+ return pageState(state);
617+ } catch (error) {
618+ console.warn("artifacts: a page opens without its state", row.id, error instanceof Error ? error.message : String(error));
619+ return null;
620+ }
621+ }
622+
600623 // ── Making and changing ─────────────────────────────────────────────────
601624
602625 /** Where a new folio may go for this person: a parent doc they can edit, a space they can edit, or their Private. */