diff --git a/src/gateway/server.test.ts b/src/gateway/server.test.ts index 4b22f980a..630c4549d 100644 --- a/src/gateway/server.test.ts +++ b/src/gateway/server.test.ts @@ -1,5 +1,8 @@ +import { randomUUID } from "node:crypto"; import { type AddressInfo, createServer } from "node:net"; -import { describe, expect, test, vi } from "vitest"; +import os from "node:os"; +import path from "node:path"; +import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { WebSocket } from "ws"; import { emitAgentEvent } from "../infra/agent-events.js"; import { startGatewayServer } from "./server.js"; @@ -24,6 +27,19 @@ vi.mock("../commands/agent.js", () => ({ process.env.CLAWDIS_SKIP_PROVIDERS = "1"; +const originalLockPath = process.env.CLAWDIS_GATEWAY_LOCK_PATH; + +beforeEach(() => { + process.env.CLAWDIS_GATEWAY_LOCK_PATH = path.join( + os.tmpdir(), + `clawdis-gateway-${randomUUID()}.lock`, + ); +}); + +afterEach(() => { + process.env.CLAWDIS_GATEWAY_LOCK_PATH = originalLockPath; +}); + async function getFreePort(): Promise { return await new Promise((resolve, reject) => { const server = createServer(); @@ -116,18 +132,22 @@ describe("gateway server", () => { process.env.CLAWDIS_GATEWAY_TOKEN = prevToken; }); - test("closes silent handshakes after timeout", async () => { - const { server, ws } = await startServerWithClient(); - const closed = await new Promise((resolve) => { - const timer = setTimeout(() => resolve(false), 4000); - ws.once("close", () => { - clearTimeout(timer); - resolve(true); + test( + "closes silent handshakes after timeout", + { timeout: 15_000 }, + async () => { + const { server, ws } = await startServerWithClient(); + const closed = await new Promise((resolve) => { + const timer = setTimeout(() => resolve(false), 12_000); + ws.once("close", () => { + clearTimeout(timer); + resolve(true); + }); }); - }); - expect(closed).toBe(true); - await server.close(); - }); + expect(closed).toBe(true); + await server.close(); + }, + ); test( "hello + health + presence + status succeed", diff --git a/src/gateway/server.ts b/src/gateway/server.ts index 76d60e398..4877ad740 100644 --- a/src/gateway/server.ts +++ b/src/gateway/server.ts @@ -97,7 +97,7 @@ function buildSnapshot(): Snapshot { const MAX_PAYLOAD_BYTES = 512 * 1024; // cap incoming frame size const MAX_BUFFERED_BYTES = 1.5 * 1024 * 1024; // per-connection send buffer limit -const HANDSHAKE_TIMEOUT_MS = 3_000; +const HANDSHAKE_TIMEOUT_MS = 10_000; const TICK_INTERVAL_MS = 30_000; const HEALTH_REFRESH_INTERVAL_MS = 60_000; const DEDUPE_TTL_MS = 5 * 60_000; diff --git a/src/infra/gateway-lock.ts b/src/infra/gateway-lock.ts index 5d818793f..f57e7915f 100644 --- a/src/infra/gateway-lock.ts +++ b/src/infra/gateway-lock.ts @@ -4,7 +4,9 @@ import path from "node:path"; import { flockSync } from "fs-ext"; -const DEFAULT_LOCK_PATH = path.join(os.tmpdir(), "clawdis-gateway.lock"); +const defaultLockPath = () => + process.env.CLAWDIS_GATEWAY_LOCK_PATH ?? + path.join(os.tmpdir(), "clawdis-gateway.lock"); export class GatewayLockError extends Error {} @@ -20,7 +22,7 @@ const SIGNALS: NodeJS.Signals[] = ["SIGINT", "SIGTERM", "SIGHUP"]; * correctness relies solely on the kernel lock. */ export async function acquireGatewayLock( - lockPath = DEFAULT_LOCK_PATH, + lockPath = defaultLockPath(), ): Promise { fs.mkdirSync(path.dirname(lockPath), { recursive: true });