test: use runner runtime in scenarios

This commit is contained in:
2026-04-30 07:23:22 +00:00
parent fc29bc9f7e
commit 3680b9c979
2 changed files with 45 additions and 52 deletions
+40 -44
View File
@@ -1,15 +1,9 @@
import { assert, assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0"; import { assert, assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
import { RunnerAdmin } from "../../../uptime.link/ts_api/classes/runner-admin.ts";
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts"; import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts";
import { import type { IRunnerMonitorDefinition } from "../../../uptime.link/ts_api/classes/runner-monitor-mapper.ts";
createRunnerSchedulesFromMonitors,
type IRunnerMonitorDefinition,
} from "../../../uptime.link/ts_api/classes/runner-monitor-mapper.ts";
import { createRunnerRequestHandler } from "../../../uptime.link/ts_api/classes/runner-request-handler.ts";
import { RunnerResultIngestor } from "../../../uptime.link/ts_api/classes/runner-result-ingestor.ts"; import { RunnerResultIngestor } from "../../../uptime.link/ts_api/classes/runner-result-ingestor.ts";
import { RunnerScheduler } from "../../../uptime.link/ts_api/classes/runner-scheduler.ts"; import { RunnerRuntime } from "../../../uptime.link/ts_api/classes/runner-runtime.ts";
import { UptimeRunner } from "../../../uptimerunner/ts/runner.ts"; import { UptimeRunner } from "../../../uptimerunner/ts/runner.ts";
import type { IResultSubmitRequest } from "../../../uptimerunner/ts/interfaces.ts"; import type { IResultSubmitRequest } from "../../../uptimerunner/ts/interfaces.ts";
@@ -65,27 +59,20 @@ const main = async () => {
}, },
]; ];
const coordinator = new RunnerCoordinator(); const runtime = new RunnerRuntime({ monitors, now: () => 1000 });
const admin = new RunnerAdmin(coordinator); const coordinator = runtime.coordinator;
const registration = admin.registerRunner({ const registration = await runtime.registerRunner({
runnerId, runnerId,
token: runnerToken, token: runnerToken,
labels: ["scenario:basic"], labels: ["scenario:basic"],
}); });
assertEquals(registration.runner.runnerId, runnerId); assertEquals(registration.runner.runnerId, runnerId);
assertEquals(registration.token, runnerToken); assertEquals(registration.token, runnerToken);
const scheduler = new RunnerScheduler(coordinator, { now: () => 1000 }); const scheduleResult = await runtime.scheduleDueChecks();
const scheduleResult = scheduler.scheduleDueChecks(
createRunnerSchedulesFromMonitors(monitors),
);
assertEquals(scheduleResult.scheduledChecks.length, 4); assertEquals(scheduleResult.scheduledChecks.length, 4);
assertEquals(coordinator.getQueueLength(), 4); assertEquals(coordinator.getQueueLength(), 4);
assertEquals( assertEquals((await runtime.scheduleDueChecks()).scheduledChecks.length, 0);
scheduler.scheduleDueChecks(scheduleResult.schedules).scheduledChecks const runnerRequestHandler = runtime.createRequestHandler();
.length,
0,
);
const runnerRequestHandler = createRunnerRequestHandler(coordinator);
const coordinatorServer = await startServer(async (request) => { const coordinatorServer = await startServer(async (request) => {
if ( if (
@@ -125,7 +112,8 @@ const main = async () => {
assertEquals(coordinator.listResults().length, 4); assertEquals(coordinator.listResults().length, 4);
assertEquals(coordinator.getQueueLength(), 0); assertEquals(coordinator.getQueueLength(), 0);
assertMonitorStatusDerivation(coordinator.listResults()); assertMonitorStatusDerivation(coordinator.listResults());
await assertSnapshotPersistence(coordinator, targetServer.url); assertEquals(runtime.listMonitorStates().length, 4);
await assertSnapshotPersistence(runtime, targetServer.url);
const emptyResult = await runner.runOnce(); const emptyResult = await runner.runOnce();
assertEquals(emptyResult.checks.length, 0); assertEquals(emptyResult.checks.length, 0);
@@ -140,8 +128,7 @@ const main = async () => {
}); });
await assertRejects(() => unauthorizedRunner.runOnce(), Error, "401"); await assertRejects(() => unauthorizedRunner.runOnce(), Error, "401");
await assertRunnerTokenLifecycle( await assertRunnerTokenLifecycle(
admin, runtime,
coordinator,
coordinatorServer.url, coordinatorServer.url,
runner, runner,
); );
@@ -226,16 +213,15 @@ function assertMonitorStatusDerivation(
} }
async function assertRunnerTokenLifecycle( async function assertRunnerTokenLifecycle(
adminArg: RunnerAdmin, runtimeArg: RunnerRuntime,
coordinatorArg: RunnerCoordinator,
instanceUrlArg: string, instanceUrlArg: string,
staleRunnerArg: UptimeRunner, staleRunnerArg: UptimeRunner,
): Promise<void> { ): Promise<void> {
const rotated = adminArg.rotateRunnerToken(runnerId, "rotated-token"); const rotated = await runtimeArg.rotateRunnerToken(runnerId, "rotated-token");
assertEquals(rotated.token, "rotated-token"); assertEquals(rotated.token, "rotated-token");
assertEquals(adminArg.listRunners()[0].tokenPreview, "rotate...oken"); assertEquals(runtimeArg.admin.listRunners()[0].tokenPreview, "rotate...oken");
coordinatorArg.enqueueCheck({ runtimeArg.coordinator.enqueueCheck({
id: "post-rotate-assumption", id: "post-rotate-assumption",
type: "assumption", type: "assumption",
assumedStatus: "ok", assumedStatus: "ok",
@@ -255,42 +241,51 @@ async function assertRunnerTokenLifecycle(
assertEquals(rotatedResult.results.length, 1); assertEquals(rotatedResult.results.length, 1);
assertEquals(rotatedResult.results[0].status, "ok"); assertEquals(rotatedResult.results[0].status, "ok");
adminArg.disableRunner(runnerId); await runtimeArg.disableRunner(runnerId);
assertEquals(adminArg.listRunners()[0].enabled, false); assertEquals(runtimeArg.admin.listRunners()[0].enabled, false);
await assertRejects(() => rotatedRunner.runOnce(), Error, "401"); await assertRejects(() => rotatedRunner.runOnce(), Error, "401");
adminArg.enableRunner(runnerId); await runtimeArg.enableRunner(runnerId);
adminArg.setRunnerLabels(runnerId, ["scenario:basic", "role:external"]); await runtimeArg.setRunnerLabels(runnerId, [
"scenario:basic",
"role:external",
]);
assertEquals( assertEquals(
adminArg.listRunners()[0].labels.includes("role:external"), runtimeArg.admin.listRunners()[0].labels.includes("role:external"),
true, true,
); );
} }
async function assertSnapshotPersistence( async function assertSnapshotPersistence(
coordinatorArg: RunnerCoordinator, runtimeArg: RunnerRuntime,
targetUrlArg: string, targetUrlArg: string,
): Promise<void> { ): Promise<void> {
const snapshotPath = await Deno.makeTempFile(); const snapshotPath = await Deno.makeTempFile();
const store = RunnerFileStore.fromDenoPath(snapshotPath); const store = RunnerFileStore.fromDenoPath(snapshotPath);
try { try {
await store.save(coordinatorArg.getSnapshot()); const persistedRuntime = new RunnerRuntime({
const snapshot = await store.load(); coordinator: runtimeArg.coordinator,
assert(snapshot); fileStore: store,
const restoredCoordinator = new RunnerCoordinator({ snapshot }); });
assertEquals(restoredCoordinator.listResults().length, 4); await persistedRuntime.save();
assertEquals(restoredCoordinator.listRunners().length, 1); const restoredRuntime = await RunnerRuntime.fromFileStore(store);
restoredCoordinator.enqueueCheck({ assertEquals(restoredRuntime.coordinator.listResults().length, 4);
assertEquals(restoredRuntime.coordinator.listRunners().length, 1);
assertEquals(restoredRuntime.listMonitorStates().length, 4);
restoredRuntime.coordinator.enqueueCheck({
id: "post-restart-http-health", id: "post-restart-http-health",
type: "http", type: "http",
url: targetUrlArg, url: targetUrlArg,
expectedStatusCodes: [200], expectedStatusCodes: [200],
expectedBodyIncludes: "healthy", expectedBodyIncludes: "healthy",
metadata: {
monitorId: "post-restart-http-health",
},
}); });
const restoredServer = await startServer( const restoredServer = await startServer(
createRunnerRequestHandler(restoredCoordinator), restoredRuntime.createRequestHandler(),
); );
try { try {
const restoredRunner = new UptimeRunner({ const restoredRunner = new UptimeRunner({
@@ -301,7 +296,8 @@ async function assertSnapshotPersistence(
const restoredResult = await restoredRunner.runOnce(); const restoredResult = await restoredRunner.runOnce();
assertEquals(restoredResult.results.length, 1); assertEquals(restoredResult.results.length, 1);
assertEquals(restoredResult.results[0].status, "ok"); assertEquals(restoredResult.results[0].status, "ok");
assertEquals(restoredCoordinator.listResults().length, 5); assertEquals(restoredRuntime.coordinator.listResults().length, 5);
assertEquals(restoredRuntime.listMonitorStates().length, 5);
} finally { } finally {
await restoredServer.server.shutdown(); await restoredServer.server.shutdown();
} }
+5 -8
View File
@@ -1,8 +1,6 @@
import { assert, assertEquals } from "jsr:@std/assert@^1.0.0"; import { assert, assertEquals } from "jsr:@std/assert@^1.0.0";
import { RunnerAdmin } from "../../../uptime.link/ts_api/classes/runner-admin.ts"; import { RunnerRuntime } from "../../../uptime.link/ts_api/classes/runner-runtime.ts";
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
import { createRunnerRequestHandler } from "../../../uptime.link/ts_api/classes/runner-request-handler.ts";
const scenarioName = "uptimerunner-vagrant"; const scenarioName = "uptimerunner-vagrant";
const controllerHost = Deno.env.get("UPTIMELINK_CONTROLLER_HOST") ?? "0.0.0.0"; const controllerHost = Deno.env.get("UPTIMELINK_CONTROLLER_HOST") ?? "0.0.0.0";
@@ -19,9 +17,9 @@ const targetUrl = Deno.env.get("UPTIMELINK_RUNNER_TARGET_URL") ??
`http://127.0.0.1:${targetPort}/health`; `http://127.0.0.1:${targetPort}/health`;
const main = async () => { const main = async () => {
const coordinator = new RunnerCoordinator(); const runtime = new RunnerRuntime();
const admin = new RunnerAdmin(coordinator); const coordinator = runtime.coordinator;
admin.registerRunner({ await runtime.registerRunner({
runnerId, runnerId,
token: runnerToken, token: runnerToken,
labels: ["scenario:vagrant", "role:internal"], labels: ["scenario:vagrant", "role:internal"],
@@ -39,11 +37,10 @@ const main = async () => {
}, },
}, { runnerId }); }, { runnerId });
const runnerRequestHandler = createRunnerRequestHandler(coordinator);
const server = Deno.serve( const server = Deno.serve(
{ hostname: controllerHost, port: controllerPort }, { hostname: controllerHost, port: controllerPort },
(request) => { (request) => {
return runnerRequestHandler(request); return runtime.handleRequest(request);
}, },
); );