Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

36 lines · 2.0 KBRaw History
1// Probe for .github/workflows/d1-replication.yml: checks the D1 Sessions API on a
2// throwaway database with read replication on, the way apps/diffinery uses it
3// (src/lib/d1.ts): write in one session, then read in a new session started from
4// the first one's bookmark, and expect to see the write every time.
5export default {
6 async fetch(req, env) {
7 const url = new URL(req.url);
8 if (url.pathname !== "/check") return new Response("not found", { status: 404 });
9 const rounds = Number(url.searchParams.get("rounds") ?? 20);
10 const out = { rounds, stale: 0, replicaReads: 0, primaryReads: 0, regions: {}, errors: [] };
11 for (let i = 1; i <= rounds; i++) {
12 try {
13 const w = env.DB.withSession("first-primary");
14 const value = `${Date.now()}-${i}-${crypto.randomUUID()}`;
15 await w.prepare("INSERT INTO probe (k, v) VALUES ('latest', ?) ON CONFLICT (k) DO UPDATE SET v = excluded.v").bind(value).run();
16 const bookmark = w.getBookmark();
17 // A later request: new session from the bookmark (as a browser cookie would carry it).
18 const r = env.DB.withSession(bookmark);
19 const row = await r.prepare("SELECT v FROM probe WHERE k = 'latest'").first();
20 const res = await r.prepare("SELECT v FROM probe WHERE k = 'latest'").run();
21 const meta = res.meta ?? {};
22 if (row?.v !== value) out.stale++;
23 if (meta.served_by_primary === false) out.replicaReads++;
24 else out.primaryReads++;
25 const region = meta.served_by_region ?? "unknown";
26 out.regions[region] = (out.regions[region] ?? 0) + 1;
27 // An unconstrained session may read an older value, but must never fail.
28 await env.DB.withSession("first-unconstrained").prepare("SELECT v FROM probe WHERE k = 'latest'").first();
29 } catch (e) {
30 out.errors.push(String(e));
31 }
32 }
33 out.ok = out.stale === 0 && out.errors.length === 0;
34 return Response.json(out, { status: out.ok ? 200 : 500 });
35 },
36};