Gateway: status route with per-route results, test push, reconnect and unpair
Gateway / check (push) Successful in 9s
Gateway / image (push) Successful in 24s

This commit is contained in:
gib committed 2026-11-01 15:04:30 -05:00
1 parent e6fd2b8f51
commit 9707daf1fe
9 files changed
+398 -55

No files matched your search

+41 -15
View File
@@ -5,16 +5,23 @@ import type { Server } from "bun";
import { T3Host } from "../src/t3/host.ts";
const ENVIRONMENT_ID = "env-laptop";
let server: Server<undefined> | undefined;
afterEach(() => server?.stop(true));
let servers: Server<undefined>[] = [];
afterEach(() => {
for (const server of servers) server.stop(true);
servers = [];
});
/** Just enough of a T3 server: the descriptor, a ticket, config, and an empty shell snapshot. */
function fakeT3() {
server = Bun.serve({
/**
* Just enough of a T3 server: the descriptor, a ticket, config, and an empty shell snapshot.
* While `state.up` is false its descriptor returns 503, like a route that is down.
*/
function fakeT3(state = { up: true }) {
const server = Bun.serve({
port: 0,
fetch(req, srv) {
const { pathname } = new URL(req.url);
if (pathname === "/.well-known/t3/environment") {
if (!state.up) return new Response("down", { status: 503 });
return Response.json({ environmentId: ENVIRONMENT_ID, label: "framework-gib", serverVersion: "0.1.5", orchestrationProtocolVersion: 2 });
}
if (pathname === "/api/auth/websocket-ticket/rpc") return Response.json({ ticket: "t" });
@@ -34,25 +41,44 @@ function fakeT3() {
},
},
});
servers.push(server);
return `http://localhost:${server.port}`;
}
/** Resolves once `check` passes, polling every few milliseconds. */
async function until(check: () => boolean) {
while (!check()) await Bun.sleep(5);
}
describe("T3Host routes", () => {
it("falls back to the next route when the preferred one does not answer", async () => {
const working = fakeT3();
// Port 9 (discard) refuses connections, standing in for a LAN route that is down.
const host = new T3Host({ id: ENVIRONMENT_ID, label: "Laptop", urls: ["http://127.0.0.1:9", working], token: "x", environmentId: ENVIRONMENT_ID });
const online = new Promise<void>((resolve) => {
const check = setInterval(() => {
if (host.status === "online") {
clearInterval(check);
resolve();
}
}, 5);
});
const refused = "http://127.0.0.1:9";
const spare = "https://t3laptop.example.org";
const host = new T3Host({ id: ENVIRONMENT_ID, label: "Laptop", urls: [refused, working, spare], token: "x", environmentId: ENVIRONMENT_ID });
host.start();
await online;
await until(() => host.status === "online");
expect(host.url).toBe(working);
expect(host.routeAttempts.get(refused)).toMatchObject({ ok: false, error: "refused" });
expect(host.routeAttempts.get(working)).toMatchObject({ ok: true, error: null });
expect(host.routeAttempts.has(spare)).toBe(false);
host.stop();
});
it("moves back to the preferred route on reconnect once it answers", async () => {
const preferredState = { up: false };
const preferred = fakeT3(preferredState);
const fallback = fakeT3();
const host = new T3Host({ id: ENVIRONMENT_ID, label: "Laptop", urls: [preferred, fallback], token: "x", environmentId: ENVIRONMENT_ID });
host.start();
await until(() => host.status === "online");
expect(host.url).toBe(fallback);
preferredState.up = true;
host.reconnect();
await until(() => host.status === "online" && host.url === preferred);
expect(host.lastOnlineAt).not.toBeNull();
host.stop();
});
});