mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
chord/next/http: a Web fetch handler built from the registry Http (routes, wraps, sockets, hosts, relays, CSP sources) and Authenticators, responses as descriptions, a security baseline on by default, Chord's own Node listener as a host-lifetime object, nodeRequest for apps mounting it, links and plugin sockets. chord/next/workers: a forked worker per address, started on demand, stopped when idle, never restarted by itself, plugins built by the server and shipped. Plugins: kinds with platform and host packages, createPluginRuntime, scripts(kind), rollout results per host, imports of other plugins by name. Kernel: RouteHandle (retry, suspend), no route backoff, anonymous host.root, origins only from relays. ws is an optional peer dependency.
90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { ChordError } from "../../../src/next/data/index.ts";
|
|
import type { HostLink } from "../../../src/next/remote/host-link.ts";
|
|
import { Path, type Upstream } from "../../../src/next/remote/path.ts";
|
|
|
|
/** A holder recording where it was held and what it was told, as `name@link` and `name dropped`. */
|
|
function holder(name: string, log: string[]): Upstream {
|
|
// The path calls only `attach` and `dropped`.
|
|
return {
|
|
attach: (link: { readonly name: string }) => void log.push(`${name}@${link.name}`),
|
|
dropped: () => void log.push(`${name} dropped`),
|
|
} as unknown as Upstream;
|
|
}
|
|
|
|
/** A link known by its name; the path only passes it on. */
|
|
function linkOf(name: string): HostLink {
|
|
return { name } as unknown as HostLink;
|
|
}
|
|
|
|
describe("a path", () => {
|
|
it("asks for a link when it gets a holder without one; holds every holder on each link it gets", () => {
|
|
const log: string[] = [];
|
|
let changes = 0;
|
|
const path = new Path(() => changes++);
|
|
path.attach(holder("a", log));
|
|
path.attach(holder("b", log));
|
|
expect(changes).toBe(2);
|
|
expect(log).toEqual([]);
|
|
const first = linkOf("1");
|
|
path.connected(first);
|
|
expect(log).toEqual(["a@1", "b@1"]);
|
|
path.attach(holder("c", log));
|
|
expect(log.at(-1)).toBe("c@1");
|
|
expect(changes).toBe(2);
|
|
});
|
|
|
|
it("tells every holder when its link drops, then asks for the next; a stale link's drop is ignored", () => {
|
|
const log: string[] = [];
|
|
let changes = 0;
|
|
const path = new Path(() => changes++);
|
|
const [first, second] = [linkOf("1"), linkOf("2")];
|
|
path.connected(first);
|
|
path.attach(holder("a", log));
|
|
path.disconnected(first);
|
|
expect(log).toEqual(["a@1", "a dropped"]);
|
|
expect(changes).toBe(1);
|
|
expect(path.link).toBeUndefined();
|
|
path.connected(second);
|
|
path.disconnected(first);
|
|
expect(log).toEqual(["a@1", "a dropped", "a@2"]);
|
|
expect(changes).toBe(1);
|
|
expect(path.link).toBe(second);
|
|
});
|
|
|
|
it("reports its last holder's detach: no later link holds it", () => {
|
|
const log: string[] = [];
|
|
let changes = 0;
|
|
const path = new Path(() => changes++);
|
|
const [a, b] = [holder("a", log), holder("b", log)];
|
|
path.connected(linkOf("1"));
|
|
path.attach(a);
|
|
path.attach(b);
|
|
path.detach(a);
|
|
expect(changes).toBe(0);
|
|
path.detach(b);
|
|
expect(changes).toBe(1);
|
|
expect(path.held).toBe(false);
|
|
path.connected(linkOf("2"));
|
|
expect(log).toEqual(["a@1", "b@1"]);
|
|
});
|
|
|
|
it("says what changed: a holder attached without a link, a drop, the last release; fails its holders waiting", () => {
|
|
const events: string[] = [];
|
|
const failed: string[] = [];
|
|
const path = new Path((event) => events.push(event.kind));
|
|
const a = {
|
|
attach: () => {},
|
|
dropped: () => {},
|
|
unreachable: (error: { readonly message: string }) => void failed.push(error.message),
|
|
} as unknown as Upstream;
|
|
path.attach(a);
|
|
path.unreachable(new ChordError({ code: "unavailable", message: "no worker" }));
|
|
const link = linkOf("1");
|
|
path.connected(link);
|
|
path.disconnected(link);
|
|
path.detach(a);
|
|
expect(events).toEqual(["attached", "dropped", "released"]);
|
|
expect(failed).toEqual(["no worker"]);
|
|
});
|
|
});
|