Implement progressive query admission, session boundaries and event-driven Studio observations

This commit is contained in:
Timothy J. Aveni
2026-10-10 03:49:05 -07:00
parent 2ae7f00acb
commit c2c01a9878
17 changed files with 775 additions and 23 deletions
+8
View File
@@ -179,3 +179,11 @@ await writeFile(
"dist/portable-reader/variants/entries.ts",
"export type Entries = " + tsType(entries.valueType) + ";\n",
);
const { queryTreeFixture } = await import("./query-tree-fixture.js");
const { generatePackageQueryClientBindings } = await import("../src/execution-world/client-contracts.js");
const treeFixture = await queryTreeFixture();
await mkdir("dist/portable-reader/query-tree", { recursive: true });
await writeFile("dist/portable-reader/query-tree/queries.ts", generatePackageQueryClientBindings(treeFixture.pkg));
await writeFile("dist/portable-reader/query-tree/queries.json", JSON.stringify(compileQueryProgram(treeFixture.plan)));
await writeFile("dist/portable-reader/query-tree/kernel.json", JSON.stringify(compileKernelProgram(treeFixture.plan)));
+10 -2
View File
@@ -8,10 +8,18 @@ export const queryFixtureSource = {
repository: "https://query-fixture.example.test/source.git",
commit: "1".repeat(40),
};
export async function queryWorkspaceFixture(options: { live?: boolean } = {}) {
export async function queryWorkspaceFixture(options: { live?: boolean; snapshot?: boolean } = {}) {
const interfaces = new Map<string, InterfaceRevision>();
const sources: Record<string, string> = {};
function iface(name: string, members: string, parameters = "") {
if (options.snapshot) members = members.replaceAll(" ordered", "");
if (options.snapshot)
for (const member of ["name", "title", "done", "rank", "assignee", "items"])
for (const operation of ["get", "resolve"])
members = members.replace(
`${operation} id "${member}:${operation}";`,
`${operation} id "${member}:${operation}" execution snapshot;`,
);
const text = `${[...interfaces.keys()].map((name) => `import interface ${name};`).join("\n")}
interface ${name}${parameters} id "${name}" revision "${name}@1" {${members}}`;
sources[name] = text;
@@ -117,7 +125,7 @@ export async function queryWorkspaceFixture(options: { live?: boolean } = {}) {
${implementation("Task")} ${implementation("Reminder")}
conform Tasks as Collection<interface TaskFacts> id "tasks-collection" {
private edge Items id "items" {
atom Tasks projection items id "items:forward" many ordered;
atom Tasks projection items id "items:forward" many${options.snapshot ? "" : " ordered"};
interface TaskFacts projection collections id "items:inverse" many;
}
bind items.resolve to edge Items.items.resolve;
+37
View File
@@ -0,0 +1,37 @@
import { queryWorkspaceFixture } from "./fixtures/query-workspace.js";
import { compileQuery } from "../src/query/compile.js";
import { queryTreeProjections } from "../src/query/tree.js";
import { linkQueries } from "../src/query/link.js";
import { compileExecutionPlan } from "../src/execution-world/plan.js";
export async function queryTreeFixture() {
const fixture = await queryWorkspaceFixture({ live: true, snapshot: true });
const declaration = {
...fixture.pkg.queries!.find((query) => query.id === "upcoming")!,
id: "tree",
displayName: "Tree",
operation: "Tree",
placement: { kind: "replica" as const },
fragments: [],
};
const checked = await compileQuery(
declaration,
fixture.interfaces,
async () => `query Tree($first:Int!, $details:Boolean!) {
root {items(first:$first) {entries {node {
...Heading @boundary(name:"basic") ...Details @boundary(name:"details") @include(if:$details)
assignee {...Person @boundary(name:"person")}
}}}}
} fragment Heading on TaskFacts {title} fragment Details on TaskFacts {rank done}
fragment Person on PersonFacts {name}`,
);
const projections = queryTreeProjections(checked);
fixture.pkg.queries = [declaration, ...projections.map((query) => query.declaration)];
fixture.pkg.checkedQueries = [checked, ...projections];
// Workspace imports retain the checked Package by value in the assembler.
const imported = fixture.workspace.packageImports.find((pkg) => pkg.revisionId === fixture.pkg.revisionId)!;
imported.queries = fixture.pkg.queries;
imported.checkedQueries = fixture.pkg.checkedQueries;
fixture.workspace.linkedQueries = linkQueries(fixture.workspace);
return { ...fixture, plan: compileExecutionPlan(fixture.workspace) };
}
+165
View File
@@ -0,0 +1,165 @@
import assert from "node:assert/strict";
import test from "node:test";
import { compileCapabilityResourceSource } from "../src/capability-language/index.js";
import { compileQuery } from "../src/query/compile.js";
import type { InterfaceRevision } from "../src/capability-model/types.js";
const source = { repository: "https://example.test/tree", commit: "a".repeat(40) };
function iface(text: string, dependencies: InterfaceRevision[] = []) {
const result = compileCapabilityResourceSource(text, {
source,
environment: {
interfaces: new Map(dependencies.map((value) => [value.displayName, value])),
interfaceClosure: dependencies,
},
});
assert.ok(result.ok, JSON.stringify(result.diagnostics));
if (result.resource.kind !== "interface") throw Error("Expected Interface");
return result.resource.revision;
}
const item = iface(`interface Item id "item" revision "item@1" {
queryable value title id "title" : string {get id "title:get" execution snapshot;}
queryable value body id "body" : string {get id "body:get" execution snapshot;}
}`);
const navigation = iface(
`import interface Item; interface Navigation id "nav" revision "nav@1" {
queryable value chrome id "chrome" : string {get id "chrome:get" execution snapshot;}
queryable relation document id "document" : optional-one interface Item {resolve id "document:resolve" execution snapshot;}
queryable relation items id "items" : many interface Item ordered {resolve id "items:resolve" execution snapshot;}
}`,
[item],
);
function declaration(root: InterfaceRevision = item) {
const result = compileCapabilityResourceSource(
`import interface ${root.displayName}; package Views id "views" revision "views@1" {
query Open id "open" root ${root.displayName} document "open.graphql" operation "Open" {replica; max rows 10;}
}`,
{ source, environment: { interfaces: new Map([[root.displayName, root]]), interfaceClosure: [root, item] } },
);
assert.ok(result.ok, JSON.stringify(result.diagnostics));
if (result.resource.kind !== "package") throw Error("Expected Package");
return result.resource.revision.queries![0]!;
}
const fragments = `fragment Heading on Item {title} fragment Body on Item {body}`;
test("boundaries remain complete typed projections; ordinary spreads stay inline", async () => {
const checked = await compileQuery(
declaration(),
[item],
async () => `query Open {root {...Heading ...Body @boundary(name:"body")}} ${fragments}`,
);
assert(checked.tree);
assert(!JSON.stringify(checked.output).includes('"body"'));
assert(!JSON.stringify(checked.selection).includes('"body"'));
const body = checked.tree.nodes.find((node) => node.id === "root/boundary/body")!;
assert(body);
assert(
JSON.stringify(checked.tree.projections.find((projection) => projection.id === body.projection)!.output).includes(
'"body"',
),
);
assert.equal(checked.tree.nodes[0]!.boundaries[0]!.name, "body");
const ordinary = await compileQuery(
declaration(),
[item],
async () => `query Open {root {...Heading ...Body}} ${fragments}`,
);
assert.equal(ordinary.tree, undefined);
assert(JSON.stringify(ordinary.output).includes('"body"'));
});
test("minimal nullable-root bindings exclude slow siblings and carry child handles", async () => {
const checked = await compileQuery(
declaration(navigation),
[item, navigation],
async () => `query Open {root {
...Chrome @boundary(name:"chrome") document {...Heading @boundary(name:"basic") ...Body @boundary(name:"body")}
}} fragment Chrome on Navigation {chrome} ${fragments}`,
);
const tree = checked.tree!;
const binding = tree.nodes[0]!.bindings[0]!;
assert.equal(binding.name, "document");
const projection = tree.projections.find((projection) => projection.id === binding.projection)!;
assert(!JSON.stringify(projection.selection).includes('"chrome"'));
assert(!JSON.stringify(projection.selection).includes('"title"'));
assert(!JSON.stringify(projection.selection).includes('"body"'));
assert.deepEqual(binding.targets[0]!.path, ["document"]);
assert.deepEqual(
tree.nodes.find((node) => node.id === binding.targets[0]!.node)!.boundaries.map((boundary) => boundary.name),
["basic", "body"],
);
});
test("bounded list bindings preserve entry identity without requesting details", async () => {
const checked = await compileQuery(
declaration(navigation),
[item, navigation],
async () => `query Open {root {
items(first: 3) {entries {node {...Body @boundary(name:"body")}}}
}} fragment Body on Item {body}`,
);
const tree = checked.tree!,
binding = tree.nodes[0]!.bindings[0]!;
assert.deepEqual(binding.targets[0]!.path, ["items", "entries", "[]", "node"]);
const projection = tree.projections.find((projection) => projection.id === binding.projection)!;
assert(JSON.stringify(projection.selection).includes('"name":"key"'));
assert(!JSON.stringify(projection.selection).includes('"name":"body"'));
assert(tree.maxOccurrences <= 256);
});
test("guards control boundary participation and invalid syntax fails checking", async () => {
const checked = await compileQuery(
declaration(),
[item],
async () => `query Open($show:Boolean!) {root {
...Body @boundary(name:"body") @include(if:$show)
}} fragment Body on Item {body}`,
);
assert.deepEqual(checked.tree!.nodes[0]!.boundaries[0]!.conditions, [
{ include: true, value: { kind: "variable", name: "show" } },
]);
for (const [text, error] of [
[`query Open {root {...Body @boundary(name:"")}} fragment Body on Item {body}`, /QUERY_BOUNDARY_NAME/],
[
`query Open($name:String!) {root {...Body @boundary(name:$name)}} fragment Body on Item {body}`,
/QUERY_BOUNDARY_NAME/,
],
[
`query Open {root {...Body @boundary(name:"x") ...Heading @boundary(name:"x")}} ${fragments}`,
/QUERY_BOUNDARY_DUPLICATE/,
],
[`query Open {root {body @boundary(name:"x")}}`, /QUERY_VALIDATION/],
[`query Open {root {...Cycle @boundary(name:"x")}} fragment Cycle on Item {...Cycle}`, /QUERY_VALIDATION/],
] as const)
await assert.rejects(
compileQuery(declaration(), [item], async () => text),
error,
);
});
test("equivalent repeated paths share bindings; aliases preserve different windows", async () => {
const checked = await compileQuery(
declaration(navigation),
[item, navigation],
async () => `query Open {root {
document {...Heading @boundary(name:"basic")} document {...Body @boundary(name:"body")}
recent:items(first:2) {entries {node {...Body @boundary(name:"body")}}}
earlier:items(first:3) {entries {node {...Body @boundary(name:"body")}}}
}} ${fragments}`,
);
assert.deepEqual(
checked.tree!.nodes[0]!.bindings.map((binding) => binding.name),
["document", "recent", "earlier"],
);
assert.deepEqual(
checked
.tree!.nodes.find((node) => node.id === "root/binding/document")!
.boundaries.map((boundary) => boundary.name),
["basic", "body"],
);
await assert.rejects(
compileQuery(
declaration(navigation),
[item, navigation],
async () => `query Open($show:Boolean!) {root {
document @include(if:$show) {...Heading @boundary(name:"basic")} document {...Body @boundary(name:"body")}
}} ${fragments}`,
),
/QUERY_TREE_BINDING_CONFLICT/,
);
});