inngest 3.48.2-pr-1209.0 → 3.48.2-pr-1214.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -656,8 +656,6 @@ var WebSocketWorkerConnection = class {
656
656
  ws.send(require_connect.ConnectMessage.encode(require_connect.ConnectMessage.create({ kind: require_connect.GatewayMessageType.WORKER_HEARTBEAT })).finish());
657
657
  }, heartbeatIntervalMs);
658
658
  conn.cleanup = () => {
659
- this.debug("Cleaning up worker heartbeat", { connectionId });
660
- clearInterval(heartbeatInterval);
661
659
  if (closed) return;
662
660
  closed = true;
663
661
  this.debug("Cleaning up connection", { connectionId });
@@ -668,8 +666,12 @@ var WebSocketWorkerConnection = class {
668
666
  this.debug("Closing connection", { connectionId });
669
667
  ws.onerror = () => {};
670
668
  ws.onclose = () => {};
671
- ws.close(1e3, require_connect.workerDisconnectReasonToJSON(require_connect.WorkerDisconnectReason.WORKER_SHUTDOWN));
672
- if (this.currentConnection?.id === connectionId) this.currentConnection = void 0;
669
+ this.inProgressRequests.wg.wait().then(() => {
670
+ ws.close(1e3, require_connect.workerDisconnectReasonToJSON(require_connect.WorkerDisconnectReason.WORKER_SHUTDOWN));
671
+ if (this.currentConnection?.id === connectionId) this.currentConnection = void 0;
672
+ this.debug("Cleaning up worker heartbeat", { connectionId });
673
+ clearInterval(heartbeatInterval);
674
+ });
673
675
  };
674
676
  return conn;
675
677
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ConnectionState","WaitGroup","getEnvironmentName","MessageBuffer","functions: Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n >","DEFAULT_SHUTDOWN_SIGNALS","allProcessEnv","envKeys","hashSigningKey","capabilities: Capabilities","functionConfigs: Record<\n string,\n {\n client: Inngest.Like;\n functions: FunctionConfig[];\n }\n >","data: connectionEstablishData","requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n >","InngestCommHandler","parseFnData","parseTraceCtx","headerKeys","sdkResponseStatus: SDKResponseStatus","SDKResponseStatus","SDKResponse","version","PREFERRED_EXECUTION_VERSION","queryKeys","ReconnectError","AuthError","ConnectionLimitError","expBackoff","waitWithCancel","createStartRequest","headers: Record<string, string>","parseStartResponse","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: any) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","workerDisconnectReasonToJSON","WorkerDisconnectReason","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","parseConnectMessage","gatewayMessageTypeToJSON","GatewayMessageType","WorkerConnectRequestData","getPlatformName","retrieveSystemAttributes","getHostname","ConnectMessage","GatewayConnectionReadyData","conn: connection","parseGatewayExecutorRequest","WorkerRequestAckData","extendLeaseInterval: NodeJS.Timeout | undefined","WorkerRequestExtendLeaseData","parseWorkerReplyAck","WorkerRequestExtendLeaseAckData","onShutdown"],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":["import { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport debug, { type Debugger } from \"debug\";\nimport ms from \"ms\";\nimport { envKeys, headerKeys, queryKeys } from \"../../helpers/consts.ts\";\nimport {\n allProcessEnv,\n getEnvironmentName,\n getPlatformName,\n} from \"../../helpers/env.ts\";\nimport { parseFnData } from \"../../helpers/functions.ts\";\nimport { hashSigningKey } from \"../../helpers/strings.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n SDKResponse,\n SDKResponseStatus,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../proto/src/components/connect/protobuf/connect.ts\";\nimport type { Capabilities, FunctionConfig } from \"../../types.ts\";\nimport { version } from \"../../version.ts\";\nimport { PREFERRED_EXECUTION_VERSION } from \"../execution/InngestExecution.ts\";\nimport type { Inngest } from \"../Inngest.ts\";\nimport { InngestCommHandler } from \"../InngestCommHandler.ts\";\nimport type { InngestFunction } from \"../InngestFunction.ts\";\nimport { MessageBuffer } from \"./buffer.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"./messages.ts\";\nimport { getHostname, onShutdown, retrieveSystemAttributes } from \"./os.ts\";\nimport {\n type ConnectApp,\n type ConnectHandlerOptions,\n ConnectionState,\n DEFAULT_SHUTDOWN_SIGNALS,\n type WorkerConnection,\n} from \"./types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n parseTraceCtx,\n ReconnectError,\n waitWithCancel,\n} from \"./util.ts\";\n\nconst ResponseAcknowlegeDeadline = 5_000;\n\nconst InngestBranchEnvironmentSigningKeyPrefix = \"signkey-branch-\";\n\ninterface connectionEstablishData {\n marshaledCapabilities: string;\n manualReadinessAck: boolean;\n apps: {\n appName: string;\n appVersion?: string;\n functions: Uint8Array;\n }[];\n}\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\ntype ConnectCommHandler = InngestCommHandler<\n [GatewayExecutorRequestData],\n SDKResponse,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n any\n>;\n\ninterface connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\nclass WebSocketWorkerConnection implements WorkerConnection {\n private inngest: Inngest.Any;\n private options: ConnectHandlerOptions;\n private debug: Debugger;\n\n /**\n * The current state of the connection.\n */\n public state: ConnectionState = ConnectionState.CONNECTING;\n\n /**\n * The current connection.\n */\n private currentConnection: connection | undefined;\n\n private inProgressRequests: {\n /**\n * A wait group to track in-flight requests.\n */\n wg: WaitGroup;\n\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n /**\n * The buffer of messages to be sent to the gateway.\n */\n private messageBuffer: MessageBuffer;\n\n private _hashedSigningKey: string | undefined;\n private _hashedFallbackKey: string | undefined;\n\n private _inngestEnv: string | undefined;\n\n /**\n * A set of gateways to exclude from the connection.\n */\n private excludeGateways: Set<string> = new Set();\n\n /**\n * Function to remove the shutdown signal handler.\n */\n private cleanupShutdownSignal: (() => void) | undefined;\n\n /**\n * A promise that resolves when the connection is closed on behalf of the\n * user by calling `close()` or when a shutdown signal is received.\n */\n private closingPromise: Promise<void> | undefined;\n private resolveClosingPromise:\n | ((value: void | PromiseLike<void>) => void)\n | undefined;\n\n constructor(options: ConnectHandlerOptions) {\n if (\n !Array.isArray(options.apps) ||\n options.apps.length === 0 ||\n !options.apps[0]\n ) {\n throw new Error(\"No apps provided\");\n }\n\n this.inngest = options.apps[0].client as Inngest.Any;\n for (const app of options.apps) {\n const client = app.client as Inngest.Any;\n\n if (client.env !== this.inngest.env) {\n throw new Error(\n `All apps must be configured to the same environment. ${client.id} is configured to ${client.env} but ${this.inngest.id} is configured to ${this.inngest.env}`,\n );\n }\n }\n\n this.options = this.applyDefaults(options);\n\n this._inngestEnv = this.inngest.env ?? getEnvironmentName();\n\n this.debug = debug(\"inngest:connect\");\n\n this.messageBuffer = new MessageBuffer(this.inngest);\n\n this.closingPromise = new Promise((resolve) => {\n this.resolveClosingPromise = resolve;\n });\n }\n\n private get functions(): Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n > {\n const functions: Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n > = {};\n for (const app of this.options.apps) {\n const client = app.client as Inngest.Any;\n\n if (functions[client.id]) {\n throw new Error(`Duplicate app id: ${client.id}`);\n }\n\n functions[client.id] = {\n client: app.client,\n functions: (app.functions as InngestFunction.Any[]) ?? client.funcs,\n };\n }\n return functions;\n }\n\n private applyDefaults(opts: ConnectHandlerOptions): ConnectHandlerOptions {\n const options = { ...opts };\n if (!Array.isArray(options.handleShutdownSignals)) {\n options.handleShutdownSignals = DEFAULT_SHUTDOWN_SIGNALS;\n }\n\n const env = allProcessEnv();\n options.signingKey = options.signingKey || env[envKeys.InngestSigningKey];\n options.signingKeyFallback =\n options.signingKeyFallback || env[envKeys.InngestSigningKeyFallback];\n\n if (options.maxWorkerConcurrency === undefined) {\n const envValue = env[envKeys.InngestConnectMaxWorkerConcurrency];\n if (envValue) {\n const parsed = Number.parseInt(envValue, 10);\n if (!Number.isNaN(parsed) && parsed > 0) {\n options.maxWorkerConcurrency = parsed;\n }\n }\n }\n\n return options;\n }\n\n async close(): Promise<void> {\n // Remove the shutdown signal handler\n if (this.cleanupShutdownSignal) {\n this.cleanupShutdownSignal();\n this.cleanupShutdownSignal = undefined;\n }\n\n this.state = ConnectionState.CLOSING;\n\n this.debug(\"Cleaning up connection resources\");\n\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\n\n this.debug(\"Connection closed\");\n\n this.debug(\"Waiting for in-flight requests to complete\");\n\n await this.inProgressRequests.wg.wait();\n\n this.debug(\"Flushing messages before closing\");\n\n try {\n await this.messageBuffer.flush(this._hashedSigningKey);\n } catch (err) {\n this.debug(\"Failed to flush messages, using fallback key\", err);\n await this.messageBuffer.flush(this._hashedFallbackKey);\n }\n\n this.state = ConnectionState.CLOSED;\n this.resolveClosingPromise?.();\n\n this.debug(\"Fully closed\");\n\n return this.closed;\n }\n\n /**\n * A promise that resolves when the connection is closed on behalf of the\n * user by calling `close()` or when a shutdown signal is received.\n */\n get closed(): Promise<void> {\n if (!this.closingPromise) {\n throw new Error(\"No connection established\");\n }\n return this.closingPromise;\n }\n\n /**\n * The current connection ID of the worker.\n */\n get connectionId(): string {\n if (!this.currentConnection) {\n throw new Error(\"Connection not prepared\");\n }\n return this.currentConnection.id;\n }\n\n /**\n * Establish a persistent connection to the gateway.\n */\n public async connect(attempt = 0, path: string[] = []) {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n if (\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED\n ) {\n throw new Error(\"Connection already closed\");\n }\n\n this.debug(\"Establishing connection\", { attempt });\n\n if (this.inngest[\"mode\"].isCloud && !this.options.signingKey) {\n throw new Error(\"Signing key is required\");\n }\n\n this._hashedSigningKey = this.options.signingKey\n ? hashSigningKey(this.options.signingKey)\n : undefined;\n\n if (\n this.options.signingKey &&\n this.options.signingKey.startsWith(\n InngestBranchEnvironmentSigningKeyPrefix,\n ) &&\n !this._inngestEnv\n ) {\n throw new Error(\n \"Environment is required when using branch environment signing keys\",\n );\n }\n\n if (this.options.signingKeyFallback) {\n this._hashedFallbackKey = hashSigningKey(this.options.signingKeyFallback);\n }\n\n try {\n await this.messageBuffer.flush(this._hashedSigningKey);\n } catch (err) {\n this.debug(\"Failed to flush messages, using fallback key\", err);\n await this.messageBuffer.flush(this._hashedFallbackKey);\n }\n\n const capabilities: Capabilities = {\n trust_probe: \"v1\",\n connect: \"v1\",\n };\n\n const functionConfigs: Record<\n string,\n {\n client: Inngest.Like;\n functions: FunctionConfig[];\n }\n > = {};\n for (const [appId, { client, functions }] of Object.entries(\n this.functions,\n )) {\n functionConfigs[appId] = {\n client: client,\n functions: functions.flatMap((f) =>\n f[\"getConfig\"]({\n baseUrl: new URL(\"wss://connect\"),\n appPrefix: (client as Inngest.Any).id,\n isConnect: true,\n }),\n ),\n };\n }\n\n this.debug(\"Prepared sync data\", {\n functionSlugs: Object.entries(functionConfigs).map(\n ([appId, { functions }]) => {\n return JSON.stringify({\n appId,\n functions: functions.map((f) => ({\n id: f.id,\n stepUrls: Object.values(f.steps).map((s) => s.runtime[\"url\"]),\n })),\n });\n },\n ),\n });\n\n const data: connectionEstablishData = {\n manualReadinessAck: false,\n\n marshaledCapabilities: JSON.stringify(capabilities),\n apps: Object.entries(functionConfigs).map(\n ([appId, { client, functions }]) => ({\n appName: appId,\n appVersion: (client as Inngest.Any).appVersion,\n functions: new TextEncoder().encode(JSON.stringify(functions)),\n }),\n ),\n };\n\n const requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n > = {};\n for (const [appId, { client, functions }] of Object.entries(\n this.functions,\n )) {\n const inngestCommHandler: ConnectCommHandler = new InngestCommHandler({\n client: client,\n functions: functions,\n frameworkName: \"connect\",\n signingKey: this.options.signingKey,\n signingKeyFallback: this.options.signingKeyFallback,\n skipSignatureValidation: true,\n handler: (msg: GatewayExecutorRequestData) => {\n const asString = new TextDecoder().decode(msg.requestPayload);\n const parsed = parseFnData(JSON.parse(asString));\n\n const userTraceCtx = parseTraceCtx(msg.userTraceCtx);\n\n return {\n body() {\n return parsed;\n },\n method() {\n return \"POST\";\n },\n headers(key) {\n switch (key) {\n case headerKeys.ContentLength.toString():\n return asString.length.toString();\n case headerKeys.InngestExpectedServerKind.toString():\n return \"connect\";\n case headerKeys.RequestVersion.toString():\n return parsed.version.toString();\n case headerKeys.Signature.toString():\n // Note: Signature is disabled for connect\n return null;\n case headerKeys.TraceParent.toString():\n return userTraceCtx?.traceParent ?? null;\n case headerKeys.TraceState.toString():\n return userTraceCtx?.traceState ?? null;\n default:\n return null;\n }\n },\n transformResponse({ body, headers, status }) {\n let sdkResponseStatus: SDKResponseStatus = SDKResponseStatus.DONE;\n switch (status) {\n case 200:\n sdkResponseStatus = SDKResponseStatus.DONE;\n break;\n case 206:\n sdkResponseStatus = SDKResponseStatus.NOT_COMPLETED;\n break;\n case 500:\n sdkResponseStatus = SDKResponseStatus.ERROR;\n break;\n }\n\n return SDKResponse.create({\n requestId: msg.requestId,\n accountId: msg.accountId,\n envId: msg.envId,\n appId: msg.appId,\n status: sdkResponseStatus,\n body: new TextEncoder().encode(body),\n noRetry: headers[headerKeys.NoRetry] === \"true\",\n retryAfter: headers[headerKeys.RetryAfter],\n sdkVersion: `inngest-js:v${version}`,\n requestVersion: parseInt(\n headers[headerKeys.RequestVersion] ??\n PREFERRED_EXECUTION_VERSION.toString(),\n 10,\n ),\n systemTraceCtx: msg.systemTraceCtx,\n userTraceCtx: msg.userTraceCtx,\n runId: msg.runId,\n });\n },\n url() {\n const baseUrl = new URL(\"http://connect.inngest.com\");\n\n baseUrl.searchParams.set(queryKeys.FnId, msg.functionSlug);\n\n if (msg.stepId) {\n baseUrl.searchParams.set(queryKeys.StepId, msg.stepId);\n }\n\n return baseUrl;\n },\n };\n },\n });\n const requestHandler = inngestCommHandler.createHandler();\n requestHandlers[appId] = requestHandler;\n }\n\n if (\n this.options.handleShutdownSignals &&\n this.options.handleShutdownSignals.length > 0\n ) {\n this.setupShutdownSignal(this.options.handleShutdownSignals);\n }\n\n let useSigningKey = this._hashedSigningKey;\n while (\n ![ConnectionState.CLOSING, ConnectionState.CLOSED].includes(this.state)\n ) {\n // Clean up any previous connection state\n // Note: Never reset the message buffer, as there may be pending/unsent messages\n {\n // Flush any pending messages\n await this.messageBuffer.flush(useSigningKey);\n }\n\n try {\n await this.prepareConnection(\n requestHandlers,\n useSigningKey,\n data,\n attempt,\n [...path],\n );\n return;\n } catch (err) {\n this.debug(\"Failed to connect\", err);\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback = useSigningKey === this._hashedSigningKey;\n if (switchToFallback) {\n this.debug(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this._hashedFallbackKey\n : this._hashedSigningKey;\n }\n\n if (err instanceof ConnectionLimitError) {\n console.error(\n \"You have reached the maximum number of concurrent connections. Please disconnect other active workers to continue.\",\n );\n // Continue reconnecting, do not throw.\n }\n\n const delay = expBackoff(attempt);\n this.debug(\"Reconnecting in\", delay, \"ms\");\n\n const cancelled = await waitWithCancel(\n delay,\n () =>\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED,\n );\n if (cancelled) {\n this.debug(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.debug(\"Exiting connect loop\");\n }\n\n private async sendStartRequest(\n hashedSigningKey: string | undefined,\n attempt: number,\n ) {\n const msg = createStartRequest(Array.from(this.excludeGateways));\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/protobuf\",\n ...(hashedSigningKey\n ? { Authorization: `Bearer ${hashedSigningKey}` }\n : {}),\n };\n\n if (this._inngestEnv) {\n headers[headerKeys.Environment] = this._inngestEnv;\n }\n\n // refactor this to a more universal spot\n const targetUrl =\n await this.inngest[\"inngestApi\"][\"getTargetUrl\"](\"/v0/connect/start\");\n\n let resp;\n try {\n resp = await fetch(targetUrl, {\n method: \"POST\",\n body: new Uint8Array(msg),\n headers: headers,\n });\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : \"Unknown error\";\n throw new ReconnectError(\n `Failed initial API handshake request to ${targetUrl.toString()}, ${errMsg}`,\n attempt,\n );\n }\n\n if (!resp.ok) {\n if (resp.status === 401) {\n throw new AuthError(\n `Failed initial API handshake request to ${targetUrl.toString()}${\n this._inngestEnv ? ` (env: ${this._inngestEnv})` : \"\"\n }, ${await resp.text()}`,\n attempt,\n );\n }\n\n if (resp.status === 429) {\n throw new ConnectionLimitError(attempt);\n }\n\n throw new ReconnectError(\n `Failed initial API handshake request to ${targetUrl.toString()}, ${await resp.text()}`,\n attempt,\n );\n }\n\n const startResp = await parseStartResponse(resp);\n\n return startResp;\n }\n\n private async prepareConnection(\n requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n >,\n hashedSigningKey: string | undefined,\n data: connectionEstablishData,\n attempt: number,\n path: string[] = [],\n ): Promise<{ cleanup: () => void }> {\n let closed = false;\n\n this.debug(\"Preparing connection\", {\n attempt,\n path,\n });\n\n const startedAt = new Date();\n\n const startResp = await this.sendStartRequest(hashedSigningKey, attempt);\n\n const connectionId = startResp.connectionId;\n path.push(connectionId);\n\n let resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let rejectWebsocketConnected: ((reason?: any) => void) | undefined;\n const websocketConnectedPromise = new Promise((resolve, reject) => {\n resolveWebsocketConnected = resolve;\n rejectWebsocketConnected = reject;\n });\n\n const connectTimeout = setTimeout(() => {\n this.excludeGateways.add(startResp.gatewayGroup);\n rejectWebsocketConnected?.(\n new ReconnectError(`Connection ${connectionId} timed out`, attempt),\n );\n }, 10_000);\n\n let finalEndpoint = startResp.gatewayEndpoint;\n if (this.options.rewriteGatewayEndpoint) {\n const rewritten = this.options.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.debug(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.debug(`Connecting to gateway`, {\n endpoint: finalEndpoint,\n gatewayGroup: startResp.gatewayGroup,\n connectionId,\n });\n\n const ws = new WebSocket(finalEndpoint, [ConnectWebSocketProtocol]);\n ws.binaryType = \"arraybuffer\";\n\n let onConnectionError: (error: unknown) => void | Promise<void>;\n {\n onConnectionError = (error: unknown) => {\n // Only process the first error per connection\n if (closed) {\n this.debug(\n `Connection error while initializing but already in closed state, skipping`,\n {\n connectionId,\n },\n );\n return;\n }\n closed = true;\n\n this.debug(`Connection error in connecting state, rejecting promise`, {\n connectionId,\n });\n\n this.excludeGateways.add(startResp.gatewayGroup);\n\n clearTimeout(connectTimeout);\n\n // Make sure to close the WebSocket if it's still open\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001, // incomplete setup\n workerDisconnectReasonToJSON(WorkerDisconnectReason.UNEXPECTED),\n );\n\n rejectWebsocketConnected?.(\n new ReconnectError(\n `Error while connecting (${connectionId}): ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n attempt,\n ),\n );\n };\n\n ws.onerror = (err) => onConnectionError(err);\n ws.onclose = (ev) => {\n void onConnectionError(\n new ReconnectError(\n `Connection ${connectionId} closed: ${ev.reason}`,\n attempt,\n ),\n );\n };\n }\n\n /**\n * The current setup state of the connection.\n */\n const setupState = {\n receivedGatewayHello: false,\n sentWorkerConnect: false,\n receivedConnectionReady: false,\n };\n\n let heartbeatIntervalMs: number | undefined;\n let extendLeaseIntervalMs: number | undefined;\n\n ws.onmessage = async (event) => {\n const messageBytes = new Uint8Array(event.data as ArrayBuffer);\n\n const connectMessage = parseConnectMessage(messageBytes);\n\n this.debug(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n {\n connectionId,\n },\n );\n\n if (!setupState.receivedGatewayHello) {\n if (connectMessage.kind !== GatewayMessageType.GATEWAY_HELLO) {\n void onConnectionError(\n new ReconnectError(\n `Expected hello message, got ${gatewayMessageTypeToJSON(\n connectMessage.kind,\n )}`,\n attempt,\n ),\n );\n return;\n }\n setupState.receivedGatewayHello = true;\n }\n\n if (!setupState.sentWorkerConnect) {\n const workerConnectRequestMsg = WorkerConnectRequestData.create({\n connectionId: startResp.connectionId,\n environment: this._inngestEnv,\n platform: getPlatformName({\n ...allProcessEnv(),\n }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck: data.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: data.apps,\n capabilities: new TextEncoder().encode(data.marshaledCapabilities),\n startedAt: startedAt,\n instanceId: this.options.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.options.maxWorkerConcurrency,\n });\n\n const workerConnectRequestMsgBytes = WorkerConnectRequestData.encode(\n workerConnectRequestMsg,\n ).finish();\n\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_CONNECT,\n payload: workerConnectRequestMsgBytes,\n }),\n ).finish(),\n );\n\n setupState.sentWorkerConnect = true;\n return;\n }\n\n if (!setupState.receivedConnectionReady) {\n if (\n connectMessage.kind !== GatewayMessageType.GATEWAY_CONNECTION_READY\n ) {\n void onConnectionError(\n new ReconnectError(\n `Expected ready message, got ${gatewayMessageTypeToJSON(\n connectMessage.kind,\n )}`,\n attempt,\n ),\n );\n return;\n }\n\n const readyPayload = GatewayConnectionReadyData.decode(\n connectMessage.payload,\n );\n\n setupState.receivedConnectionReady = true;\n\n // The intervals should be supplied by the gateway, but we should fall back just in case\n heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue) // TODO Grim cast\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue) // TODO Grim cast\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.debug(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState: setupState,\n state: this.state,\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\n this.state = ConnectionState.ACTIVE;\n this.excludeGateways.delete(startResp.gatewayGroup);\n\n attempt = 0;\n\n const conn: connection = {\n id: connectionId,\n ws,\n cleanup: () => {\n if (closed) {\n return;\n }\n closed = true;\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close();\n },\n pendingHeartbeats: 0,\n };\n this.currentConnection = conn;\n\n this.debug(`Connection ready (${connectionId})`);\n\n // Flag to prevent connecting twice in draining scenario:\n // 1. We're already draining and repeatedly trying to connect while keeping the old connection open\n // 2. The gateway closes the old connection after a timeout, causing a connection error (which would also trigger a new connection)\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n // Only process the first error per connection\n if (closed) {\n this.debug(`Connection error but already in closed state, skipping`, {\n connectionId,\n });\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n // Don't attempt to reconnect if we're already closing or closed\n if (\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED\n ) {\n this.debug(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.state = ConnectionState.RECONNECTING;\n this.excludeGateways.add(startResp.gatewayGroup);\n\n // If this connection is draining and got closed unexpectedly, there's already a new connection being established\n if (isDraining) {\n this.debug(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.debug(`Connection error (${connectionId})`, error);\n this.connect(attempt + 1, [...path, \"onConnectionError\"]);\n };\n\n ws.onerror = (err) => onConnectionError(err);\n ws.onclose = (ev) => {\n void onConnectionError(\n new ReconnectError(`Connection closed: ${ev.reason}`, attempt),\n );\n };\n }\n\n ws.onmessage = async (event) => {\n const messageBytes = new Uint8Array(event.data as ArrayBuffer);\n\n const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.debug(\"Received draining message\", { connectionId });\n try {\n this.debug(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n // Wait for new conn to be successfully established\n await this.connect(0, [...path]);\n\n // Clean up the old connection\n await conn.cleanup();\n } catch (err) {\n this.debug(\"Failed to reconnect after receiving draining message\", {\n connectionId,\n err,\n });\n\n // Clean up the old connection\n await conn.cleanup();\n\n void onConnectionError(\n new ReconnectError(\n `Failed to reconnect after receiving draining message (${connectionId})`,\n attempt,\n ),\n );\n }\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_HEARTBEAT) {\n conn.pendingHeartbeats = 0;\n this.debug(\"Handled gateway heartbeat\", {\n connectionId,\n });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n if (this.state !== ConnectionState.ACTIVE) {\n this.debug(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.debug(\"Received gateway executor request\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n appName: gatewayExecutorRequest.appName,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n\n if (\n typeof gatewayExecutorRequest.appName !== \"string\" ||\n gatewayExecutorRequest.appName.length === 0\n ) {\n this.debug(\"No app name in request, skipping\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n return;\n }\n const requestHandler = requestHandlers[gatewayExecutorRequest.appName];\n\n if (!requestHandler) {\n this.debug(\"No request handler found for app, skipping\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n appName: gatewayExecutorRequest.appName,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n return;\n }\n\n // Ack received request\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REQUEST_ACK,\n payload: WorkerRequestAckData.encode(\n WorkerRequestAckData.create({\n accountId: gatewayExecutorRequest.accountId,\n envId: gatewayExecutorRequest.envId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n requestId: gatewayExecutorRequest.requestId,\n stepId: gatewayExecutorRequest.stepId,\n userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n runId: gatewayExecutorRequest.runId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n\n this.inProgressRequests.wg.add(1);\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ] = gatewayExecutorRequest.leaseId;\n\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n try {\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n // Only extend lease if it's still set on the request\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n this.debug(\"extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\n // Send extend lease request\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE,\n payload: WorkerRequestExtendLeaseData.encode(\n WorkerRequestExtendLeaseData.create({\n accountId: gatewayExecutorRequest.accountId,\n envId: gatewayExecutorRequest.envId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n requestId: gatewayExecutorRequest.requestId,\n stepId: gatewayExecutorRequest.stepId,\n runId: gatewayExecutorRequest.runId,\n userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n\n leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n const res = await requestHandler(gatewayExecutorRequest);\n\n this.debug(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n this.messageBuffer.addPending(res, ResponseAcknowlegeDeadline);\n\n if (!this.currentConnection) {\n this.debug(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n this.messageBuffer.append(res);\n return;\n }\n\n // Send reply back to gateway\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: SDKResponse.encode(res).finish(),\n }),\n ).finish(),\n );\n } finally {\n this.inProgressRequests.wg.done();\n delete this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n clearInterval(extendLeaseInterval);\n }\n\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.WORKER_REPLY_ACK) {\n const replyAck = parseWorkerReplyAck(connectMessage.payload);\n\n this.debug(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.messageBuffer.acknowledgePending(replyAck.requestId);\n\n return;\n }\n\n if (\n connectMessage.kind ===\n GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE_ACK\n ) {\n const extendLeaseAck = WorkerRequestExtendLeaseAckData.decode(\n connectMessage.payload,\n );\n\n this.debug(\"received extend lease ack\", {\n connectionId,\n newLeaseId: extendLeaseAck.newLeaseId,\n });\n\n if (extendLeaseAck.newLeaseId) {\n this.inProgressRequests.requestLeases[extendLeaseAck.requestId] =\n extendLeaseAck.newLeaseId;\n } else {\n this.debug(\"unable to extend lease\", {\n connectionId,\n requestId: extendLeaseAck.requestId,\n });\n delete this.inProgressRequests.requestLeases[\n extendLeaseAck.requestId\n ];\n }\n\n return;\n }\n\n this.debug(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState: setupState,\n state: this.state,\n connectionId,\n });\n };\n\n let heartbeatInterval = undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n // Check if we've missed 2 consecutive heartbeats\n if (conn.pendingHeartbeats >= 2) {\n this.debug(\"Gateway heartbeat missed\");\n void onConnectionError(\n new ReconnectError(\n `Consecutive gateway heartbeats missed (${connectionId})`,\n attempt,\n ),\n );\n return;\n }\n\n this.debug(\"Sending worker heartbeat\", {\n connectionId,\n });\n\n // Send worker heartbeat\n conn.pendingHeartbeats++;\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_HEARTBEAT,\n }),\n ).finish(),\n );\n }, heartbeatIntervalMs);\n }\n\n conn.cleanup = () => {\n this.debug(\"Cleaning up worker heartbeat\", {\n connectionId,\n });\n\n clearInterval(heartbeatInterval);\n\n if (closed) {\n return;\n }\n closed = true;\n\n this.debug(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.debug(\"Sending pause message\", { connectionId });\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_PAUSE,\n }),\n ).finish(),\n );\n }\n\n this.debug(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 1000,\n workerDisconnectReasonToJSON(WorkerDisconnectReason.WORKER_SHUTDOWN),\n );\n\n if (this.currentConnection?.id === connectionId) {\n this.currentConnection = undefined;\n }\n };\n\n return conn;\n }\n\n private setupShutdownSignal(signals: string[]) {\n if (this.cleanupShutdownSignal) {\n return;\n }\n\n this.debug(`Setting up shutdown signal handler for ${signals.join(\", \")}`);\n\n const cleanupShutdownHandlers = onShutdown(signals, () => {\n this.debug(\"Received shutdown signal, closing connection\");\n void this.close();\n });\n\n this.cleanupShutdownSignal = () => {\n this.debug(\"Cleaning up shutdown signal handler\");\n cleanupShutdownHandlers();\n };\n }\n}\n\n// Export types for convenience\nexport {\n DEFAULT_SHUTDOWN_SIGNALS,\n type ConnectApp,\n type ConnectHandlerOptions,\n ConnectionState,\n type WorkerConnection,\n};\n\nexport const connect = async (\n options: ConnectHandlerOptions,\n): Promise<WorkerConnection> => {\n if (options.apps.length === 0) {\n throw new Error(\"No apps provided\");\n }\n\n const conn = new WebSocketWorkerConnection(options);\n\n await conn.connect();\n\n return conn;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ConnectionState","WaitGroup","getEnvironmentName","MessageBuffer","functions: Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n >","DEFAULT_SHUTDOWN_SIGNALS","allProcessEnv","envKeys","hashSigningKey","capabilities: Capabilities","functionConfigs: Record<\n string,\n {\n client: Inngest.Like;\n functions: FunctionConfig[];\n }\n >","data: connectionEstablishData","requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n >","InngestCommHandler","parseFnData","parseTraceCtx","headerKeys","sdkResponseStatus: SDKResponseStatus","SDKResponseStatus","SDKResponse","version","PREFERRED_EXECUTION_VERSION","queryKeys","ReconnectError","AuthError","ConnectionLimitError","expBackoff","waitWithCancel","createStartRequest","headers: Record<string, string>","parseStartResponse","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: any) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","workerDisconnectReasonToJSON","WorkerDisconnectReason","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","parseConnectMessage","gatewayMessageTypeToJSON","GatewayMessageType","WorkerConnectRequestData","getPlatformName","retrieveSystemAttributes","getHostname","ConnectMessage","GatewayConnectionReadyData","conn: connection","parseGatewayExecutorRequest","WorkerRequestAckData","extendLeaseInterval: NodeJS.Timeout | undefined","WorkerRequestExtendLeaseData","parseWorkerReplyAck","WorkerRequestExtendLeaseAckData","onShutdown"],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":["import { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport debug, { type Debugger } from \"debug\";\nimport ms from \"ms\";\nimport { envKeys, headerKeys, queryKeys } from \"../../helpers/consts.ts\";\nimport {\n allProcessEnv,\n getEnvironmentName,\n getPlatformName,\n} from \"../../helpers/env.ts\";\nimport { parseFnData } from \"../../helpers/functions.ts\";\nimport { hashSigningKey } from \"../../helpers/strings.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n SDKResponse,\n SDKResponseStatus,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../proto/src/components/connect/protobuf/connect.ts\";\nimport type { Capabilities, FunctionConfig } from \"../../types.ts\";\nimport { version } from \"../../version.ts\";\nimport { PREFERRED_EXECUTION_VERSION } from \"../execution/InngestExecution.ts\";\nimport type { Inngest } from \"../Inngest.ts\";\nimport { InngestCommHandler } from \"../InngestCommHandler.ts\";\nimport type { InngestFunction } from \"../InngestFunction.ts\";\nimport { MessageBuffer } from \"./buffer.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"./messages.ts\";\nimport { getHostname, onShutdown, retrieveSystemAttributes } from \"./os.ts\";\nimport {\n type ConnectApp,\n type ConnectHandlerOptions,\n ConnectionState,\n DEFAULT_SHUTDOWN_SIGNALS,\n type WorkerConnection,\n} from \"./types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n parseTraceCtx,\n ReconnectError,\n waitWithCancel,\n} from \"./util.ts\";\n\nconst ResponseAcknowlegeDeadline = 5_000;\n\nconst InngestBranchEnvironmentSigningKeyPrefix = \"signkey-branch-\";\n\ninterface connectionEstablishData {\n marshaledCapabilities: string;\n manualReadinessAck: boolean;\n apps: {\n appName: string;\n appVersion?: string;\n functions: Uint8Array;\n }[];\n}\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\ntype ConnectCommHandler = InngestCommHandler<\n [GatewayExecutorRequestData],\n SDKResponse,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n any\n>;\n\ninterface connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\nclass WebSocketWorkerConnection implements WorkerConnection {\n private inngest: Inngest.Any;\n private options: ConnectHandlerOptions;\n private debug: Debugger;\n\n /**\n * The current state of the connection.\n */\n public state: ConnectionState = ConnectionState.CONNECTING;\n\n /**\n * The current connection.\n */\n private currentConnection: connection | undefined;\n\n private inProgressRequests: {\n /**\n * A wait group to track in-flight requests.\n */\n wg: WaitGroup;\n\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n /**\n * The buffer of messages to be sent to the gateway.\n */\n private messageBuffer: MessageBuffer;\n\n private _hashedSigningKey: string | undefined;\n private _hashedFallbackKey: string | undefined;\n\n private _inngestEnv: string | undefined;\n\n /**\n * A set of gateways to exclude from the connection.\n */\n private excludeGateways: Set<string> = new Set();\n\n /**\n * Function to remove the shutdown signal handler.\n */\n private cleanupShutdownSignal: (() => void) | undefined;\n\n /**\n * A promise that resolves when the connection is closed on behalf of the\n * user by calling `close()` or when a shutdown signal is received.\n */\n private closingPromise: Promise<void> | undefined;\n private resolveClosingPromise:\n | ((value: void | PromiseLike<void>) => void)\n | undefined;\n\n constructor(options: ConnectHandlerOptions) {\n if (\n !Array.isArray(options.apps) ||\n options.apps.length === 0 ||\n !options.apps[0]\n ) {\n throw new Error(\"No apps provided\");\n }\n\n this.inngest = options.apps[0].client as Inngest.Any;\n for (const app of options.apps) {\n const client = app.client as Inngest.Any;\n\n if (client.env !== this.inngest.env) {\n throw new Error(\n `All apps must be configured to the same environment. ${client.id} is configured to ${client.env} but ${this.inngest.id} is configured to ${this.inngest.env}`,\n );\n }\n }\n\n this.options = this.applyDefaults(options);\n\n this._inngestEnv = this.inngest.env ?? getEnvironmentName();\n\n this.debug = debug(\"inngest:connect\");\n\n this.messageBuffer = new MessageBuffer(this.inngest);\n\n this.closingPromise = new Promise((resolve) => {\n this.resolveClosingPromise = resolve;\n });\n }\n\n private get functions(): Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n > {\n const functions: Record<\n string,\n {\n client: Inngest.Like;\n functions: InngestFunction.Any[];\n }\n > = {};\n for (const app of this.options.apps) {\n const client = app.client as Inngest.Any;\n\n if (functions[client.id]) {\n throw new Error(`Duplicate app id: ${client.id}`);\n }\n\n functions[client.id] = {\n client: app.client,\n functions: (app.functions as InngestFunction.Any[]) ?? client.funcs,\n };\n }\n return functions;\n }\n\n private applyDefaults(opts: ConnectHandlerOptions): ConnectHandlerOptions {\n const options = { ...opts };\n if (!Array.isArray(options.handleShutdownSignals)) {\n options.handleShutdownSignals = DEFAULT_SHUTDOWN_SIGNALS;\n }\n\n const env = allProcessEnv();\n options.signingKey = options.signingKey || env[envKeys.InngestSigningKey];\n options.signingKeyFallback =\n options.signingKeyFallback || env[envKeys.InngestSigningKeyFallback];\n\n if (options.maxWorkerConcurrency === undefined) {\n const envValue = env[envKeys.InngestConnectMaxWorkerConcurrency];\n if (envValue) {\n const parsed = Number.parseInt(envValue, 10);\n if (!Number.isNaN(parsed) && parsed > 0) {\n options.maxWorkerConcurrency = parsed;\n }\n }\n }\n\n return options;\n }\n\n async close(): Promise<void> {\n // Remove the shutdown signal handler\n if (this.cleanupShutdownSignal) {\n this.cleanupShutdownSignal();\n this.cleanupShutdownSignal = undefined;\n }\n\n this.state = ConnectionState.CLOSING;\n\n this.debug(\"Cleaning up connection resources\");\n\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\n\n this.debug(\"Connection closed\");\n\n this.debug(\"Waiting for in-flight requests to complete\");\n\n await this.inProgressRequests.wg.wait();\n\n this.debug(\"Flushing messages before closing\");\n\n try {\n await this.messageBuffer.flush(this._hashedSigningKey);\n } catch (err) {\n this.debug(\"Failed to flush messages, using fallback key\", err);\n await this.messageBuffer.flush(this._hashedFallbackKey);\n }\n\n this.state = ConnectionState.CLOSED;\n this.resolveClosingPromise?.();\n\n this.debug(\"Fully closed\");\n\n return this.closed;\n }\n\n /**\n * A promise that resolves when the connection is closed on behalf of the\n * user by calling `close()` or when a shutdown signal is received.\n */\n get closed(): Promise<void> {\n if (!this.closingPromise) {\n throw new Error(\"No connection established\");\n }\n return this.closingPromise;\n }\n\n /**\n * The current connection ID of the worker.\n */\n get connectionId(): string {\n if (!this.currentConnection) {\n throw new Error(\"Connection not prepared\");\n }\n return this.currentConnection.id;\n }\n\n /**\n * Establish a persistent connection to the gateway.\n */\n public async connect(attempt = 0, path: string[] = []) {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n if (\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED\n ) {\n throw new Error(\"Connection already closed\");\n }\n\n this.debug(\"Establishing connection\", { attempt });\n\n if (this.inngest[\"mode\"].isCloud && !this.options.signingKey) {\n throw new Error(\"Signing key is required\");\n }\n\n this._hashedSigningKey = this.options.signingKey\n ? hashSigningKey(this.options.signingKey)\n : undefined;\n\n if (\n this.options.signingKey &&\n this.options.signingKey.startsWith(\n InngestBranchEnvironmentSigningKeyPrefix,\n ) &&\n !this._inngestEnv\n ) {\n throw new Error(\n \"Environment is required when using branch environment signing keys\",\n );\n }\n\n if (this.options.signingKeyFallback) {\n this._hashedFallbackKey = hashSigningKey(this.options.signingKeyFallback);\n }\n\n try {\n await this.messageBuffer.flush(this._hashedSigningKey);\n } catch (err) {\n this.debug(\"Failed to flush messages, using fallback key\", err);\n await this.messageBuffer.flush(this._hashedFallbackKey);\n }\n\n const capabilities: Capabilities = {\n trust_probe: \"v1\",\n connect: \"v1\",\n };\n\n const functionConfigs: Record<\n string,\n {\n client: Inngest.Like;\n functions: FunctionConfig[];\n }\n > = {};\n for (const [appId, { client, functions }] of Object.entries(\n this.functions,\n )) {\n functionConfigs[appId] = {\n client: client,\n functions: functions.flatMap((f) =>\n f[\"getConfig\"]({\n baseUrl: new URL(\"wss://connect\"),\n appPrefix: (client as Inngest.Any).id,\n isConnect: true,\n }),\n ),\n };\n }\n\n this.debug(\"Prepared sync data\", {\n functionSlugs: Object.entries(functionConfigs).map(\n ([appId, { functions }]) => {\n return JSON.stringify({\n appId,\n functions: functions.map((f) => ({\n id: f.id,\n stepUrls: Object.values(f.steps).map((s) => s.runtime[\"url\"]),\n })),\n });\n },\n ),\n });\n\n const data: connectionEstablishData = {\n manualReadinessAck: false,\n\n marshaledCapabilities: JSON.stringify(capabilities),\n apps: Object.entries(functionConfigs).map(\n ([appId, { client, functions }]) => ({\n appName: appId,\n appVersion: (client as Inngest.Any).appVersion,\n functions: new TextEncoder().encode(JSON.stringify(functions)),\n }),\n ),\n };\n\n const requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n > = {};\n for (const [appId, { client, functions }] of Object.entries(\n this.functions,\n )) {\n const inngestCommHandler: ConnectCommHandler = new InngestCommHandler({\n client: client,\n functions: functions,\n frameworkName: \"connect\",\n signingKey: this.options.signingKey,\n signingKeyFallback: this.options.signingKeyFallback,\n skipSignatureValidation: true,\n handler: (msg: GatewayExecutorRequestData) => {\n const asString = new TextDecoder().decode(msg.requestPayload);\n const parsed = parseFnData(JSON.parse(asString));\n\n const userTraceCtx = parseTraceCtx(msg.userTraceCtx);\n\n return {\n body() {\n return parsed;\n },\n method() {\n return \"POST\";\n },\n headers(key) {\n switch (key) {\n case headerKeys.ContentLength.toString():\n return asString.length.toString();\n case headerKeys.InngestExpectedServerKind.toString():\n return \"connect\";\n case headerKeys.RequestVersion.toString():\n return parsed.version.toString();\n case headerKeys.Signature.toString():\n // Note: Signature is disabled for connect\n return null;\n case headerKeys.TraceParent.toString():\n return userTraceCtx?.traceParent ?? null;\n case headerKeys.TraceState.toString():\n return userTraceCtx?.traceState ?? null;\n default:\n return null;\n }\n },\n transformResponse({ body, headers, status }) {\n let sdkResponseStatus: SDKResponseStatus = SDKResponseStatus.DONE;\n switch (status) {\n case 200:\n sdkResponseStatus = SDKResponseStatus.DONE;\n break;\n case 206:\n sdkResponseStatus = SDKResponseStatus.NOT_COMPLETED;\n break;\n case 500:\n sdkResponseStatus = SDKResponseStatus.ERROR;\n break;\n }\n\n return SDKResponse.create({\n requestId: msg.requestId,\n accountId: msg.accountId,\n envId: msg.envId,\n appId: msg.appId,\n status: sdkResponseStatus,\n body: new TextEncoder().encode(body),\n noRetry: headers[headerKeys.NoRetry] === \"true\",\n retryAfter: headers[headerKeys.RetryAfter],\n sdkVersion: `inngest-js:v${version}`,\n requestVersion: parseInt(\n headers[headerKeys.RequestVersion] ??\n PREFERRED_EXECUTION_VERSION.toString(),\n 10,\n ),\n systemTraceCtx: msg.systemTraceCtx,\n userTraceCtx: msg.userTraceCtx,\n runId: msg.runId,\n });\n },\n url() {\n const baseUrl = new URL(\"http://connect.inngest.com\");\n\n baseUrl.searchParams.set(queryKeys.FnId, msg.functionSlug);\n\n if (msg.stepId) {\n baseUrl.searchParams.set(queryKeys.StepId, msg.stepId);\n }\n\n return baseUrl;\n },\n };\n },\n });\n const requestHandler = inngestCommHandler.createHandler();\n requestHandlers[appId] = requestHandler;\n }\n\n if (\n this.options.handleShutdownSignals &&\n this.options.handleShutdownSignals.length > 0\n ) {\n this.setupShutdownSignal(this.options.handleShutdownSignals);\n }\n\n let useSigningKey = this._hashedSigningKey;\n while (\n ![ConnectionState.CLOSING, ConnectionState.CLOSED].includes(this.state)\n ) {\n // Clean up any previous connection state\n // Note: Never reset the message buffer, as there may be pending/unsent messages\n {\n // Flush any pending messages\n await this.messageBuffer.flush(useSigningKey);\n }\n\n try {\n await this.prepareConnection(\n requestHandlers,\n useSigningKey,\n data,\n attempt,\n [...path],\n );\n return;\n } catch (err) {\n this.debug(\"Failed to connect\", err);\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback = useSigningKey === this._hashedSigningKey;\n if (switchToFallback) {\n this.debug(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this._hashedFallbackKey\n : this._hashedSigningKey;\n }\n\n if (err instanceof ConnectionLimitError) {\n console.error(\n \"You have reached the maximum number of concurrent connections. Please disconnect other active workers to continue.\",\n );\n // Continue reconnecting, do not throw.\n }\n\n const delay = expBackoff(attempt);\n this.debug(\"Reconnecting in\", delay, \"ms\");\n\n const cancelled = await waitWithCancel(\n delay,\n () =>\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED,\n );\n if (cancelled) {\n this.debug(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.debug(\"Exiting connect loop\");\n }\n\n private async sendStartRequest(\n hashedSigningKey: string | undefined,\n attempt: number,\n ) {\n const msg = createStartRequest(Array.from(this.excludeGateways));\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/protobuf\",\n ...(hashedSigningKey\n ? { Authorization: `Bearer ${hashedSigningKey}` }\n : {}),\n };\n\n if (this._inngestEnv) {\n headers[headerKeys.Environment] = this._inngestEnv;\n }\n\n // refactor this to a more universal spot\n const targetUrl =\n await this.inngest[\"inngestApi\"][\"getTargetUrl\"](\"/v0/connect/start\");\n\n let resp;\n try {\n resp = await fetch(targetUrl, {\n method: \"POST\",\n body: new Uint8Array(msg),\n headers: headers,\n });\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : \"Unknown error\";\n throw new ReconnectError(\n `Failed initial API handshake request to ${targetUrl.toString()}, ${errMsg}`,\n attempt,\n );\n }\n\n if (!resp.ok) {\n if (resp.status === 401) {\n throw new AuthError(\n `Failed initial API handshake request to ${targetUrl.toString()}${\n this._inngestEnv ? ` (env: ${this._inngestEnv})` : \"\"\n }, ${await resp.text()}`,\n attempt,\n );\n }\n\n if (resp.status === 429) {\n throw new ConnectionLimitError(attempt);\n }\n\n throw new ReconnectError(\n `Failed initial API handshake request to ${targetUrl.toString()}, ${await resp.text()}`,\n attempt,\n );\n }\n\n const startResp = await parseStartResponse(resp);\n\n return startResp;\n }\n\n private async prepareConnection(\n requestHandlers: Record<\n string,\n (msg: GatewayExecutorRequestData) => Promise<SDKResponse>\n >,\n hashedSigningKey: string | undefined,\n data: connectionEstablishData,\n attempt: number,\n path: string[] = [],\n ): Promise<{ cleanup: () => void }> {\n let closed = false;\n\n this.debug(\"Preparing connection\", {\n attempt,\n path,\n });\n\n const startedAt = new Date();\n\n const startResp = await this.sendStartRequest(hashedSigningKey, attempt);\n\n const connectionId = startResp.connectionId;\n path.push(connectionId);\n\n let resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined;\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n let rejectWebsocketConnected: ((reason?: any) => void) | undefined;\n const websocketConnectedPromise = new Promise((resolve, reject) => {\n resolveWebsocketConnected = resolve;\n rejectWebsocketConnected = reject;\n });\n\n const connectTimeout = setTimeout(() => {\n this.excludeGateways.add(startResp.gatewayGroup);\n rejectWebsocketConnected?.(\n new ReconnectError(`Connection ${connectionId} timed out`, attempt),\n );\n }, 10_000);\n\n let finalEndpoint = startResp.gatewayEndpoint;\n if (this.options.rewriteGatewayEndpoint) {\n const rewritten = this.options.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.debug(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.debug(`Connecting to gateway`, {\n endpoint: finalEndpoint,\n gatewayGroup: startResp.gatewayGroup,\n connectionId,\n });\n\n const ws = new WebSocket(finalEndpoint, [ConnectWebSocketProtocol]);\n ws.binaryType = \"arraybuffer\";\n\n let onConnectionError: (error: unknown) => void | Promise<void>;\n {\n onConnectionError = (error: unknown) => {\n // Only process the first error per connection\n if (closed) {\n this.debug(\n `Connection error while initializing but already in closed state, skipping`,\n {\n connectionId,\n },\n );\n return;\n }\n closed = true;\n\n this.debug(`Connection error in connecting state, rejecting promise`, {\n connectionId,\n });\n\n this.excludeGateways.add(startResp.gatewayGroup);\n\n clearTimeout(connectTimeout);\n\n // Make sure to close the WebSocket if it's still open\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001, // incomplete setup\n workerDisconnectReasonToJSON(WorkerDisconnectReason.UNEXPECTED),\n );\n\n rejectWebsocketConnected?.(\n new ReconnectError(\n `Error while connecting (${connectionId}): ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n attempt,\n ),\n );\n };\n\n ws.onerror = (err) => onConnectionError(err);\n ws.onclose = (ev) => {\n void onConnectionError(\n new ReconnectError(\n `Connection ${connectionId} closed: ${ev.reason}`,\n attempt,\n ),\n );\n };\n }\n\n /**\n * The current setup state of the connection.\n */\n const setupState = {\n receivedGatewayHello: false,\n sentWorkerConnect: false,\n receivedConnectionReady: false,\n };\n\n let heartbeatIntervalMs: number | undefined;\n let extendLeaseIntervalMs: number | undefined;\n\n ws.onmessage = async (event) => {\n const messageBytes = new Uint8Array(event.data as ArrayBuffer);\n\n const connectMessage = parseConnectMessage(messageBytes);\n\n this.debug(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n {\n connectionId,\n },\n );\n\n if (!setupState.receivedGatewayHello) {\n if (connectMessage.kind !== GatewayMessageType.GATEWAY_HELLO) {\n void onConnectionError(\n new ReconnectError(\n `Expected hello message, got ${gatewayMessageTypeToJSON(\n connectMessage.kind,\n )}`,\n attempt,\n ),\n );\n return;\n }\n setupState.receivedGatewayHello = true;\n }\n\n if (!setupState.sentWorkerConnect) {\n const workerConnectRequestMsg = WorkerConnectRequestData.create({\n connectionId: startResp.connectionId,\n environment: this._inngestEnv,\n platform: getPlatformName({\n ...allProcessEnv(),\n }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck: data.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: data.apps,\n capabilities: new TextEncoder().encode(data.marshaledCapabilities),\n startedAt: startedAt,\n instanceId: this.options.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.options.maxWorkerConcurrency,\n });\n\n const workerConnectRequestMsgBytes = WorkerConnectRequestData.encode(\n workerConnectRequestMsg,\n ).finish();\n\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_CONNECT,\n payload: workerConnectRequestMsgBytes,\n }),\n ).finish(),\n );\n\n setupState.sentWorkerConnect = true;\n return;\n }\n\n if (!setupState.receivedConnectionReady) {\n if (\n connectMessage.kind !== GatewayMessageType.GATEWAY_CONNECTION_READY\n ) {\n void onConnectionError(\n new ReconnectError(\n `Expected ready message, got ${gatewayMessageTypeToJSON(\n connectMessage.kind,\n )}`,\n attempt,\n ),\n );\n return;\n }\n\n const readyPayload = GatewayConnectionReadyData.decode(\n connectMessage.payload,\n );\n\n setupState.receivedConnectionReady = true;\n\n // The intervals should be supplied by the gateway, but we should fall back just in case\n heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue) // TODO Grim cast\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue) // TODO Grim cast\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.debug(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState: setupState,\n state: this.state,\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\n this.state = ConnectionState.ACTIVE;\n this.excludeGateways.delete(startResp.gatewayGroup);\n\n attempt = 0;\n\n const conn: connection = {\n id: connectionId,\n ws,\n cleanup: () => {\n if (closed) {\n return;\n }\n closed = true;\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close();\n },\n pendingHeartbeats: 0,\n };\n this.currentConnection = conn;\n\n this.debug(`Connection ready (${connectionId})`);\n\n // Flag to prevent connecting twice in draining scenario:\n // 1. We're already draining and repeatedly trying to connect while keeping the old connection open\n // 2. The gateway closes the old connection after a timeout, causing a connection error (which would also trigger a new connection)\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n // Only process the first error per connection\n if (closed) {\n this.debug(`Connection error but already in closed state, skipping`, {\n connectionId,\n });\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n // Don't attempt to reconnect if we're already closing or closed\n if (\n this.state === ConnectionState.CLOSING ||\n this.state === ConnectionState.CLOSED\n ) {\n this.debug(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.state = ConnectionState.RECONNECTING;\n this.excludeGateways.add(startResp.gatewayGroup);\n\n // If this connection is draining and got closed unexpectedly, there's already a new connection being established\n if (isDraining) {\n this.debug(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.debug(`Connection error (${connectionId})`, error);\n this.connect(attempt + 1, [...path, \"onConnectionError\"]);\n };\n\n ws.onerror = (err) => onConnectionError(err);\n ws.onclose = (ev) => {\n void onConnectionError(\n new ReconnectError(`Connection closed: ${ev.reason}`, attempt),\n );\n };\n }\n\n ws.onmessage = async (event) => {\n const messageBytes = new Uint8Array(event.data as ArrayBuffer);\n\n const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.debug(\"Received draining message\", { connectionId });\n try {\n this.debug(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n // Wait for new conn to be successfully established\n await this.connect(0, [...path]);\n\n // Clean up the old connection\n await conn.cleanup();\n } catch (err) {\n this.debug(\"Failed to reconnect after receiving draining message\", {\n connectionId,\n err,\n });\n\n // Clean up the old connection\n await conn.cleanup();\n\n void onConnectionError(\n new ReconnectError(\n `Failed to reconnect after receiving draining message (${connectionId})`,\n attempt,\n ),\n );\n }\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_HEARTBEAT) {\n conn.pendingHeartbeats = 0;\n this.debug(\"Handled gateway heartbeat\", {\n connectionId,\n });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n if (this.state !== ConnectionState.ACTIVE) {\n this.debug(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.debug(\"Received gateway executor request\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n appName: gatewayExecutorRequest.appName,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n\n if (\n typeof gatewayExecutorRequest.appName !== \"string\" ||\n gatewayExecutorRequest.appName.length === 0\n ) {\n this.debug(\"No app name in request, skipping\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n return;\n }\n const requestHandler = requestHandlers[gatewayExecutorRequest.appName];\n\n if (!requestHandler) {\n this.debug(\"No request handler found for app, skipping\", {\n requestId: gatewayExecutorRequest.requestId,\n appId: gatewayExecutorRequest.appId,\n appName: gatewayExecutorRequest.appName,\n functionSlug: gatewayExecutorRequest.functionSlug,\n stepId: gatewayExecutorRequest.stepId,\n connectionId,\n });\n return;\n }\n\n // Ack received request\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REQUEST_ACK,\n payload: WorkerRequestAckData.encode(\n WorkerRequestAckData.create({\n accountId: gatewayExecutorRequest.accountId,\n envId: gatewayExecutorRequest.envId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n requestId: gatewayExecutorRequest.requestId,\n stepId: gatewayExecutorRequest.stepId,\n userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n runId: gatewayExecutorRequest.runId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n\n this.inProgressRequests.wg.add(1);\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ] = gatewayExecutorRequest.leaseId;\n\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n try {\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n // Only extend lease if it's still set on the request\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n this.debug(\"extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\n // Send extend lease request\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE,\n payload: WorkerRequestExtendLeaseData.encode(\n WorkerRequestExtendLeaseData.create({\n accountId: gatewayExecutorRequest.accountId,\n envId: gatewayExecutorRequest.envId,\n appId: gatewayExecutorRequest.appId,\n functionSlug: gatewayExecutorRequest.functionSlug,\n requestId: gatewayExecutorRequest.requestId,\n stepId: gatewayExecutorRequest.stepId,\n runId: gatewayExecutorRequest.runId,\n userTraceCtx: gatewayExecutorRequest.userTraceCtx,\n systemTraceCtx: gatewayExecutorRequest.systemTraceCtx,\n\n leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n const res = await requestHandler(gatewayExecutorRequest);\n\n this.debug(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n this.messageBuffer.addPending(res, ResponseAcknowlegeDeadline);\n\n if (!this.currentConnection) {\n this.debug(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n this.messageBuffer.append(res);\n return;\n }\n\n // Send reply back to gateway\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: SDKResponse.encode(res).finish(),\n }),\n ).finish(),\n );\n } finally {\n this.inProgressRequests.wg.done();\n delete this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n clearInterval(extendLeaseInterval);\n }\n\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.WORKER_REPLY_ACK) {\n const replyAck = parseWorkerReplyAck(connectMessage.payload);\n\n this.debug(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.messageBuffer.acknowledgePending(replyAck.requestId);\n\n return;\n }\n\n if (\n connectMessage.kind ===\n GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE_ACK\n ) {\n const extendLeaseAck = WorkerRequestExtendLeaseAckData.decode(\n connectMessage.payload,\n );\n\n this.debug(\"received extend lease ack\", {\n connectionId,\n newLeaseId: extendLeaseAck.newLeaseId,\n });\n\n if (extendLeaseAck.newLeaseId) {\n this.inProgressRequests.requestLeases[extendLeaseAck.requestId] =\n extendLeaseAck.newLeaseId;\n } else {\n this.debug(\"unable to extend lease\", {\n connectionId,\n requestId: extendLeaseAck.requestId,\n });\n delete this.inProgressRequests.requestLeases[\n extendLeaseAck.requestId\n ];\n }\n\n return;\n }\n\n this.debug(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState: setupState,\n state: this.state,\n connectionId,\n });\n };\n\n let heartbeatInterval = undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n // Check if we've missed 2 consecutive heartbeats\n if (conn.pendingHeartbeats >= 2) {\n this.debug(\"Gateway heartbeat missed\");\n void onConnectionError(\n new ReconnectError(\n `Consecutive gateway heartbeats missed (${connectionId})`,\n attempt,\n ),\n );\n return;\n }\n\n this.debug(\"Sending worker heartbeat\", {\n connectionId,\n });\n\n // Send worker heartbeat\n conn.pendingHeartbeats++;\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_HEARTBEAT,\n }),\n ).finish(),\n );\n }, heartbeatIntervalMs);\n }\n\n conn.cleanup = () => {\n if (closed) {\n return;\n }\n closed = true;\n\n this.debug(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.debug(\"Sending pause message\", { connectionId });\n ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_PAUSE,\n }),\n ).finish(),\n );\n }\n\n this.debug(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n\n this.inProgressRequests.wg.wait().then(() => {\n // We must wait for all in-flight requests to complete before closing\n // the connection and stopping the heartbeater. If we don't, then\n // Inngest Server will mark the step as failed since it lost contact\n // with the worker\n\n ws.close(\n 1000,\n workerDisconnectReasonToJSON(WorkerDisconnectReason.WORKER_SHUTDOWN),\n );\n\n if (this.currentConnection?.id === connectionId) {\n this.currentConnection = undefined;\n }\n\n this.debug(\"Cleaning up worker heartbeat\", {\n connectionId,\n });\n\n clearInterval(heartbeatInterval);\n });\n };\n\n return conn;\n }\n\n private setupShutdownSignal(signals: string[]) {\n if (this.cleanupShutdownSignal) {\n return;\n }\n\n this.debug(`Setting up shutdown signal handler for ${signals.join(\", \")}`);\n\n const cleanupShutdownHandlers = onShutdown(signals, () => {\n this.debug(\"Received shutdown signal, closing connection\");\n void this.close();\n });\n\n this.cleanupShutdownSignal = () => {\n this.debug(\"Cleaning up shutdown signal handler\");\n cleanupShutdownHandlers();\n };\n }\n}\n\n// Export types for convenience\nexport {\n DEFAULT_SHUTDOWN_SIGNALS,\n type ConnectApp,\n type ConnectHandlerOptions,\n ConnectionState,\n type WorkerConnection,\n};\n\nexport const connect = async (\n options: ConnectHandlerOptions,\n): Promise<WorkerConnection> => {\n if (options.apps.length === 0) {\n throw new Error(\"No apps provided\");\n }\n\n const conn = new WebSocketWorkerConnection(options);\n\n await conn.connect();\n\n return conn;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAyDA,MAAM,6BAA6B;AAEnC,MAAM,2CAA2C;AAYjD,MAAM,2BAA2B;AAgBjC,IAAM,4BAAN,MAA4D;CAC1D,AAAQ;CACR,AAAQ;CACR,AAAQ;;;;CAKR,AAAO,QAAyBA,8BAAgB;;;;CAKhD,AAAQ;CAER,AAAQ,qBAOJ;EACF,IAAI,IAAIC,kCAAW;EACnB,eAAe,EAAE;EAClB;;;;CAKD,AAAQ;CAER,AAAQ;CACR,AAAQ;CAER,AAAQ;;;;CAKR,AAAQ,kCAA+B,IAAI,KAAK;;;;CAKhD,AAAQ;;;;;CAMR,AAAQ;CACR,AAAQ;CAIR,YAAY,SAAgC;AAC1C,MACE,CAAC,MAAM,QAAQ,QAAQ,KAAK,IAC5B,QAAQ,KAAK,WAAW,KACxB,CAAC,QAAQ,KAAK,GAEd,OAAM,IAAI,MAAM,mBAAmB;AAGrC,OAAK,UAAU,QAAQ,KAAK,GAAG;AAC/B,OAAK,MAAM,OAAO,QAAQ,MAAM;GAC9B,MAAM,SAAS,IAAI;AAEnB,OAAI,OAAO,QAAQ,KAAK,QAAQ,IAC9B,OAAM,IAAI,MACR,wDAAwD,OAAO,GAAG,oBAAoB,OAAO,IAAI,OAAO,KAAK,QAAQ,GAAG,oBAAoB,KAAK,QAAQ,MAC1J;;AAIL,OAAK,UAAU,KAAK,cAAc,QAAQ;AAE1C,OAAK,cAAc,KAAK,QAAQ,OAAOC,gCAAoB;AAE3D,OAAK,2BAAc,kBAAkB;AAErC,OAAK,gBAAgB,IAAIC,6BAAc,KAAK,QAAQ;AAEpD,OAAK,iBAAiB,IAAI,SAAS,YAAY;AAC7C,QAAK,wBAAwB;IAC7B;;CAGJ,IAAY,YAMV;EACA,MAAMC,YAMF,EAAE;AACN,OAAK,MAAM,OAAO,KAAK,QAAQ,MAAM;GACnC,MAAM,SAAS,IAAI;AAEnB,OAAI,UAAU,OAAO,IACnB,OAAM,IAAI,MAAM,qBAAqB,OAAO,KAAK;AAGnD,aAAU,OAAO,MAAM;IACrB,QAAQ,IAAI;IACZ,WAAY,IAAI,aAAuC,OAAO;IAC/D;;AAEH,SAAO;;CAGT,AAAQ,cAAc,MAAoD;EACxE,MAAM,UAAU,EAAE,GAAG,MAAM;AAC3B,MAAI,CAAC,MAAM,QAAQ,QAAQ,sBAAsB,CAC/C,SAAQ,wBAAwBC;EAGlC,MAAM,MAAMC,2BAAe;AAC3B,UAAQ,aAAa,QAAQ,cAAc,IAAIC,uBAAQ;AACvD,UAAQ,qBACN,QAAQ,sBAAsB,IAAIA,uBAAQ;AAE5C,MAAI,QAAQ,yBAAyB,QAAW;GAC9C,MAAM,WAAW,IAAIA,uBAAQ;AAC7B,OAAI,UAAU;IACZ,MAAM,SAAS,OAAO,SAAS,UAAU,GAAG;AAC5C,QAAI,CAAC,OAAO,MAAM,OAAO,IAAI,SAAS,EACpC,SAAQ,uBAAuB;;;AAKrC,SAAO;;CAGT,MAAM,QAAuB;AAE3B,MAAI,KAAK,uBAAuB;AAC9B,QAAK,uBAAuB;AAC5B,QAAK,wBAAwB;;AAG/B,OAAK,QAAQP,8BAAgB;AAE7B,OAAK,MAAM,mCAAmC;AAE9C,MAAI,KAAK,mBAAmB;AAC1B,SAAM,KAAK,kBAAkB,SAAS;AACtC,QAAK,oBAAoB;;AAG3B,OAAK,MAAM,oBAAoB;AAE/B,OAAK,MAAM,6CAA6C;AAExD,QAAM,KAAK,mBAAmB,GAAG,MAAM;AAEvC,OAAK,MAAM,mCAAmC;AAE9C,MAAI;AACF,SAAM,KAAK,cAAc,MAAM,KAAK,kBAAkB;WAC/C,KAAK;AACZ,QAAK,MAAM,gDAAgD,IAAI;AAC/D,SAAM,KAAK,cAAc,MAAM,KAAK,mBAAmB;;AAGzD,OAAK,QAAQA,8BAAgB;AAC7B,OAAK,yBAAyB;AAE9B,OAAK,MAAM,eAAe;AAE1B,SAAO,KAAK;;;;;;CAOd,IAAI,SAAwB;AAC1B,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,4BAA4B;AAE9C,SAAO,KAAK;;;;;CAMd,IAAI,eAAuB;AACzB,MAAI,CAAC,KAAK,kBACR,OAAM,IAAI,MAAM,0BAA0B;AAE5C,SAAO,KAAK,kBAAkB;;;;;CAMhC,MAAa,QAAQ,UAAU,GAAG,OAAiB,EAAE,EAAE;AACrD,MAAI,OAAO,cAAc,YACvB,OAAM,IAAI,MAAM,kDAAkD;AAGpE,MACE,KAAK,UAAUA,8BAAgB,WAC/B,KAAK,UAAUA,8BAAgB,OAE/B,OAAM,IAAI,MAAM,4BAA4B;AAG9C,OAAK,MAAM,2BAA2B,EAAE,SAAS,CAAC;AAElD,MAAI,KAAK,QAAQ,QAAQ,WAAW,CAAC,KAAK,QAAQ,WAChD,OAAM,IAAI,MAAM,0BAA0B;AAG5C,OAAK,oBAAoB,KAAK,QAAQ,aAClCQ,+BAAe,KAAK,QAAQ,WAAW,GACvC;AAEJ,MACE,KAAK,QAAQ,cACb,KAAK,QAAQ,WAAW,WACtB,yCACD,IACD,CAAC,KAAK,YAEN,OAAM,IAAI,MACR,qEACD;AAGH,MAAI,KAAK,QAAQ,mBACf,MAAK,qBAAqBA,+BAAe,KAAK,QAAQ,mBAAmB;AAG3E,MAAI;AACF,SAAM,KAAK,cAAc,MAAM,KAAK,kBAAkB;WAC/C,KAAK;AACZ,QAAK,MAAM,gDAAgD,IAAI;AAC/D,SAAM,KAAK,cAAc,MAAM,KAAK,mBAAmB;;EAGzD,MAAMC,eAA6B;GACjC,aAAa;GACb,SAAS;GACV;EAED,MAAMC,kBAMF,EAAE;AACN,OAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,gBAAgB,OAAO,QAClD,KAAK,UACN,CACC,iBAAgB,SAAS;GACf;GACR,WAAW,UAAU,SAAS,MAC5B,EAAE,aAAa;IACb,SAAS,IAAI,IAAI,gBAAgB;IACjC,WAAY,OAAuB;IACnC,WAAW;IACZ,CAAC,CACH;GACF;AAGH,OAAK,MAAM,sBAAsB,EAC/B,eAAe,OAAO,QAAQ,gBAAgB,CAAC,KAC5C,CAAC,OAAO,EAAE,iBAAiB;AAC1B,UAAO,KAAK,UAAU;IACpB;IACA,WAAW,UAAU,KAAK,OAAO;KAC/B,IAAI,EAAE;KACN,UAAU,OAAO,OAAO,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,QAAQ,OAAO;KAC9D,EAAE;IACJ,CAAC;IAEL,EACF,CAAC;EAEF,MAAMC,OAAgC;GACpC,oBAAoB;GAEpB,uBAAuB,KAAK,UAAU,aAAa;GACnD,MAAM,OAAO,QAAQ,gBAAgB,CAAC,KACnC,CAAC,OAAO,EAAE,QAAQ,kBAAkB;IACnC,SAAS;IACT,YAAa,OAAuB;IACpC,WAAW,IAAI,aAAa,CAAC,OAAO,KAAK,UAAU,UAAU,CAAC;IAC/D,EACF;GACF;EAED,MAAMC,kBAGF,EAAE;AACN,OAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,gBAAgB,OAAO,QAClD,KAAK,UACN,CAyFC,iBAAgB,SAxF+B,IAAIC,8CAAmB;GAC5D;GACG;GACX,eAAe;GACf,YAAY,KAAK,QAAQ;GACzB,oBAAoB,KAAK,QAAQ;GACjC,yBAAyB;GACzB,UAAU,QAAoC;IAC5C,MAAM,WAAW,IAAI,aAAa,CAAC,OAAO,IAAI,eAAe;IAC7D,MAAM,SAASC,8BAAY,KAAK,MAAM,SAAS,CAAC;IAEhD,MAAM,eAAeC,2BAAc,IAAI,aAAa;AAEpD,WAAO;KACL,OAAO;AACL,aAAO;;KAET,SAAS;AACP,aAAO;;KAET,QAAQ,KAAK;AACX,cAAQ,KAAR;OACE,KAAKC,0BAAW,cAAc,UAAU,CACtC,QAAO,SAAS,OAAO,UAAU;OACnC,KAAKA,0BAAW,0BAA0B,UAAU,CAClD,QAAO;OACT,KAAKA,0BAAW,eAAe,UAAU,CACvC,QAAO,OAAO,QAAQ,UAAU;OAClC,KAAKA,0BAAW,UAAU,UAAU,CAElC,QAAO;OACT,KAAKA,0BAAW,YAAY,UAAU,CACpC,QAAO,cAAc,eAAe;OACtC,KAAKA,0BAAW,WAAW,UAAU,CACnC,QAAO,cAAc,cAAc;OACrC,QACE,QAAO;;;KAGb,kBAAkB,EAAE,MAAM,SAAS,UAAU;MAC3C,IAAIC,oBAAuCC,kCAAkB;AAC7D,cAAQ,QAAR;OACE,KAAK;AACH,4BAAoBA,kCAAkB;AACtC;OACF,KAAK;AACH,4BAAoBA,kCAAkB;AACtC;OACF,KAAK;AACH,4BAAoBA,kCAAkB;AACtC;;AAGJ,aAAOC,4BAAY,OAAO;OACxB,WAAW,IAAI;OACf,WAAW,IAAI;OACf,OAAO,IAAI;OACX,OAAO,IAAI;OACX,QAAQ;OACR,MAAM,IAAI,aAAa,CAAC,OAAO,KAAK;OACpC,SAAS,QAAQH,0BAAW,aAAa;OACzC,YAAY,QAAQA,0BAAW;OAC/B,YAAY,eAAeI;OAC3B,gBAAgB,SACd,QAAQJ,0BAAW,mBACjBK,qDAA4B,UAAU,EACxC,GACD;OACD,gBAAgB,IAAI;OACpB,cAAc,IAAI;OAClB,OAAO,IAAI;OACZ,CAAC;;KAEJ,MAAM;MACJ,MAAM,UAAU,IAAI,IAAI,6BAA6B;AAErD,cAAQ,aAAa,IAAIC,yBAAU,MAAM,IAAI,aAAa;AAE1D,UAAI,IAAI,OACN,SAAQ,aAAa,IAAIA,yBAAU,QAAQ,IAAI,OAAO;AAGxD,aAAO;;KAEV;;GAEJ,CAAC,CACwC,eAAe;AAI3D,MACE,KAAK,QAAQ,yBACb,KAAK,QAAQ,sBAAsB,SAAS,EAE5C,MAAK,oBAAoB,KAAK,QAAQ,sBAAsB;EAG9D,IAAI,gBAAgB,KAAK;AACzB,SACE,CAAC,CAACtB,8BAAgB,SAASA,8BAAgB,OAAO,CAAC,SAAS,KAAK,MAAM,EACvE;AAKE,SAAM,KAAK,cAAc,MAAM,cAAc;AAG/C,OAAI;AACF,UAAM,KAAK,kBACT,iBACA,eACA,MACA,SACA,CAAC,GAAG,KAAK,CACV;AACD;YACO,KAAK;AACZ,SAAK,MAAM,qBAAqB,IAAI;AAEpC,QAAI,EAAE,eAAeuB,6BACnB,OAAM;AAGR,cAAU,IAAI;AAEd,QAAI,eAAeC,wBAAW;KAC5B,MAAM,mBAAmB,kBAAkB,KAAK;AAChD,SAAI,iBACF,MAAK,MAAM,oCAAoC;AAEjD,qBAAgB,mBACZ,KAAK,qBACL,KAAK;;AAGX,QAAI,eAAeC,kCACjB,SAAQ,MACN,qHACD;IAIH,MAAM,QAAQC,wBAAW,QAAQ;AACjC,SAAK,MAAM,mBAAmB,OAAO,KAAK;AAQ1C,QANkB,MAAMC,4BACtB,aAEE,KAAK,UAAU3B,8BAAgB,WAC/B,KAAK,UAAUA,8BAAgB,OAClC,EACc;AACb,UAAK,MAAM,8BAA8B;AACzC;;AAGF;;;AAIJ,OAAK,MAAM,uBAAuB;;CAGpC,MAAc,iBACZ,kBACA,SACA;EACA,MAAM,MAAM4B,oCAAmB,MAAM,KAAK,KAAK,gBAAgB,CAAC;EAEhE,MAAMC,UAAkC;GACtC,gBAAgB;GAChB,GAAI,mBACA,EAAE,eAAe,UAAU,oBAAoB,GAC/C,EAAE;GACP;AAED,MAAI,KAAK,YACP,SAAQb,0BAAW,eAAe,KAAK;EAIzC,MAAM,YACJ,MAAM,KAAK,QAAQ,cAAc,gBAAgB,oBAAoB;EAEvE,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,MAAM,WAAW;IAC5B,QAAQ;IACR,MAAM,IAAI,WAAW,IAAI;IAChB;IACV,CAAC;WACK,KAAK;GACZ,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,SAAM,IAAIO,4BACR,2CAA2C,UAAU,UAAU,CAAC,IAAI,UACpE,QACD;;AAGH,MAAI,CAAC,KAAK,IAAI;AACZ,OAAI,KAAK,WAAW,IAClB,OAAM,IAAIC,uBACR,2CAA2C,UAAU,UAAU,GAC7D,KAAK,cAAc,UAAU,KAAK,YAAY,KAAK,GACpD,IAAI,MAAM,KAAK,MAAM,IACtB,QACD;AAGH,OAAI,KAAK,WAAW,IAClB,OAAM,IAAIC,kCAAqB,QAAQ;AAGzC,SAAM,IAAIF,4BACR,2CAA2C,UAAU,UAAU,CAAC,IAAI,MAAM,KAAK,MAAM,IACrF,QACD;;AAKH,SAFkB,MAAMO,oCAAmB,KAAK;;CAKlD,MAAc,kBACZ,iBAIA,kBACA,MACA,SACA,OAAiB,EAAE,EACe;EAClC,IAAI,SAAS;AAEb,OAAK,MAAM,wBAAwB;GACjC;GACA;GACD,CAAC;EAEF,MAAM,4BAAY,IAAI,MAAM;EAE5B,MAAM,YAAY,MAAM,KAAK,iBAAiB,kBAAkB,QAAQ;EAExE,MAAM,eAAe,UAAU;AAC/B,OAAK,KAAK,aAAa;EAEvB,IAAIC;EAIJ,IAAIC;EACJ,MAAM,4BAA4B,IAAI,SAAS,SAAS,WAAW;AACjE,+BAA4B;AAC5B,8BAA2B;IAC3B;EAEF,MAAM,iBAAiB,iBAAiB;AACtC,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAChD,8BACE,IAAIT,4BAAe,cAAc,aAAa,aAAa,QAAQ,CACpE;KACA,IAAO;EAEV,IAAI,gBAAgB,UAAU;AAC9B,MAAI,KAAK,QAAQ,wBAAwB;GACvC,MAAM,YAAY,KAAK,QAAQ,uBAC7B,UAAU,gBACX;AACD,QAAK,MAAM,8BAA8B;IACvC,UAAU,UAAU;IACpB;IACD,CAAC;AACF,mBAAgB;;AAGlB,OAAK,MAAM,yBAAyB;GAClC,UAAU;GACV,cAAc,UAAU;GACxB;GACD,CAAC;EAEF,MAAM,KAAK,IAAI,UAAU,eAAe,CAAC,yBAAyB,CAAC;AACnE,KAAG,aAAa;EAEhB,IAAIU,qBAEmB,UAAmB;AAEtC,OAAI,QAAQ;AACV,SAAK,MACH,6EACA,EACE,cACD,CACF;AACD;;AAEF,YAAS;AAET,QAAK,MAAM,2DAA2D,EACpE,cACD,CAAC;AAEF,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAEhD,gBAAa,eAAe;AAG5B,MAAG,gBAAgB;AACnB,MAAG,gBAAgB;AACnB,MAAG,MACD,MACAC,6CAA6BC,uCAAuB,WAAW,CAChE;AAED,8BACE,IAAIZ,4BACF,2BAA2B,aAAa,KACtC,iBAAiB,QAAQ,MAAM,UAAU,mBAE3C,QACD,CACF;;AAGH,KAAG,WAAW,QAAQ,kBAAkB,IAAI;AAC5C,KAAG,WAAW,OAAO;AACnB,GAAK,kBACH,IAAIA,4BACF,cAAc,aAAa,WAAW,GAAG,UACzC,QACD,CACF;;;;;EAOL,MAAM,aAAa;GACjB,sBAAsB;GACtB,mBAAmB;GACnB,yBAAyB;GAC1B;EAED,IAAIa;EACJ,IAAIC;AAEJ,KAAG,YAAY,OAAO,UAAU;GAG9B,MAAM,iBAAiBC,qCAFF,IAAI,WAAW,MAAM,KAAoB,CAEN;AAExD,QAAK,MACH,qBAAqBC,yCAAyB,eAAe,KAAK,IAClE,EACE,cACD,CACF;AAED,OAAI,CAAC,WAAW,sBAAsB;AACpC,QAAI,eAAe,SAASC,mCAAmB,eAAe;AAC5D,KAAK,kBACH,IAAIjB,4BACF,+BAA+BgB,yCAC7B,eAAe,KAChB,IACD,QACD,CACF;AACD;;AAEF,eAAW,uBAAuB;;AAGpC,OAAI,CAAC,WAAW,mBAAmB;IACjC,MAAM,0BAA0BE,yCAAyB,OAAO;KAC9D,cAAc,UAAU;KACxB,aAAa,KAAK;KAClB,UAAUC,4BAAgB,EACxB,GAAGpC,2BAAe,EACnB,CAAC;KACF,YAAY,IAAIc;KAChB,aAAa;KACb,WAAW;KACX,0BAA0B,KAAK;KAC/B,kBAAkB,MAAMuB,qCAA0B;KAClD,UAAU;MACR,cAAc,UAAU;MACxB,WAAW,UAAU;MACtB;KACD,MAAM,KAAK;KACX,cAAc,IAAI,aAAa,CAAC,OAAO,KAAK,sBAAsB;KACvD;KACX,YAAY,KAAK,QAAQ,cAAe,MAAMC,wBAAa;KAC3D,sBAAsB,KAAK,QAAQ;KACpC,CAAC;IAEF,MAAM,+BAA+BH,yCAAyB,OAC5D,wBACD,CAAC,QAAQ;AAEV,OAAG,KACDI,+BAAe,OACbA,+BAAe,OAAO;KACpB,MAAML,mCAAmB;KACzB,SAAS;KACV,CAAC,CACH,CAAC,QAAQ,CACX;AAED,eAAW,oBAAoB;AAC/B;;AAGF,OAAI,CAAC,WAAW,yBAAyB;AACvC,QACE,eAAe,SAASA,mCAAmB,0BAC3C;AACA,KAAK,kBACH,IAAIjB,4BACF,+BAA+BgB,yCAC7B,eAAe,KAChB,IACD,QACD,CACF;AACD;;IAGF,MAAM,eAAeO,2CAA2B,OAC9C,eAAe,QAChB;AAED,eAAW,0BAA0B;AAGrC,0BACE,aAAa,kBAAkB,SAAS,oBACjC,aAAa,kBAAoC,GACpD;AACN,4BACE,aAAa,oBAAoB,SAAS,oBACnC,aAAa,oBAAsC,GACtD;AAEN,iCAA6B;AAC7B;;AAGF,QAAK,MAAM,wCAAwC;IACjD,MAAMP,yCAAyB,eAAe,KAAK;IACnD,SAAS,eAAe;IACxB;IACY;IACZ,OAAO,KAAK;IACZ;IACD,CAAC;;AAGJ,QAAM;AAEN,eAAa,eAAe;AAE5B,OAAK,QAAQvC,8BAAgB;AAC7B,OAAK,gBAAgB,OAAO,UAAU,aAAa;AAEnD,YAAU;EAEV,MAAM+C,OAAmB;GACvB,IAAI;GACJ;GACA,eAAe;AACb,QAAI,OACF;AAEF,aAAS;AACT,OAAG,gBAAgB;AACnB,OAAG,gBAAgB;AACnB,OAAG,OAAO;;GAEZ,mBAAmB;GACpB;AACD,OAAK,oBAAoB;AAEzB,OAAK,MAAM,qBAAqB,aAAa,GAAG;EAKhD,IAAI,aAAa;AAEf,sBAAoB,OAAO,UAAmB;AAE5C,OAAI,QAAQ;AACV,SAAK,MAAM,0DAA0D,EACnE,cACD,CAAC;AACF;;AAEF,YAAS;AAET,SAAM,KAAK,SAAS;AAGpB,OACE,KAAK,UAAU/C,8BAAgB,WAC/B,KAAK,UAAUA,8BAAgB,QAC/B;AACA,SAAK,MACH,qBAAqB,aAAa,2CACnC;AACD;;AAGF,QAAK,QAAQA,8BAAgB;AAC7B,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAGhD,OAAI,YAAY;AACd,SAAK,MACH,qBAAqB,aAAa,kCACnC;AACD;;AAGF,QAAK,MAAM,qBAAqB,aAAa,IAAI,MAAM;AACvD,QAAK,QAAQ,UAAU,GAAG,CAAC,GAAG,MAAM,oBAAoB,CAAC;;AAG3D,KAAG,WAAW,QAAQ,kBAAkB,IAAI;AAC5C,KAAG,WAAW,OAAO;AACnB,GAAK,kBACH,IAAIuB,4BAAe,sBAAsB,GAAG,UAAU,QAAQ,CAC/D;;AAIL,KAAG,YAAY,OAAO,UAAU;GAG9B,MAAM,iBAAiBe,qCAFF,IAAI,WAAW,MAAM,KAAoB,CAEN;AAExD,OAAI,eAAe,SAASE,mCAAmB,iBAAiB;AAC9D,iBAAa;AACb,SAAK,MAAM,6BAA6B,EAAE,cAAc,CAAC;AACzD,QAAI;AACF,UAAK,MACH,oEACA,EAAE,cAAc,CACjB;AAGD,WAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC;AAGhC,WAAM,KAAK,SAAS;aACb,KAAK;AACZ,UAAK,MAAM,wDAAwD;MACjE;MACA;MACD,CAAC;AAGF,WAAM,KAAK,SAAS;AAEpB,KAAK,kBACH,IAAIjB,4BACF,yDAAyD,aAAa,IACtE,QACD,CACF;;AAEH;;AAGF,OAAI,eAAe,SAASiB,mCAAmB,mBAAmB;AAChE,SAAK,oBAAoB;AACzB,SAAK,MAAM,6BAA6B,EACtC,cACD,CAAC;AACF;;AAGF,OAAI,eAAe,SAASA,mCAAmB,0BAA0B;AACvE,QAAI,KAAK,UAAUxC,8BAAgB,QAAQ;AACzC,UAAK,MAAM,+CAA+C,EACxD,cACD,CAAC;AACF;;IAGF,MAAM,yBAAyBgD,6CAC7B,eAAe,QAChB;AAED,SAAK,MAAM,qCAAqC;KAC9C,WAAW,uBAAuB;KAClC,OAAO,uBAAuB;KAC9B,SAAS,uBAAuB;KAChC,cAAc,uBAAuB;KACrC,QAAQ,uBAAuB;KAC/B;KACD,CAAC;AAEF,QACE,OAAO,uBAAuB,YAAY,YAC1C,uBAAuB,QAAQ,WAAW,GAC1C;AACA,UAAK,MAAM,oCAAoC;MAC7C,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,QAAQ,uBAAuB;MAC/B;MACD,CAAC;AACF;;IAEF,MAAM,iBAAiB,gBAAgB,uBAAuB;AAE9D,QAAI,CAAC,gBAAgB;AACnB,UAAK,MAAM,8CAA8C;MACvD,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,SAAS,uBAAuB;MAChC,cAAc,uBAAuB;MACrC,QAAQ,uBAAuB;MAC/B;MACD,CAAC;AACF;;AAIF,OAAG,KACDH,+BAAe,OACbA,+BAAe,OAAO;KACpB,MAAML,mCAAmB;KACzB,SAASS,qCAAqB,OAC5BA,qCAAqB,OAAO;MAC1B,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,WAAW,uBAAuB;MAClC,QAAQ,uBAAuB;MAC/B,cAAc,uBAAuB;MACrC,gBAAgB,uBAAuB;MACvC,OAAO,uBAAuB;MAC/B,CAAC,CACH,CAAC,QAAQ;KACX,CAAC,CACH,CAAC,QAAQ,CACX;AAED,SAAK,mBAAmB,GAAG,IAAI,EAAE;AACjC,SAAK,mBAAmB,cACtB,uBAAuB,aACrB,uBAAuB;IAE3B,IAAIC;AACJ,QAAI;AACF,2BAAsB,kBAAkB;AACtC,UAAI,0BAA0B,OAC5B;MAIF,MAAM,iBACJ,KAAK,mBAAmB,cACtB,uBAAuB;AAE3B,UAAI,CAAC,gBAAgB;AACnB,qBAAc,oBAAoB;AAClC;;AAGF,WAAK,MAAM,mBAAmB;OAC5B;OACA,SAAS;OACV,CAAC;AAGF,SAAG,KACDL,+BAAe,OACbA,+BAAe,OAAO;OACpB,MAAML,mCAAmB;OACzB,SAASW,6CAA6B,OACpCA,6CAA6B,OAAO;QAClC,WAAW,uBAAuB;QAClC,OAAO,uBAAuB;QAC9B,OAAO,uBAAuB;QAC9B,cAAc,uBAAuB;QACrC,WAAW,uBAAuB;QAClC,QAAQ,uBAAuB;QAC/B,OAAO,uBAAuB;QAC9B,cAAc,uBAAuB;QACrC,gBAAgB,uBAAuB;QAEvC,SAAS;QACV,CAAC,CACH,CAAC,QAAQ;OACX,CAAC,CACH,CAAC,QAAQ,CACX;QACA,sBAAsB;KAEzB,MAAM,MAAM,MAAM,eAAe,uBAAuB;AAExD,UAAK,MAAM,wBAAwB;MACjC;MACA,WAAW,uBAAuB;MACnC,CAAC;AAEF,UAAK,cAAc,WAAW,KAAK,2BAA2B;AAE9D,SAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,MAAM,4CAA4C;OACrD;OACA,WAAW,uBAAuB;OACnC,CAAC;AACF,WAAK,cAAc,OAAO,IAAI;AAC9B;;AAIF,UAAK,kBAAkB,GAAG,KACxBN,+BAAe,OACbA,+BAAe,OAAO;MACpB,MAAML,mCAAmB;MACzB,SAASrB,4BAAY,OAAO,IAAI,CAAC,QAAQ;MAC1C,CAAC,CACH,CAAC,QAAQ,CACX;cACO;AACR,UAAK,mBAAmB,GAAG,MAAM;AACjC,YAAO,KAAK,mBAAmB,cAC7B,uBAAuB;AAEzB,mBAAc,oBAAoB;;AAGpC;;AAGF,OAAI,eAAe,SAASqB,mCAAmB,kBAAkB;IAC/D,MAAM,WAAWY,qCAAoB,eAAe,QAAQ;AAE5D,SAAK,MAAM,2BAA2B;KACpC;KACA,WAAW,SAAS;KACrB,CAAC;AAEF,SAAK,cAAc,mBAAmB,SAAS,UAAU;AAEzD;;AAGF,OACE,eAAe,SACfZ,mCAAmB,iCACnB;IACA,MAAM,iBAAiBa,gDAAgC,OACrD,eAAe,QAChB;AAED,SAAK,MAAM,6BAA6B;KACtC;KACA,YAAY,eAAe;KAC5B,CAAC;AAEF,QAAI,eAAe,WACjB,MAAK,mBAAmB,cAAc,eAAe,aACnD,eAAe;SACZ;AACL,UAAK,MAAM,0BAA0B;MACnC;MACA,WAAW,eAAe;MAC3B,CAAC;AACF,YAAO,KAAK,mBAAmB,cAC7B,eAAe;;AAInB;;AAGF,QAAK,MAAM,2BAA2B;IACpC,MAAMd,yCAAyB,eAAe,KAAK;IACnD,SAAS,eAAe;IACxB;IACY;IACZ,OAAO,KAAK;IACZ;IACD,CAAC;;EAGJ,IAAI,oBAAoB;AACxB,MAAI,wBAAwB,OAC1B,qBAAoB,kBAAkB;AACpC,OAAI,wBAAwB,OAC1B;AAIF,OAAI,KAAK,qBAAqB,GAAG;AAC/B,SAAK,MAAM,2BAA2B;AACtC,IAAK,kBACH,IAAIhB,4BACF,0CAA0C,aAAa,IACvD,QACD,CACF;AACD;;AAGF,QAAK,MAAM,4BAA4B,EACrC,cACD,CAAC;AAGF,QAAK;AACL,MAAG,KACDsB,+BAAe,OACbA,+BAAe,OAAO,EACpB,MAAML,mCAAmB,kBAC1B,CAAC,CACH,CAAC,QAAQ,CACX;KACA,oBAAoB;AAGzB,OAAK,gBAAgB;AACnB,OAAI,OACF;AAEF,YAAS;AAET,QAAK,MAAM,0BAA0B,EAAE,cAAc,CAAC;AACtD,OAAI,GAAG,eAAe,UAAU,MAAM;AACpC,SAAK,MAAM,yBAAyB,EAAE,cAAc,CAAC;AACrD,OAAG,KACDK,+BAAe,OACbA,+BAAe,OAAO,EACpB,MAAML,mCAAmB,cAC1B,CAAC,CACH,CAAC,QAAQ,CACX;;AAGH,QAAK,MAAM,sBAAsB,EAAE,cAAc,CAAC;AAClD,MAAG,gBAAgB;AACnB,MAAG,gBAAgB;AAEnB,QAAK,mBAAmB,GAAG,MAAM,CAAC,WAAW;AAM3C,OAAG,MACD,KACAN,6CAA6BC,uCAAuB,gBAAgB,CACrE;AAED,QAAI,KAAK,mBAAmB,OAAO,aACjC,MAAK,oBAAoB;AAG3B,SAAK,MAAM,gCAAgC,EACzC,cACD,CAAC;AAEF,kBAAc,kBAAkB;KAChC;;AAGJ,SAAO;;CAGT,AAAQ,oBAAoB,SAAmB;AAC7C,MAAI,KAAK,sBACP;AAGF,OAAK,MAAM,0CAA0C,QAAQ,KAAK,KAAK,GAAG;EAE1E,MAAM,0BAA0BmB,sBAAW,eAAe;AACxD,QAAK,MAAM,+CAA+C;AAC1D,GAAK,KAAK,OAAO;IACjB;AAEF,OAAK,8BAA8B;AACjC,QAAK,MAAM,sCAAsC;AACjD,4BAAyB;;;;AAc/B,MAAa,UAAU,OACrB,YAC8B;AAC9B,KAAI,QAAQ,KAAK,WAAW,EAC1B,OAAM,IAAI,MAAM,mBAAmB;CAGrC,MAAM,OAAO,IAAI,0BAA0B,QAAQ;AAEnD,OAAM,KAAK,SAAS;AAEpB,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":[],"mappings":";;;cAqxCa,mBACF,0BACR,QAAQ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":[],"mappings":";;;cA6xCa,mBACF,0BACR,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":[],"mappings":";;;cAqxCa,mBACF,0BACR,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/components/connect/index.ts"],"sourcesContent":[],"mappings":";;;cA6xCa,mBACF,0BACR,QAAQ"}
@@ -653,8 +653,6 @@ var WebSocketWorkerConnection = class {
653
653
  ws.send(ConnectMessage.encode(ConnectMessage.create({ kind: GatewayMessageType.WORKER_HEARTBEAT })).finish());
654
654
  }, heartbeatIntervalMs);
655
655
  conn.cleanup = () => {
656
- this.debug("Cleaning up worker heartbeat", { connectionId });
657
- clearInterval(heartbeatInterval);
658
656
  if (closed) return;
659
657
  closed = true;
660
658
  this.debug("Cleaning up connection", { connectionId });
@@ -665,8 +663,12 @@ var WebSocketWorkerConnection = class {
665
663
  this.debug("Closing connection", { connectionId });
666
664
  ws.onerror = () => {};
667
665
  ws.onclose = () => {};
668
- ws.close(1e3, workerDisconnectReasonToJSON(WorkerDisconnectReason.WORKER_SHUTDOWN));
669
- if (this.currentConnection?.id === connectionId) this.currentConnection = void 0;
666
+ this.inProgressRequests.wg.wait().then(() => {
667
+ ws.close(1e3, workerDisconnectReasonToJSON(WorkerDisconnectReason.WORKER_SHUTDOWN));
668
+ if (this.currentConnection?.id === connectionId) this.currentConnection = void 0;
669
+ this.debug("Cleaning up worker heartbeat", { connectionId });
670
+ clearInterval(heartbeatInterval);
671
+ });
670
672
  };
671
673
  return conn;
672
674
  }