capsite/toybox: mount lookups in SQL, not a scan in JS
Each request parsed every mount's labels and searched them in JS. Labels now sit one per row in mount_label, indexed on (key, value): a lookup joins the request's labels (json_each) on the index and keeps the vat whose every label matched. The overlap check at registration is SQL too. mount.labels keeps the whole set as JSON; mounts stored before mount_label get their rows filled in when the schema runs. The SQL lives in mounts-sql.js, tested on node:sqlite, old-shape state included. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9356f63c64
commit
7fcd251261
4 files changed
+124
-38
No files matched your search
+18
-18
@@ -4,7 +4,8 @@ import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
|
||||
import { RpcTarget, newWebSocketRpcSession, newWorkersRpcResponse } from "capnweb";
|
||||
import { E, Far } from "@endo/far";
|
||||
import { makeClient, swissnumFromBytes } from "@endo/ocapn";
|
||||
import { carries, conflict, mergeLabels, urlLabels } from "./labels.js";
|
||||
import { mergeLabels, urlLabels } from "./labels.js";
|
||||
import { LOOKUP, MOUNT, MOUNT_LABELS, MOUNT_SCHEMA, OVERLAP, UNMOUNT, UNMOUNT_LABELS } from "./mounts-sql.js";
|
||||
import { locationOf, makeRpcNetLayer } from "./netlayer.js";
|
||||
import VAT_RUNTIME from "vat-runtime.txt";
|
||||
|
||||
@@ -282,14 +283,7 @@ export class Router extends WorkerEntrypoint {
|
||||
export class Directory extends DurableObject {
|
||||
constructor(ctx, env) {
|
||||
super(ctx, env);
|
||||
ctx.storage.sql.exec("CREATE TABLE IF NOT EXISTS mount (vat TEXT PRIMARY KEY, labels TEXT)");
|
||||
}
|
||||
|
||||
#mounts() {
|
||||
return this.ctx.storage.sql
|
||||
.exec("SELECT vat, labels FROM mount")
|
||||
.toArray()
|
||||
.map(({ vat, labels }) => ({ vat, labels: JSON.parse(labels) }));
|
||||
for (const statement of MOUNT_SCHEMA) ctx.storage.sql.exec(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,22 +293,28 @@ export class Directory extends DurableObject {
|
||||
* @param {Record<string, string> | null} labels
|
||||
*/
|
||||
mount(vat, labels) {
|
||||
if (labels) {
|
||||
const overlap = this.#mounts().find((m) => m.vat !== vat && !conflict(m.labels, labels));
|
||||
if (overlap) throw new Error("mount overlaps another: add a label whose value tells them apart");
|
||||
this.ctx.storage.sql.exec("INSERT OR REPLACE INTO mount VALUES (?, ?)", vat, JSON.stringify(labels));
|
||||
} else {
|
||||
this.ctx.storage.sql.exec("DELETE FROM mount WHERE vat = ?", vat);
|
||||
}
|
||||
const { sql } = this.ctx.storage;
|
||||
this.ctx.storage.transactionSync(() => {
|
||||
sql.exec(UNMOUNT_LABELS, vat);
|
||||
if (!labels) return void sql.exec(UNMOUNT, vat);
|
||||
const json = JSON.stringify(labels);
|
||||
if (sql.exec(OVERLAP, json, vat).toArray().length) {
|
||||
throw new Error("mount overlaps another: add a label whose value tells them apart");
|
||||
}
|
||||
sql.exec(MOUNT, vat, json);
|
||||
sql.exec(MOUNT_LABELS, vat, json);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The mount whose labels `request` carries, if any.
|
||||
* The mount whose labels `request` carries, if any. Registration keeps
|
||||
* mounts pairwise conflicting, so at most one can match.
|
||||
*
|
||||
* @param {Record<string, string>} request
|
||||
*/
|
||||
lookup(request) {
|
||||
return this.#mounts().find((m) => carries(m.labels, request)) ?? null;
|
||||
const [row] = this.ctx.storage.sql.exec(LOOKUP, JSON.stringify(request)).toArray();
|
||||
return row ? { vat: row.vat, labels: JSON.parse(row.labels) } : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user