Download src/fleet/registry.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 5.26 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/fleet/registry.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/fleet/registry.test.ts
-
curl -L -o registry.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/fleet/registry.test.ts
5.26 kB
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| import { afterEach, beforeEach, describe, expect, it } from "vitest"; | |
| import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js"; | |
| import { createSuiteTempRootTracker } from "../test-helpers/temp-dir.js"; | |
| import { | |
| acquireFleetCellOperation, | |
| deleteFleetCell, | |
| getFleetCell, | |
| listFleetCells, | |
| reserveFleetCell, | |
| updateFleetCellImage, | |
| } from "./registry.js"; | |
| type ReserveFleetCellParams = Parameters<typeof reserveFleetCell>[1]; | |
| describe("fleet cell registry", () => { | |
| let root: string | undefined; | |
| let env: NodeJS.ProcessEnv; | |
| const tempRoot = createSuiteTempRootTracker({ prefix: "openclaw-fleet-registry-" }); | |
| beforeEach(async () => { | |
| root = await tempRoot.setup(); | |
| env = { ...process.env, OPENCLAW_STATE_DIR: root }; | |
| }); | |
| afterEach(async () => { | |
| closeOpenClawStateDatabaseForTest(); | |
| await tempRoot.cleanup(); | |
| root = undefined; | |
| }); | |
| function params(tenantId: string, requestedPort?: number): ReserveFleetCellParams { | |
| if (!root) { | |
| throw new Error("test root not initialized"); | |
| } | |
| return { | |
| tenantId, | |
| createdAtMs: 1, | |
| image: "ghcr.io/openclaw/openclaw:latest", | |
| runtime: "docker", | |
| containerName: `openclaw-cell-${tenantId}`, | |
| dataDir: path.join(root, "fleet", "cells", tenantId), | |
| ...(requestedPort === undefined ? {} : { requestedPort }), | |
| }; | |
| } | |
| it("returns empty reads without creating state on a fresh install", () => { | |
| if (!root) { | |
| throw new Error("test root not initialized"); | |
| } | |
| const databasePath = path.join(root, "state", "openclaw.sqlite"); | |
| expect(listFleetCells(env)).toEqual([]); | |
| expect(getFleetCell(env, "missing")).toBeUndefined(); | |
| expect(fs.existsSync(databasePath)).toBe(false); | |
| }); | |
| it("persists, orders, updates, and deletes cells", () => { | |
| const zulu = reserveFleetCell(env, { | |
| ...params("zulu", 19_250), | |
| createdAtMs: 20, | |
| runtime: "podman", | |
| }); | |
| const alpha = reserveFleetCell(env, { | |
| ...params("alpha"), | |
| createdAtMs: 10, | |
| }); | |
| expect(alpha.hostPort).toBe(19_100); | |
| expect(zulu.hostPort).toBe(19_250); | |
| expect(listFleetCells(env).map((cell) => cell.tenantId)).toEqual(["alpha", "zulu"]); | |
| expect(getFleetCell(env, "zulu")).toEqual(zulu); | |
| updateFleetCellImage(env, "zulu", "ghcr.io/openclaw/openclaw:v2"); | |
| expect(getFleetCell(env, "zulu")?.image).toBe("ghcr.io/openclaw/openclaw:v2"); | |
| deleteFleetCell(env, "alpha"); | |
| expect(getFleetCell(env, "alpha")).toBeUndefined(); | |
| }); | |
| it("rejects duplicate tenant ids without replacing the row", () => { | |
| const original = reserveFleetCell(env, params("alpha", 19_300)); | |
| expect(() => | |
| reserveFleetCell(env, { | |
| ...params("alpha", 19_301), | |
| image: "ghcr.io/openclaw/openclaw:other", | |
| }), | |
| ).toThrow("Fleet cell already exists: alpha"); | |
| expect(getFleetCell(env, "alpha")).toEqual(original); | |
| }); | |
| it("allocates the first free port and rejects explicit collisions", () => { | |
| expect(reserveFleetCell(env, params("alpha")).hostPort).toBe(19_100); | |
| expect(reserveFleetCell(env, params("beta")).hostPort).toBe(19_101); | |
| expect(() => reserveFleetCell(env, params("gamma", 19_100))).toThrow(/19100/); | |
| expect(getFleetCell(env, "gamma")).toBeUndefined(); | |
| expect(reserveFleetCell(env, params("delta", 20_000)).hostPort).toBe(20_000); | |
| }); | |
| it("serializes tenant mutations with renewable expiring leases", () => { | |
| const first = acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "upgrade", | |
| owner: "first", | |
| nowMs: 1_000, | |
| }); | |
| expect(() => | |
| acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "rm", | |
| owner: "second", | |
| nowMs: 1_001, | |
| }), | |
| ).toThrow(/fleet upgrade.*already running/iu); | |
| first.heartbeat(200_000); | |
| expect(() => | |
| acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "rm", | |
| owner: "second", | |
| nowMs: 400_000, | |
| }), | |
| ).toThrow(/already running/iu); | |
| first.release(); | |
| const second = acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "rm", | |
| owner: "second", | |
| nowMs: 400_001, | |
| }); | |
| second.release(); | |
| }); | |
| it("fences an expired owner from its replacement lease", () => { | |
| const first = acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "upgrade", | |
| owner: "first", | |
| nowMs: 1_000, | |
| }); | |
| const successor = acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "rm", | |
| owner: "successor", | |
| nowMs: 301_000, | |
| }); | |
| expect(() => first.heartbeat(301_001)).toThrow(/lease was lost/iu); | |
| first.release(); | |
| expect(() => | |
| acquireFleetCellOperation({ | |
| env, | |
| tenantId: "alpha", | |
| operation: "create", | |
| owner: "third", | |
| nowMs: 301_002, | |
| }), | |
| ).toThrow(/fleet rm.*already running/iu); | |
| successor.release(); | |
| }); | |
| it("fails image updates when the cell row disappeared", () => { | |
| expect(() => updateFleetCellImage(env, "missing", "image:v2")).toThrow(/disappeared/iu); | |
| }); | |
| }); | |