diff --git a/packages/rivetkit/fixtures/driver-test-suite/sleep.ts b/packages/rivetkit/fixtures/driver-test-suite/sleep.ts index fec86f6a3..741d39b1b 100644 --- a/packages/rivetkit/fixtures/driver-test-suite/sleep.ts +++ b/packages/rivetkit/fixtures/driver-test-suite/sleep.ts @@ -1,7 +1,7 @@ import { actor, type UniversalWebSocket } from "rivetkit"; import { promiseWithResolvers } from "rivetkit/utils"; -export const SLEEP_TIMEOUT = 500; +export const SLEEP_TIMEOUT = 1000; export const sleep = actor({ state: { startCount: 0, sleepCount: 0 }, diff --git a/packages/rivetkit/src/actor/instance.ts b/packages/rivetkit/src/actor/instance.ts index 9005de913..f85e64045 100644 --- a/packages/rivetkit/src/actor/instance.ts +++ b/packages/rivetkit/src/actor/instance.ts @@ -373,6 +373,9 @@ export class ActorInstance { this.#config.options.connectionLivenessInterval, ); this.#checkConnectionsLiveness(); + + // Trigger any pending alarms + await this._onAlarm(); } async #scheduleEventInner(newEvent: PersistedScheduleEvent) { @@ -401,6 +404,12 @@ export class ActorInstance { } } + /** + * Triggers any pending alarms. + * + * This method is idempotent. It's called automatically when the actor wakes + * in order to trigger any pending alarms. + */ async _onAlarm() { const now = Date.now(); this.actorContext.log.debug({ @@ -424,7 +433,7 @@ export class ActorInstance { this.#rLog.warn({ msg: "no events are due yet, time may have broken" }); if (this.#persist.scheduledEvents.length > 0) { const nextTs = this.#persist.scheduledEvents[0].timestamp; - this.actorContext.log.warn({ + this.actorContext.log.debug({ msg: "alarm fired early, rescheduling for next event", now, nextTs, @@ -786,7 +795,7 @@ export class ActorInstance { } /** - * Connection disconnected. + * Call when conn is disconnected. Used by transports. * * If a clean diconnect, will be removed immediately. * @@ -800,7 +809,7 @@ export class ActorInstance { // If socket ID is provided, check if it matches the current socket ID // If it doesn't match, this is a stale disconnect event from an old socket if (socketId && conn.__socket && socketId !== conn.__socket.socketId) { - this.rLog.debug({ + this.#rLog.debug({ msg: "ignoring stale disconnect event", connId: conn.id, eventSocketId: socketId, @@ -825,6 +834,9 @@ export class ActorInstance { // Remove socket conn.__socket = undefined; + + // Update sleep + this.#resetSleepTimer(); } } @@ -848,6 +860,7 @@ export class ActorInstance { // Remove from state this.#connections.delete(conn.id); + this.#rLog.debug({ msg: "removed conn", connId: conn.id }); // Remove subscriptions for (const eventName of [...conn.subscriptions.values()]) { diff --git a/packages/rivetkit/src/actor/router-endpoints.ts b/packages/rivetkit/src/actor/router-endpoints.ts index 8472c9631..9f8e145ec 100644 --- a/packages/rivetkit/src/actor/router-endpoints.ts +++ b/packages/rivetkit/src/actor/router-endpoints.ts @@ -292,7 +292,8 @@ export async function handleWebSocketConnect( // Handle cleanup asynchronously handlersPromise .then(({ conn, actor }) => { - actor.__connDisconnected(conn, event.wasClean, socketId); + const wasClean = event.wasClean || event.code === 1000; + actor.__connDisconnected(conn, wasClean, socketId); }) .catch((error) => { deconstructError( diff --git a/packages/rivetkit/src/actor/router.ts b/packages/rivetkit/src/actor/router.ts index 1b9752b98..6089bad19 100644 --- a/packages/rivetkit/src/actor/router.ts +++ b/packages/rivetkit/src/actor/router.ts @@ -69,6 +69,7 @@ export type ActorRouter = Hono<{ Bindings: ActorRouterBindings }>; export function createActorRouter( runConfig: RunConfig, actorDriver: ActorDriver, + isTest: boolean, ): ActorRouter { const router = new Hono<{ Bindings: ActorRouterBindings }>({ strict: false }); @@ -84,37 +85,39 @@ export function createActorRouter( return c.text("ok"); }); - // Test endpoint to force disconnect a connection non-cleanly - router.post("/.test/force-disconnect", async (c) => { - const connId = c.req.query("conn"); + if (isTest) { + // Test endpoint to force disconnect a connection non-cleanly + router.post("/.test/force-disconnect", async (c) => { + const connId = c.req.query("conn"); - if (!connId) { - return c.text("Missing conn query parameter", 400); - } + if (!connId) { + return c.text("Missing conn query parameter", 400); + } - const actor = await actorDriver.loadActor(c.env.actorId); - const conn = actor.__getConnForId(connId); + const actor = await actorDriver.loadActor(c.env.actorId); + const conn = actor.__getConnForId(connId); - if (!conn) { - return c.text(`Connection not found: ${connId}`, 404); - } + if (!conn) { + return c.text(`Connection not found: ${connId}`, 404); + } - // Force close the websocket/SSE connection without clean shutdown - const driverState = conn.__driverState; - if (driverState && ConnDriverKind.WEBSOCKET in driverState) { - const ws = driverState[ConnDriverKind.WEBSOCKET].websocket; + // Force close the websocket/SSE connection without clean shutdown + const driverState = conn.__driverState; + if (driverState && ConnDriverKind.WEBSOCKET in driverState) { + const ws = driverState[ConnDriverKind.WEBSOCKET].websocket; - // Force close without sending close frame - (ws.raw as any).terminate(); - } else if (driverState && ConnDriverKind.SSE in driverState) { - const stream = driverState[ConnDriverKind.SSE].stream; + // Force close without sending close frame + (ws.raw as any).terminate(); + } else if (driverState && ConnDriverKind.SSE in driverState) { + const stream = driverState[ConnDriverKind.SSE].stream; - // Force close the SSE stream - stream.abort(); - } + // Force close the SSE stream + stream.abort(); + } - return c.json({ success: true }); - }); + return c.json({ success: true }); + }); + } router.get(PATH_CONNECT_WEBSOCKET, async (c) => { const upgradeWebSocket = runConfig.getUpgradeWebSocket?.(); diff --git a/packages/rivetkit/src/client/actor-conn.ts b/packages/rivetkit/src/client/actor-conn.ts index e99c29fe8..a89283dc4 100644 --- a/packages/rivetkit/src/client/actor-conn.ts +++ b/packages/rivetkit/src/client/actor-conn.ts @@ -914,6 +914,8 @@ enc if (!this.#transport) { // Nothing to do } else if ("websocket" in this.#transport) { + logger().debug("closing ws"); + const ws = this.#transport.websocket; // Check if WebSocket is already closed or closing if ( @@ -927,10 +929,12 @@ enc logger().debug({ msg: "ws closed" }); resolve(undefined); }); - ws.close(); + ws.close(1000, "Normal closure"); await promise; } } else if ("sse" in this.#transport) { + logger().debug("closing sse"); + // Send close request to server for SSE connections if (this.#connectionId && this.#connectionToken) { try { diff --git a/packages/rivetkit/src/driver-test-suite/mod.ts b/packages/rivetkit/src/driver-test-suite/mod.ts index 5d3d940d1..4dfa265c8 100644 --- a/packages/rivetkit/src/driver-test-suite/mod.ts +++ b/packages/rivetkit/src/driver-test-suite/mod.ts @@ -35,6 +35,7 @@ export interface SkipTests { schedule?: boolean; sleep?: boolean; sse?: boolean; + inline?: boolean; } export interface DriverTestConfig { @@ -79,7 +80,10 @@ export interface DriverDeployOutput { export function runDriverTests( driverTestConfigPartial: Omit, ) { - for (const clientType of ["http", "inline"] as ClientType[]) { + const clientTypes: ClientType[] = driverTestConfigPartial.skip?.inline + ? ["http"] + : ["http", "inline"]; + for (const clientType of clientTypes) { const driverTestConfig: DriverTestConfig = { ...driverTestConfigPartial, clientType, @@ -148,7 +152,12 @@ export function runDriverTests( export async function createTestRuntime( registryPath: string, driverFactory: (registry: Registry) => Promise<{ - rivetEngine?: { endpoint: string; namespace: string; runnerName: string }; + rivetEngine?: { + endpoint: string; + namespace: string; + runnerName: string; + token: string; + }; driver: DriverConfig; cleanup?: () => Promise; }>, diff --git a/packages/rivetkit/src/driver-test-suite/tests/actor-schedule.ts b/packages/rivetkit/src/driver-test-suite/tests/actor-schedule.ts index 55d1fc676..886c6d82a 100644 --- a/packages/rivetkit/src/driver-test-suite/tests/actor-schedule.ts +++ b/packages/rivetkit/src/driver-test-suite/tests/actor-schedule.ts @@ -6,6 +6,8 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) { describe.skipIf(driverTestConfig.skip?.schedule)( "Actor Schedule Tests", () => { + // See alarm + actor sleeping test in actor-sleep.ts + describe("Scheduled Alarms", () => { test("executes c.schedule.at() with specific timestamp", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); @@ -13,12 +15,12 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) { // Create instance const scheduled = client.scheduled.getOrCreate(); - // Schedule a task to run in 100ms using timestamp - const timestamp = Date.now() + 100; + // Schedule a task to run using timestamp + const timestamp = Date.now() + 250; await scheduled.scheduleTaskAt(timestamp); // Wait for longer than the scheduled time - await waitFor(driverTestConfig, 200); + await waitFor(driverTestConfig, 500); // Verify the scheduled task ran const lastRun = await scheduled.getLastRun(); @@ -34,11 +36,11 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) { // Create instance const scheduled = client.scheduled.getOrCreate(); - // Schedule a task to run in 100ms using delay - await scheduled.scheduleTaskAfter(100); + // Schedule a task to run using delay + await scheduled.scheduleTaskAfter(250); // Wait for longer than the scheduled time - await waitFor(driverTestConfig, 200); + await waitFor(driverTestConfig, 500); // Verify the scheduled task ran const lastRun = await scheduled.getLastRun(); @@ -48,31 +50,6 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) { expect(scheduledCount).toBe(1); }); - test("scheduled tasks persist across actor restarts", async (c) => { - const { client } = await setupDriverTest(c, driverTestConfig); - - // Create instance and schedule - const scheduled = client.scheduled.getOrCreate(); - await scheduled.scheduleTaskAfter(200); - - // Wait a little so the schedule is stored but hasn't triggered yet - await waitFor(driverTestConfig, 100); - - // Get a new reference to simulate actor restart - const newInstance = client.scheduled.getOrCreate(); - - // Verify the schedule still exists but hasn't run yet - const initialCount = await newInstance.getScheduledCount(); - expect(initialCount).toBe(0); - - // Wait for the scheduled task to execute - await waitFor(driverTestConfig, 200); - - // Verify the scheduled task ran after "restart" - const scheduledCount = await newInstance.getScheduledCount(); - expect(scheduledCount).toBe(1); - }); - test("multiple scheduled tasks execute in order", async (c) => { const { client } = await setupDriverTest(c, driverTestConfig); @@ -83,22 +60,22 @@ export function runActorScheduleTests(driverTestConfig: DriverTestConfig) { await scheduled.clearHistory(); // Schedule multiple tasks with different delays - await scheduled.scheduleTaskAfterWithId("first", 100); - await scheduled.scheduleTaskAfterWithId("second", 300); - await scheduled.scheduleTaskAfterWithId("third", 500); + await scheduled.scheduleTaskAfterWithId("first", 250); + await scheduled.scheduleTaskAfterWithId("second", 750); + await scheduled.scheduleTaskAfterWithId("third", 1250); // Wait for first task only - await waitFor(driverTestConfig, 200); + await waitFor(driverTestConfig, 500); const history1 = await scheduled.getTaskHistory(); expect(history1).toEqual(["first"]); // Wait for second task - await waitFor(driverTestConfig, 200); + await waitFor(driverTestConfig, 500); const history2 = await scheduled.getTaskHistory(); expect(history2).toEqual(["first", "second"]); // Wait for third task - await waitFor(driverTestConfig, 200); + await waitFor(driverTestConfig, 500); const history3 = await scheduled.getTaskHistory(); expect(history3).toEqual(["first", "second", "third"]); }); diff --git a/packages/rivetkit/src/driver-test-suite/tests/actor-sleep.ts b/packages/rivetkit/src/driver-test-suite/tests/actor-sleep.ts index 28354455c..ab0cc13fe 100644 --- a/packages/rivetkit/src/driver-test-suite/tests/actor-sleep.ts +++ b/packages/rivetkit/src/driver-test-suite/tests/actor-sleep.ts @@ -29,7 +29,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { await sleepActor.triggerSleep(); // HACK: Wait for sleep to finish in background - await waitFor(driverTestConfig, 100); + await waitFor(driverTestConfig, 250); // Get sleep count after restore { @@ -59,7 +59,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { await sleepActor.dispose(); // HACK: Wait for sleep to finish in background - await waitFor(driverTestConfig, 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Reconnect to get sleep count after restore const sleepActor2 = client.sleep.getOrCreate(); @@ -84,7 +84,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait for sleep - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Get sleep count after restore { @@ -111,7 +111,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { await sleepActor.dispose(); // Wait for sleep - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Reconnect to get sleep count after restore const sleepActor2 = client.sleep.getOrCreate(); @@ -136,7 +136,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait almost until sleep timeout, then make RPC call - await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT - 250); // RPC call should reset the sleep timer { @@ -146,7 +146,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait another partial timeout period - actor should still be awake - await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT - 250); // Actor should still be awake { @@ -156,7 +156,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Now wait for full timeout without any RPC calls - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should have slept and restarted { @@ -180,10 +180,10 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Set an alarm to keep the actor awake - await sleepActor.setAlarm(SLEEP_TIMEOUT - 100); + await sleepActor.setAlarm(SLEEP_TIMEOUT - 250); // Wait until after SLEEPT_IMEOUT to validate the actor did not sleep - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should not have slept { @@ -207,7 +207,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Set an alarm to keep the actor awake - await sleepActor.setAlarm(SLEEP_TIMEOUT + 100); + await sleepActor.setAlarm(SLEEP_TIMEOUT + 250); // Wait until after SLEEPT_IMEOUT to validate the actor did not sleep await waitFor(driverTestConfig, SLEEP_TIMEOUT + 200); @@ -239,7 +239,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { ); const longRunningPromise = sleepActor.longRunningRpc(); await waitPromise; - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); await sleepActor.finishLongRunningRpc(); await longRunningPromise; @@ -252,7 +252,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { await sleepActor.dispose(); // Now wait for the sleep timeout - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should have slept after the timeout const sleepActor2 = client.sleepWithLongRpc.getOrCreate(); @@ -298,7 +298,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { }); // Wait longer than sleep timeout while keeping WebSocket connected - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Send a message to check if actor is still alive ws.send(JSON.stringify({ type: "getCounts" })); @@ -320,7 +320,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { ws.close(); // Wait for sleep timeout after WebSocket closed - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should have slept after WebSocket closed { @@ -347,7 +347,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Start a long-running fetch request - const fetchDuration = SLEEP_TIMEOUT + 100; + const fetchDuration = SLEEP_TIMEOUT + 250; const fetchPromise = sleepActor.fetch( `long-request?duration=${fetchDuration}`, ); @@ -365,7 +365,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait for sleep timeout - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should have slept after timeout { @@ -389,7 +389,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait longer than sleep timeout - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should NOT have slept due to noSleep option { @@ -399,7 +399,7 @@ export function runActorSleepTests(driverTestConfig: DriverTestConfig) { } // Wait even longer to be sure - await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100); + await waitFor(driverTestConfig, SLEEP_TIMEOUT + 250); // Actor should still not have slept { diff --git a/packages/rivetkit/src/drivers/engine/actor-driver.ts b/packages/rivetkit/src/drivers/engine/actor-driver.ts index aa4923aa3..0dae41616 100644 --- a/packages/rivetkit/src/drivers/engine/actor-driver.ts +++ b/packages/rivetkit/src/drivers/engine/actor-driver.ts @@ -35,7 +35,11 @@ import { } from "@/driver-helpers/mod"; import type { RegistryConfig } from "@/registry/config"; import type { RunConfig } from "@/registry/run-config"; -import { promiseWithResolvers } from "@/utils"; +import { + type LongTimeoutHandle, + promiseWithResolvers, + setLongTimeout, +} from "@/utils"; import type { Config } from "./config"; import { KEYS } from "./kv"; import { logger } from "./log"; @@ -58,6 +62,7 @@ export class EngineActorDriver implements ActorDriver { #actors: Map = new Map(); #actorRouter: ActorRouter; #version: number = 1; // Version for the runner protocol + #alarmTimeout?: LongTimeoutHandle; #runnerStarted: PromiseWithResolvers = Promise.withResolvers(); #runnerStopped: PromiseWithResolvers = Promise.withResolvers(); @@ -74,7 +79,11 @@ export class EngineActorDriver implements ActorDriver { this.#managerDriver = managerDriver; this.#inlineClient = inlineClient; this.#config = config; - this.#actorRouter = createActorRouter(runConfig, this); + this.#actorRouter = createActorRouter( + runConfig, + this, + registryConfig.test.enabled, + ); // Create runner configuration let hasDisconnected = false; @@ -186,9 +195,29 @@ export class EngineActorDriver implements ActorDriver { } async setAlarm(actor: AnyActorInstance, timestamp: number): Promise { - // TODO: Set timeout - // TODO: Use alarm on sleep - // TODO: Send alarm to runner + // Clear prev timeout + if (this.#alarmTimeout) { + this.#alarmTimeout.abort(); + this.#alarmTimeout = undefined; + } + + // Set alarm + const delay = Math.max(0, timestamp - Date.now()); + this.#alarmTimeout = setLongTimeout(() => { + actor._onAlarm(); + this.#alarmTimeout = undefined; + }, delay); + + // TODO: This call may not be needed on ActorInstance.start, but it does help ensure that the local state is synced with the alarm state + // Set alarm on Rivet + // + // This does not call an "alarm" event like Durable Objects. + // Instead, it just wakes the actor on the alarm (if not + // already awake). + // + // _onAlarm is automatically called on `ActorInstance.start` when waking + // again. + this.#runner.setAlarm(actor.id, timestamp); } async getDatabase(_actorId: string): Promise { diff --git a/packages/rivetkit/src/drivers/file-system/manager.ts b/packages/rivetkit/src/drivers/file-system/manager.ts index 5d8237f65..a6622857b 100644 --- a/packages/rivetkit/src/drivers/file-system/manager.ts +++ b/packages/rivetkit/src/drivers/file-system/manager.ts @@ -123,7 +123,11 @@ export class FileSystemManagerDriver implements ManagerDriver { this, inlineClient, ); - this.#actorRouter = createActorRouter(this.#runConfig, this.#actorDriver); + this.#actorRouter = createActorRouter( + this.#runConfig, + this.#actorDriver, + registryConfig.test.enabled, + ); } async sendRequest(actorId: string, actorRequest: Request): Promise { diff --git a/packages/rivetkit/src/manager/router.ts b/packages/rivetkit/src/manager/router.ts index dac073a3e..2ca344401 100644 --- a/packages/rivetkit/src/manager/router.ts +++ b/packages/rivetkit/src/manager/router.ts @@ -118,7 +118,9 @@ function addServerlessRoutes( // Serverless start endpoint router.get("/start", cors, async (c) => { - const actorDriver = serverlessActorDriverBuilder(c.req.header("x-rivet-token")); + const actorDriver = serverlessActorDriverBuilder( + c.req.header("x-rivet-token"), + ); invariant( actorDriver.serverlessHandleStart, "missing serverlessHandleStart on ActorDriver", @@ -169,9 +171,9 @@ function addManagerRoutes( const actorIdsParsed = actor_ids ? actor_ids - .split(",") - .map((id) => id.trim()) - .filter((id) => id.length > 0) + .split(",") + .map((id) => id.trim()) + .filter((id) => id.length > 0) : undefined; const actors: ActorOutput[] = []; diff --git a/packages/rivetkit/src/registry/mod.ts b/packages/rivetkit/src/registry/mod.ts index 2bf636dfd..755395025 100644 --- a/packages/rivetkit/src/registry/mod.ts +++ b/packages/rivetkit/src/registry/mod.ts @@ -215,7 +215,9 @@ export class Registry { console.log(); } - let serverlessActorDriverBuilder: ((token?: string) => ActorDriver) | undefined = (token: string | undefined) => { + let serverlessActorDriverBuilder: + | ((token?: string) => ActorDriver) + | undefined = (token: string | undefined) => { // Override config token if one was set if (token) config.token = token; diff --git a/packages/rivetkit/tests/driver-engine.test.ts b/packages/rivetkit/tests/driver-engine.test.ts index 108507910..bfc729a6a 100644 --- a/packages/rivetkit/tests/driver-engine.test.ts +++ b/packages/rivetkit/tests/driver-engine.test.ts @@ -3,15 +3,15 @@ import { createClientWithDriver } from "@/client/client"; import { createTestRuntime, runDriverTests } from "@/driver-test-suite/mod"; import { createEngineDriver } from "@/drivers/engine/mod"; import { RunConfigSchema } from "@/registry/run-config"; -import { getPort } from "@/test/mod"; runDriverTests({ // Use real timers for engine-runner tests useRealTimers: true, skip: { - // Skip tests that aren't applicable for engine-runner - schedule: true, // Scheduling handled by engine + // SSE is not implemented on Rivet Guard yet sse: true, + // The inline client is the same as the remote client driver on Rivet + inline: true, }, async start() { return await createTestRuntime( @@ -27,6 +27,7 @@ runDriverTests({ method: "POST", headers: { "Content-Type": "application/json", + Authorization: "Bearer dev", }, body: JSON.stringify({ name: namespace, @@ -42,6 +43,7 @@ runDriverTests({ endpoint, namespace, runnerName, + token: "dev", totalSlots: 1000, }); @@ -64,6 +66,7 @@ runDriverTests({ endpoint: "http://127.0.0.1:6420", namespace: namespace, runnerName: runnerName, + token: "dev", }, driver: driverConfig, cleanup: async () => {