inngest 3.52.6 → 3.52.7
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.
- package/CHANGELOG.md +8 -0
- package/api/schema.d.cts +2 -2
- package/api/schema.d.cts.map +1 -1
- package/api/schema.d.ts +2 -2
- package/api/schema.d.ts.map +1 -1
- package/components/connect/strategies/core/connection.cjs +14 -8
- package/components/connect/strategies/core/connection.cjs.map +1 -1
- package/components/connect/strategies/core/connection.js +14 -8
- package/components/connect/strategies/core/connection.js.map +1 -1
- package/components/execution/otel/consts.cjs +1 -0
- package/components/execution/otel/consts.cjs.map +1 -1
- package/components/execution/otel/consts.js +1 -0
- package/components/execution/otel/consts.js.map +1 -1
- package/components/execution/otel/processor.cjs +56 -5
- package/components/execution/otel/processor.cjs.map +1 -1
- package/components/execution/otel/processor.d.cts +11 -0
- package/components/execution/otel/processor.d.cts.map +1 -1
- package/components/execution/otel/processor.d.ts +11 -0
- package/components/execution/otel/processor.d.ts.map +1 -1
- package/components/execution/otel/processor.js +56 -5
- package/components/execution/otel/processor.js.map +1 -1
- package/components/execution/v1.cjs +4 -0
- package/components/execution/v1.cjs.map +1 -1
- package/components/execution/v1.d.cts.map +1 -1
- package/components/execution/v1.d.ts.map +1 -1
- package/components/execution/v1.js +4 -0
- package/components/execution/v1.js.map +1 -1
- package/components/execution/v2.cjs +4 -0
- package/components/execution/v2.cjs.map +1 -1
- package/components/execution/v2.d.cts.map +1 -1
- package/components/execution/v2.d.ts.map +1 -1
- package/components/execution/v2.js +4 -0
- package/components/execution/v2.js.map +1 -1
- package/helpers/deterministicId.cjs +298 -0
- package/helpers/deterministicId.cjs.map +1 -0
- package/helpers/deterministicId.js +296 -0
- package/helpers/deterministicId.js.map +1 -0
- package/package.json +1 -1
- package/types.d.cts +1 -1
- package/types.d.ts +1 -1
- package/version.cjs +1 -1
- package/version.cjs.map +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# inngest
|
|
2
2
|
|
|
3
|
+
## 3.52.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1359](https://github.com/inngest/inngest-js/pull/1359) [`b4d9833f`](https://github.com/inngest/inngest-js/commit/b4d9833fe632f542aad10c6faf5da3fd6a6fc9b7) Thanks [@Linell](https://github.com/Linell)! - fix: use deterministic IDs for correct checkpointed parenting
|
|
8
|
+
|
|
9
|
+
- [#1370](https://github.com/inngest/inngest-js/pull/1370) [`037336dc`](https://github.com/inngest/inngest-js/commit/037336dce8731aa9fcf5d56ff3e2d8a48e5aee6f) Thanks [@amh4r](https://github.com/amh4r)! - Fix mishandling drain message (Connect only)
|
|
10
|
+
|
|
3
11
|
## 3.52.6
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/api/schema.d.cts
CHANGED
|
@@ -7,11 +7,11 @@ declare const errorSchema: z.ZodObject<{
|
|
|
7
7
|
error: z.ZodString;
|
|
8
8
|
status: z.ZodNumber;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
status: number;
|
|
11
10
|
error: string;
|
|
12
|
-
}, {
|
|
13
11
|
status: number;
|
|
12
|
+
}, {
|
|
14
13
|
error: string;
|
|
14
|
+
status: number;
|
|
15
15
|
}>;
|
|
16
16
|
type ErrorResponse = z.infer<typeof errorSchema>;
|
|
17
17
|
declare const stepsSchemas: {
|
package/api/schema.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.cts","names":[],"sources":["../../src/api/schema.ts"],"sourcesContent":[],"mappings":";;;;;cAIa,aAAW,CAAA,CAAA;;EAAX,MAAA,aAGX;CAAA,EAAA,OAAA,cAAA,EAAA;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.cts","names":[],"sources":["../../src/api/schema.ts"],"sourcesContent":[],"mappings":";;;;;cAIa,aAAW,CAAA,CAAA;;EAAX,MAAA,aAGX;CAAA,EAAA,OAAA,cAAA,EAAA;;;;OAHsB,EAAA,MAAA;EAAA,MAAA,EAAA,MAAA;AAIxB,CAAA,CAAA;AAAyB,KAAb,aAAA,GAAgB,CAAA,CAAE,KAAL,CAAA,OAAkB,WAAlB,CAAA;AAAkB,cAsD9B,YAtD8B,EAAA;kBAAb,cAAA,YAAA,YAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA,CAAA,CAAA,CAAA;EAAK,CAAA,cAAA,YAAA,YAAA,YAAA,CAAA,WAAA,CAAA,WAAA,CAAA,YAAA,CAAA;IAsDtB,IAAA,cAIoC,cAAA,aAAA,CAAA,MAAA,CAAA,CAAA,CAAA;IAAA,IAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAErC,IAAA,EAAA,OAAa;EAAA,CAAA,EAAA;IACjB,KAAA,EAAA;MAAmC,KAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAAc,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAA5B,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAC3B,KAAA,CAAA,EAAA,MAAA,GAAA,SAAA;IAAgB,CAAA,GAAA;MAEL,IAAA,EAEZ,MAAA;MAAA,OAAA,EAAA,MAAA;MAFuB,KAAA,CAAA,EAAA,OAAA;IAAA,CAAA;IAAA,IAAA,CAAA,EAAA,OAAA,GAAA,SAAA;KAAA,CAAA,aAAA,CAAA;IAAA,IAAA,cAAA,cAAA,aAAA,CAAA,OAAA,CAAA,CAAA,CAAA;IAAA,KAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA;KAAA,QAAA,cAAA,EAAA;IAAA,IAAA,EAAA,OAAA;IAGZ,KAAA,CAAA,EAAA,GAAA;EAAa,CAAA,EAAA;IAAkB,IAAA,CAAA,EAAA,OAAA,GAAA,SAAA;IAAf,KAAE,CAAA,EAAA,GAAA;EAAK,CAAA,CAAA,CAAA,CAAA,cAAA,SAAA,EAAA;;;;;KAPvB,aAAA,WACJ,mBAAmB,CAAA,CAAE,cAAc,cAAc,MACvD;cAEW,aAAW,CAAA,CAAA,SAAA,CAAA,CAAA,WAAA,CAAA,CAAA,UAAA,CAAA,CAAA,WAAA,CAAA,CAAA,SAAA,mBAAA;KAGZ,aAAA,GAAgB,CAAA,CAAE,aAAa"}
|
package/api/schema.d.ts
CHANGED
|
@@ -7,11 +7,11 @@ declare const errorSchema: z.ZodObject<{
|
|
|
7
7
|
error: z.ZodString;
|
|
8
8
|
status: z.ZodNumber;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
status: number;
|
|
11
10
|
error: string;
|
|
12
|
-
}, {
|
|
13
11
|
status: number;
|
|
12
|
+
}, {
|
|
14
13
|
error: string;
|
|
14
|
+
status: number;
|
|
15
15
|
}>;
|
|
16
16
|
type ErrorResponse = z.infer<typeof errorSchema>;
|
|
17
17
|
declare const stepsSchemas: {
|
package/api/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/api/schema.ts"],"sourcesContent":[],"mappings":";;;;;cAIa,aAAW,CAAA,CAAA;;EAAX,MAAA,aAGX;CAAA,EAAA,OAAA,cAAA,EAAA;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/api/schema.ts"],"sourcesContent":[],"mappings":";;;;;cAIa,aAAW,CAAA,CAAA;;EAAX,MAAA,aAGX;CAAA,EAAA,OAAA,cAAA,EAAA;;;;OAHsB,EAAA,MAAA;EAAA,MAAA,EAAA,MAAA;AAIxB,CAAA,CAAA;AAAyB,KAAb,aAAA,GAAgB,CAAA,CAAE,KAAL,CAAA,OAAkB,WAAlB,CAAA;AAAkB,cAsD9B,YAtD8B,EAAA;kBAAb,cAAA,YAAA,YAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA,CAAA,CAAA,CAAA;EAAK,CAAA,cAAA,YAAA,YAAA,YAAA,CAAA,WAAA,CAAA,WAAA,CAAA,YAAA,CAAA;IAsDtB,IAAA,cAIoC,cAAA,aAAA,CAAA,MAAA,CAAA,CAAA,CAAA;IAAA,IAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAErC,IAAA,EAAA,OAAa;EAAA,CAAA,EAAA;IACjB,KAAA,EAAA;MAAmC,KAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAAc,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAA5B,OAAA,CAAA,EAAA,MAAA,GAAA,SAAA;MAC3B,KAAA,CAAA,EAAA,MAAA,GAAA,SAAA;IAAgB,CAAA,GAAA;MAEL,IAAA,EAEZ,MAAA;MAAA,OAAA,EAAA,MAAA;MAFuB,KAAA,CAAA,EAAA,OAAA;IAAA,CAAA;IAAA,IAAA,CAAA,EAAA,OAAA,GAAA,SAAA;KAAA,CAAA,aAAA,CAAA;IAAA,IAAA,cAAA,cAAA,aAAA,CAAA,OAAA,CAAA,CAAA,CAAA;IAAA,KAAA,cAAA,SAAA,EAAA,GAAA,EAAA,GAAA,CAAA;KAAA,QAAA,cAAA,EAAA;IAAA,IAAA,EAAA,OAAA;IAGZ,KAAA,CAAA,EAAA,GAAA;EAAa,CAAA,EAAA;IAAkB,IAAA,CAAA,EAAA,OAAA,GAAA,SAAA;IAAf,KAAE,CAAA,EAAA,GAAA;EAAK,CAAA,CAAA,CAAA,CAAA,cAAA,SAAA,EAAA;;;;;KAPvB,aAAA,WACJ,mBAAmB,CAAA,CAAE,cAAc,cAAc,MACvD;cAEW,aAAW,CAAA,CAAA,SAAA,CAAA,CAAA,WAAA,CAAA,CAAA,UAAA,CAAA,CAAA,WAAA,CAAA,CAAA,SAAA,mBAAA;KAGZ,aAAA,GAAgB,CAAA,CAAE,aAAa"}
|
|
@@ -55,13 +55,11 @@ var ConnectionCore = class {
|
|
|
55
55
|
*/
|
|
56
56
|
async connect(attempt = 0, path = []) {
|
|
57
57
|
if (typeof WebSocket === "undefined") throw new Error("WebSockets not supported in current environment");
|
|
58
|
-
|
|
59
|
-
if (state === require_types.ConnectionState.CLOSING || state === require_types.ConnectionState.CLOSED) throw new Error("Connection already closed");
|
|
58
|
+
if (this.callbacks.getState() === require_types.ConnectionState.CLOSED) throw new Error("Connection already closed");
|
|
60
59
|
this.callbacks.log("Establishing connection", { attempt });
|
|
61
60
|
let useSigningKey = this.config.hashedSigningKey;
|
|
62
61
|
while (true) {
|
|
63
|
-
|
|
64
|
-
if (currentState === require_types.ConnectionState.CLOSING || currentState === require_types.ConnectionState.CLOSED) break;
|
|
62
|
+
if (this.callbacks.getState() === require_types.ConnectionState.CLOSED) break;
|
|
65
63
|
if (this.callbacks.beforeConnect) await this.callbacks.beforeConnect(useSigningKey);
|
|
66
64
|
try {
|
|
67
65
|
await this.prepareConnection(useSigningKey, attempt, [...path]);
|
|
@@ -79,8 +77,7 @@ var ConnectionCore = class {
|
|
|
79
77
|
const delay = require_util.expBackoff(attempt);
|
|
80
78
|
this.callbacks.log(`Reconnecting in ${delay}ms`);
|
|
81
79
|
if (await require_util.waitWithCancel(delay, () => {
|
|
82
|
-
|
|
83
|
-
return s === require_types.ConnectionState.CLOSING || s === require_types.ConnectionState.CLOSED;
|
|
80
|
+
return this.callbacks.getState() === require_types.ConnectionState.CLOSED;
|
|
84
81
|
})) {
|
|
85
82
|
this.callbacks.log("Reconnect backoff cancelled");
|
|
86
83
|
break;
|
|
@@ -373,11 +370,19 @@ var ConnectionCore = class {
|
|
|
373
370
|
clearInterval(extendLeaseInterval);
|
|
374
371
|
return;
|
|
375
372
|
}
|
|
373
|
+
const leaseWs = this.currentConnection?.ws ?? ws;
|
|
376
374
|
this.callbacks.log("Extending lease", {
|
|
377
375
|
connectionId,
|
|
378
376
|
leaseId: currentLeaseId
|
|
379
377
|
});
|
|
380
|
-
|
|
378
|
+
if (leaseWs.readyState !== WebSocket.OPEN) {
|
|
379
|
+
this.callbacks.log("Cannot extend lease, no open WebSocket available", {
|
|
380
|
+
connectionId,
|
|
381
|
+
requestId: gatewayExecutorRequest.requestId
|
|
382
|
+
});
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
leaseWs.send(require_connect.ConnectMessage.encode(require_connect.ConnectMessage.create({
|
|
381
386
|
kind: require_connect.GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE,
|
|
382
387
|
payload: require_connect.WorkerRequestExtendLeaseData.encode(require_connect.WorkerRequestExtendLeaseData.create({
|
|
383
388
|
accountId: gatewayExecutorRequest.accountId,
|
|
@@ -457,8 +462,9 @@ var ConnectionCore = class {
|
|
|
457
462
|
let heartbeatInterval;
|
|
458
463
|
if (heartbeatIntervalMs !== void 0) heartbeatInterval = setInterval(() => {
|
|
459
464
|
if (heartbeatIntervalMs === void 0) return;
|
|
465
|
+
if (ws.readyState !== WebSocket.OPEN) return;
|
|
460
466
|
if (conn.pendingHeartbeats >= 2) {
|
|
461
|
-
this.callbacks.log("Gateway heartbeat missed");
|
|
467
|
+
this.callbacks.log("Gateway heartbeat missed", { connectionId });
|
|
462
468
|
onConnectionError(new require_util.ReconnectError(`Consecutive gateway heartbeats missed (${connectionId})`, attempt));
|
|
463
469
|
return;
|
|
464
470
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.cjs","names":["WaitGroup","ConnectionState","ReconnectError","AuthError","ConnectionLimitError","expBackoff","waitWithCancel","createStartRequest","headers: Record<string, string>","headerKeys","parseStartResponse","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: unknown) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","workerDisconnectReasonToJSON","WorkerDisconnectReason","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","parseConnectMessage","gatewayMessageTypeToJSON","GatewayMessageType","WorkerConnectRequestData","getPlatformName","allProcessEnv","version","retrieveSystemAttributes","getHostname","ConnectMessage","GatewayConnectionReadyData","conn: Connection","parseGatewayExecutorRequest","WorkerRequestAckData","extendLeaseInterval: NodeJS.Timeout | undefined","WorkerRequestExtendLeaseData","parseWorkerReplyAck","WorkerRequestExtendLeaseAckData","heartbeatInterval: NodeJS.Timeout | undefined","resolveApiBaseUrl"],"sources":["../../../../../src/components/connect/strategies/core/connection.ts"],"sourcesContent":["/**\n * Shared connection core logic used by both SameThreadStrategy and\n * WorkerThreadStrategy.\n *\n * This module extracts the common WebSocket connection management, handshake,\n * heartbeat, lease extension, and reconnection logic.\n */\n\nimport { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport ms from \"ms\";\nimport { headerKeys } from \"../../../../helpers/consts.ts\";\nimport { allProcessEnv, getPlatformName } from \"../../../../helpers/env.ts\";\nimport { resolveApiBaseUrl } from \"../../../../helpers/url.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { version } from \"../../../../version.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"../../messages.ts\";\nimport { getHostname, retrieveSystemAttributes } from \"../../os.ts\";\nimport { ConnectionState } from \"../../types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n ReconnectError,\n waitWithCancel,\n} from \"../../util.ts\";\nimport type { BaseConnectionConfig } from \"./types.ts\";\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\n/**\n * Connection object representing an active WebSocket connection.\n */\nexport interface Connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\n/**\n * Configuration for the connection core.\n * Extends BaseConnectionConfig with connection-specific options.\n */\nexport interface ConnectionCoreConfig extends BaseConnectionConfig {\n instanceId?: string;\n maxWorkerConcurrency?: number;\n rewriteGatewayEndpoint?: (endpoint: string) => string;\n appIds: string[];\n}\n\n/**\n * Callbacks for connection core events.\n */\nexport interface ConnectionCoreCallbacks {\n log: (message: string, data?: unknown) => void;\n onStateChange: (state: ConnectionState) => void;\n getState: () => ConnectionState;\n handleExecutionRequest: (\n request: GatewayExecutorRequestData,\n ) => Promise<Uint8Array>;\n onReplyAck?: (requestId: string) => void;\n onBufferResponse?: (requestId: string, responseBytes: Uint8Array) => void;\n beforeConnect?: (signingKey: string | undefined) => Promise<void>;\n}\n\n/**\n * Core connection manager that handles WebSocket connection lifecycle,\n * handshake, heartbeat, lease extension, and reconnection.\n */\nexport class ConnectionCore {\n private config: ConnectionCoreConfig;\n private callbacks: ConnectionCoreCallbacks;\n\n private currentConnection: Connection | undefined;\n private excludeGateways: Set<string> = new Set();\n\n private inProgressRequests: {\n wg: WaitGroup;\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n constructor(\n config: ConnectionCoreConfig,\n callbacks: ConnectionCoreCallbacks,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n get connection(): Connection | undefined {\n return this.currentConnection;\n }\n\n get connectionId(): string | undefined {\n return this.currentConnection?.id;\n }\n\n /**\n * Wait for all in-progress requests to complete.\n */\n async waitForInProgress(): Promise<void> {\n await this.inProgressRequests.wg.wait();\n }\n\n /**\n * Main connection loop with reconnection logic.\n */\n async connect(attempt = 0, path: string[] = []): Promise<void> {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n const state = this.callbacks.getState();\n if (state === ConnectionState.CLOSING || state === ConnectionState.CLOSED) {\n throw new Error(\"Connection already closed\");\n }\n\n this.callbacks.log(\"Establishing connection\", { attempt });\n\n let useSigningKey = this.config.hashedSigningKey;\n\n while (true) {\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n break;\n }\n\n // Flush any pending messages before attempting connection\n if (this.callbacks.beforeConnect) {\n await this.callbacks.beforeConnect(useSigningKey);\n }\n\n try {\n await this.prepareConnection(useSigningKey, attempt, [...path]);\n return;\n } catch (err) {\n this.callbacks.log(\n \"Failed to connect\",\n err instanceof Error ? err.message : err,\n );\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback =\n useSigningKey === this.config.hashedSigningKey;\n if (switchToFallback) {\n this.callbacks.log(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this.config.hashedFallbackKey\n : this.config.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 }\n\n const delay = expBackoff(attempt);\n this.callbacks.log(`Reconnecting in ${delay}ms`);\n\n const cancelled = await waitWithCancel(delay, () => {\n const s = this.callbacks.getState();\n return s === ConnectionState.CLOSING || s === ConnectionState.CLOSED;\n });\n if (cancelled) {\n this.callbacks.log(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.callbacks.log(\"Exiting connect loop\");\n }\n\n /**\n * Clean up the current connection.\n */\n async cleanup(): Promise<void> {\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\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.config.envName) {\n headers[headerKeys.Environment] = this.config.envName;\n }\n\n const targetUrl = new URL(\"/v0/connect/start\", await this.getApiBaseUrl());\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.config.envName ? ` (env: ${this.config.envName})` : \"\"\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 return startResp;\n }\n\n private async prepareConnection(\n hashedSigningKey: string | undefined,\n attempt: number,\n path: string[] = [],\n ): Promise<Connection> {\n let closed = false;\n\n this.callbacks.log(\"Preparing connection\", { attempt, path });\n\n const startedAt = new Date();\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 let rejectWebsocketConnected: ((reason?: unknown) => void) | undefined;\n const websocketConnectedPromise = new Promise<void>((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.config.rewriteGatewayEndpoint) {\n const rewritten = this.config.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.callbacks.log(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.callbacks.log(\"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 if (closed) {\n this.callbacks.log(\n \"Connection error while initializing but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n this.callbacks.log(\n \"Connection error in connecting state, rejecting promise\",\n { connectionId },\n );\n\n this.excludeGateways.add(startResp.gatewayGroup);\n clearTimeout(connectTimeout);\n\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001,\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 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 const connectMessage = parseConnectMessage(messageBytes);\n\n this.callbacks.log(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n { connectionId },\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.config.envName,\n platform: getPlatformName({ ...allProcessEnv() }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck:\n this.config.connectionData.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: this.config.connectionData.apps,\n capabilities: new TextEncoder().encode(\n this.config.connectionData.marshaledCapabilities,\n ),\n startedAt: startedAt,\n instanceId: this.config.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.config.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 heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue)\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue)\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.callbacks.log(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\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 // Set state to ACTIVE after currentConnection is set, so that\n // connectionId is available in the onStateChange callback.\n this.callbacks.onStateChange(ConnectionState.ACTIVE);\n\n this.callbacks.log(`Connection ready (${connectionId})`);\n\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n if (closed) {\n this.callbacks.log(\n \"Connection error but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.callbacks.onStateChange(ConnectionState.RECONNECTING);\n this.excludeGateways.add(startResp.gatewayGroup);\n\n if (isDraining) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.callbacks.log(\n `Connection error (${connectionId})`,\n error instanceof Error ? error.message : error,\n );\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 const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.callbacks.log(\"Received draining message\", { connectionId });\n try {\n this.callbacks.log(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n await this.connect(0, [...path]);\n await conn.cleanup();\n } catch (err) {\n this.callbacks.log(\n \"Failed to reconnect after receiving draining message\",\n {\n connectionId,\n err: err instanceof Error ? err.message : err,\n },\n );\n\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.callbacks.log(\"Handled gateway heartbeat\", { connectionId });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n const currentState = this.callbacks.getState();\n if (currentState !== ConnectionState.ACTIVE) {\n this.callbacks.log(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.callbacks.log(\"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.callbacks.log(\"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\n if (!this.config.appIds.includes(gatewayExecutorRequest.appName)) {\n this.callbacks.log(\"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 // Send ACK\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 // Start lease extension interval\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n this.callbacks.log(\"Extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\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 leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n try {\n // Handle execution via callback\n const responseBytes = await this.callbacks.handleExecutionRequest(\n gatewayExecutorRequest,\n );\n\n this.callbacks.log(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n if (!this.currentConnection) {\n this.callbacks.log(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n if (this.callbacks.onBufferResponse) {\n this.callbacks.onBufferResponse(\n gatewayExecutorRequest.requestId,\n responseBytes,\n );\n }\n return;\n }\n\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: responseBytes,\n }),\n ).finish(),\n );\n } catch (err) {\n this.callbacks.log(\n `Execution error for request ${gatewayExecutorRequest.requestId}`,\n err instanceof Error ? err.message : err,\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.callbacks.log(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.callbacks.onReplyAck?.(replyAck.requestId);\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.callbacks.log(\"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.callbacks.log(\"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.callbacks.log(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n // Heartbeat interval\n let heartbeatInterval: NodeJS.Timeout | undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n if (conn.pendingHeartbeats >= 2) {\n this.callbacks.log(\"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.callbacks.log(\"Sending worker heartbeat\", { connectionId });\n\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 = async () => {\n if (closed) {\n return;\n }\n closed = true;\n\n this.callbacks.log(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.callbacks.log(\"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.callbacks.log(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n\n await this.inProgressRequests.wg.wait();\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.callbacks.log(\"Cleaning up worker heartbeat\", { connectionId });\n clearInterval(heartbeatInterval);\n };\n\n return conn;\n }\n\n async getApiBaseUrl(): Promise<string> {\n return resolveApiBaseUrl({\n apiBaseUrl: this.config.apiBaseUrl,\n mode: this.config.mode,\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connection.cjs","names":["WaitGroup","ConnectionState","ReconnectError","AuthError","ConnectionLimitError","expBackoff","waitWithCancel","createStartRequest","headers: Record<string, string>","headerKeys","parseStartResponse","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: unknown) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","workerDisconnectReasonToJSON","WorkerDisconnectReason","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","parseConnectMessage","gatewayMessageTypeToJSON","GatewayMessageType","WorkerConnectRequestData","getPlatformName","allProcessEnv","version","retrieveSystemAttributes","getHostname","ConnectMessage","GatewayConnectionReadyData","conn: Connection","parseGatewayExecutorRequest","WorkerRequestAckData","extendLeaseInterval: NodeJS.Timeout | undefined","WorkerRequestExtendLeaseData","parseWorkerReplyAck","WorkerRequestExtendLeaseAckData","heartbeatInterval: NodeJS.Timeout | undefined","resolveApiBaseUrl"],"sources":["../../../../../src/components/connect/strategies/core/connection.ts"],"sourcesContent":["/**\n * Shared connection core logic used by both SameThreadStrategy and\n * WorkerThreadStrategy.\n *\n * This module extracts the common WebSocket connection management, handshake,\n * heartbeat, lease extension, and reconnection logic.\n */\n\nimport { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport ms from \"ms\";\nimport { headerKeys } from \"../../../../helpers/consts.ts\";\nimport { allProcessEnv, getPlatformName } from \"../../../../helpers/env.ts\";\nimport { resolveApiBaseUrl } from \"../../../../helpers/url.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { version } from \"../../../../version.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"../../messages.ts\";\nimport { getHostname, retrieveSystemAttributes } from \"../../os.ts\";\nimport { ConnectionState } from \"../../types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n ReconnectError,\n waitWithCancel,\n} from \"../../util.ts\";\nimport type { BaseConnectionConfig } from \"./types.ts\";\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\n/**\n * Connection object representing an active WebSocket connection.\n */\nexport interface Connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\n/**\n * Configuration for the connection core.\n * Extends BaseConnectionConfig with connection-specific options.\n */\nexport interface ConnectionCoreConfig extends BaseConnectionConfig {\n instanceId?: string;\n maxWorkerConcurrency?: number;\n rewriteGatewayEndpoint?: (endpoint: string) => string;\n appIds: string[];\n}\n\n/**\n * Callbacks for connection core events.\n */\nexport interface ConnectionCoreCallbacks {\n log: (message: string, data?: unknown) => void;\n onStateChange: (state: ConnectionState) => void;\n getState: () => ConnectionState;\n handleExecutionRequest: (\n request: GatewayExecutorRequestData,\n ) => Promise<Uint8Array>;\n onReplyAck?: (requestId: string) => void;\n onBufferResponse?: (requestId: string, responseBytes: Uint8Array) => void;\n beforeConnect?: (signingKey: string | undefined) => Promise<void>;\n}\n\n/**\n * Core connection manager that handles WebSocket connection lifecycle,\n * handshake, heartbeat, lease extension, and reconnection.\n */\nexport class ConnectionCore {\n private config: ConnectionCoreConfig;\n private callbacks: ConnectionCoreCallbacks;\n\n private currentConnection: Connection | undefined;\n private excludeGateways: Set<string> = new Set();\n\n private inProgressRequests: {\n wg: WaitGroup;\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n constructor(\n config: ConnectionCoreConfig,\n callbacks: ConnectionCoreCallbacks,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n get connection(): Connection | undefined {\n return this.currentConnection;\n }\n\n get connectionId(): string | undefined {\n return this.currentConnection?.id;\n }\n\n /**\n * Wait for all in-progress requests to complete.\n */\n async waitForInProgress(): Promise<void> {\n await this.inProgressRequests.wg.wait();\n }\n\n /**\n * Main connection loop with reconnection logic.\n */\n async connect(attempt = 0, path: string[] = []): Promise<void> {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n const state = this.callbacks.getState();\n if (state === ConnectionState.CLOSED) {\n throw new Error(\"Connection already closed\");\n }\n\n this.callbacks.log(\"Establishing connection\", { attempt });\n\n let useSigningKey = this.config.hashedSigningKey;\n\n while (true) {\n const currentState = this.callbacks.getState();\n if (currentState === ConnectionState.CLOSED) {\n break;\n }\n\n // NOTE: We can get here when the state is CLOSING, therefore it's\n // possible to reconnect while the CLOSING. This is intentional so that\n // the worker can reconnect while waiting for pending requests during a\n // graceful shutdown. If we didn't allow reconnect in that case,\n // heartbeats and lease extensions would stop and the Inngest Server would\n // think the worker died.\n //\n // However, the state can be CLOSING during a shutdown without pending\n // requests. The window of that happening is very small, but it's\n // technically possible that we could mistakenly reconnect during a\n // shutdown if the Inngest Server send a drain message.\n\n // Flush any pending messages before attempting connection\n if (this.callbacks.beforeConnect) {\n await this.callbacks.beforeConnect(useSigningKey);\n }\n\n try {\n await this.prepareConnection(useSigningKey, attempt, [...path]);\n return;\n } catch (err) {\n this.callbacks.log(\n \"Failed to connect\",\n err instanceof Error ? err.message : err,\n );\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback =\n useSigningKey === this.config.hashedSigningKey;\n if (switchToFallback) {\n this.callbacks.log(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this.config.hashedFallbackKey\n : this.config.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 }\n\n const delay = expBackoff(attempt);\n this.callbacks.log(`Reconnecting in ${delay}ms`);\n\n const cancelled = await waitWithCancel(delay, () => {\n return this.callbacks.getState() === ConnectionState.CLOSED;\n });\n if (cancelled) {\n this.callbacks.log(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.callbacks.log(\"Exiting connect loop\");\n }\n\n /**\n * Clean up the current connection.\n */\n async cleanup(): Promise<void> {\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\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.config.envName) {\n headers[headerKeys.Environment] = this.config.envName;\n }\n\n const targetUrl = new URL(\"/v0/connect/start\", await this.getApiBaseUrl());\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.config.envName ? ` (env: ${this.config.envName})` : \"\"\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 return startResp;\n }\n\n private async prepareConnection(\n hashedSigningKey: string | undefined,\n attempt: number,\n path: string[] = [],\n ): Promise<Connection> {\n let closed = false;\n\n this.callbacks.log(\"Preparing connection\", { attempt, path });\n\n const startedAt = new Date();\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 let rejectWebsocketConnected: ((reason?: unknown) => void) | undefined;\n const websocketConnectedPromise = new Promise<void>((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.config.rewriteGatewayEndpoint) {\n const rewritten = this.config.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.callbacks.log(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.callbacks.log(\"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 if (closed) {\n this.callbacks.log(\n \"Connection error while initializing but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n this.callbacks.log(\n \"Connection error in connecting state, rejecting promise\",\n { connectionId },\n );\n\n this.excludeGateways.add(startResp.gatewayGroup);\n clearTimeout(connectTimeout);\n\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001,\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 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 const connectMessage = parseConnectMessage(messageBytes);\n\n this.callbacks.log(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n { connectionId },\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.config.envName,\n platform: getPlatformName({ ...allProcessEnv() }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck:\n this.config.connectionData.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: this.config.connectionData.apps,\n capabilities: new TextEncoder().encode(\n this.config.connectionData.marshaledCapabilities,\n ),\n startedAt: startedAt,\n instanceId: this.config.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.config.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 heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue)\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue)\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.callbacks.log(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\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 // Set state to ACTIVE after currentConnection is set, so that\n // connectionId is available in the onStateChange callback.\n this.callbacks.onStateChange(ConnectionState.ACTIVE);\n\n this.callbacks.log(`Connection ready (${connectionId})`);\n\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n if (closed) {\n this.callbacks.log(\n \"Connection error but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.callbacks.onStateChange(ConnectionState.RECONNECTING);\n this.excludeGateways.add(startResp.gatewayGroup);\n\n if (isDraining) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.callbacks.log(\n `Connection error (${connectionId})`,\n error instanceof Error ? error.message : error,\n );\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 const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.callbacks.log(\"Received draining message\", { connectionId });\n try {\n this.callbacks.log(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n await this.connect(0, [...path]);\n await conn.cleanup();\n } catch (err) {\n this.callbacks.log(\n \"Failed to reconnect after receiving draining message\",\n {\n connectionId,\n err: err instanceof Error ? err.message : err,\n },\n );\n\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.callbacks.log(\"Handled gateway heartbeat\", { connectionId });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n const currentState = this.callbacks.getState();\n if (currentState !== ConnectionState.ACTIVE) {\n this.callbacks.log(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.callbacks.log(\"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.callbacks.log(\"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\n if (!this.config.appIds.includes(gatewayExecutorRequest.appName)) {\n this.callbacks.log(\"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 // Send ACK\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 // Start lease extension interval\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n // Use the current live connection's WebSocket for lease\n // extensions. During a drain, the original WebSocket may be\n // closed by the gateway while the request is still in flight,\n // causing lease extension messages to silently fail and the\n // gateway to time out the request.\n const leaseWs = this.currentConnection?.ws ?? ws;\n\n this.callbacks.log(\"Extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\n if (leaseWs.readyState !== WebSocket.OPEN) {\n this.callbacks.log(\n \"Cannot extend lease, no open WebSocket available\",\n {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n },\n );\n return;\n }\n\n leaseWs.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 leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n try {\n // Handle execution via callback\n const responseBytes = await this.callbacks.handleExecutionRequest(\n gatewayExecutorRequest,\n );\n\n this.callbacks.log(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n if (!this.currentConnection) {\n this.callbacks.log(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n if (this.callbacks.onBufferResponse) {\n this.callbacks.onBufferResponse(\n gatewayExecutorRequest.requestId,\n responseBytes,\n );\n }\n return;\n }\n\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: responseBytes,\n }),\n ).finish(),\n );\n } catch (err) {\n this.callbacks.log(\n `Execution error for request ${gatewayExecutorRequest.requestId}`,\n err instanceof Error ? err.message : err,\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.callbacks.log(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.callbacks.onReplyAck?.(replyAck.requestId);\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.callbacks.log(\"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.callbacks.log(\"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.callbacks.log(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n // Heartbeat interval\n let heartbeatInterval: NodeJS.Timeout | undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n // Skip heartbeat ticks when the WebSocket is no longer open. During\n // drain the Gateway may close the old WS while in-flight requests are\n // still running. Sending on a closed socket is a no-op and we must not\n // treat the missing response as a failure.\n //\n // This is safe because each connection gets its own heartbeat\n // interval. Once we reconnect, we can safely skip the old WS\n // heartbeats because the new WS is heartbeating.\n //\n // TODO: We need a better way to handle this. This isn't a horrible\n // hack, but it isn't ideal. Over the life of a worker, it'll have N-1\n // noop heartbeat intervals, where N is the number of times it\n // reconnected.\n if (ws.readyState !== WebSocket.OPEN) {\n return;\n }\n\n if (conn.pendingHeartbeats >= 2) {\n this.callbacks.log(\"Gateway heartbeat missed\", { connectionId });\n void onConnectionError(\n new ReconnectError(\n `Consecutive gateway heartbeats missed (${connectionId})`,\n attempt,\n ),\n );\n return;\n }\n\n this.callbacks.log(\"Sending worker heartbeat\", { connectionId });\n\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 = async () => {\n if (closed) {\n return;\n }\n closed = true;\n\n this.callbacks.log(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.callbacks.log(\"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.callbacks.log(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n\n await this.inProgressRequests.wg.wait();\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.callbacks.log(\"Cleaning up worker heartbeat\", { connectionId });\n clearInterval(heartbeatInterval);\n };\n\n return conn;\n }\n\n async getApiBaseUrl(): Promise<string> {\n return resolveApiBaseUrl({\n apiBaseUrl: this.config.apiBaseUrl,\n mode: this.config.mode,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -53,13 +53,11 @@ var ConnectionCore = class {
|
|
|
53
53
|
*/
|
|
54
54
|
async connect(attempt = 0, path = []) {
|
|
55
55
|
if (typeof WebSocket === "undefined") throw new Error("WebSockets not supported in current environment");
|
|
56
|
-
|
|
57
|
-
if (state === ConnectionState.CLOSING || state === ConnectionState.CLOSED) throw new Error("Connection already closed");
|
|
56
|
+
if (this.callbacks.getState() === ConnectionState.CLOSED) throw new Error("Connection already closed");
|
|
58
57
|
this.callbacks.log("Establishing connection", { attempt });
|
|
59
58
|
let useSigningKey = this.config.hashedSigningKey;
|
|
60
59
|
while (true) {
|
|
61
|
-
|
|
62
|
-
if (currentState === ConnectionState.CLOSING || currentState === ConnectionState.CLOSED) break;
|
|
60
|
+
if (this.callbacks.getState() === ConnectionState.CLOSED) break;
|
|
63
61
|
if (this.callbacks.beforeConnect) await this.callbacks.beforeConnect(useSigningKey);
|
|
64
62
|
try {
|
|
65
63
|
await this.prepareConnection(useSigningKey, attempt, [...path]);
|
|
@@ -77,8 +75,7 @@ var ConnectionCore = class {
|
|
|
77
75
|
const delay = expBackoff(attempt);
|
|
78
76
|
this.callbacks.log(`Reconnecting in ${delay}ms`);
|
|
79
77
|
if (await waitWithCancel(delay, () => {
|
|
80
|
-
|
|
81
|
-
return s === ConnectionState.CLOSING || s === ConnectionState.CLOSED;
|
|
78
|
+
return this.callbacks.getState() === ConnectionState.CLOSED;
|
|
82
79
|
})) {
|
|
83
80
|
this.callbacks.log("Reconnect backoff cancelled");
|
|
84
81
|
break;
|
|
@@ -371,11 +368,19 @@ var ConnectionCore = class {
|
|
|
371
368
|
clearInterval(extendLeaseInterval);
|
|
372
369
|
return;
|
|
373
370
|
}
|
|
371
|
+
const leaseWs = this.currentConnection?.ws ?? ws;
|
|
374
372
|
this.callbacks.log("Extending lease", {
|
|
375
373
|
connectionId,
|
|
376
374
|
leaseId: currentLeaseId
|
|
377
375
|
});
|
|
378
|
-
|
|
376
|
+
if (leaseWs.readyState !== WebSocket.OPEN) {
|
|
377
|
+
this.callbacks.log("Cannot extend lease, no open WebSocket available", {
|
|
378
|
+
connectionId,
|
|
379
|
+
requestId: gatewayExecutorRequest.requestId
|
|
380
|
+
});
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
leaseWs.send(ConnectMessage.encode(ConnectMessage.create({
|
|
379
384
|
kind: GatewayMessageType.WORKER_REQUEST_EXTEND_LEASE,
|
|
380
385
|
payload: WorkerRequestExtendLeaseData.encode(WorkerRequestExtendLeaseData.create({
|
|
381
386
|
accountId: gatewayExecutorRequest.accountId,
|
|
@@ -455,8 +460,9 @@ var ConnectionCore = class {
|
|
|
455
460
|
let heartbeatInterval;
|
|
456
461
|
if (heartbeatIntervalMs !== void 0) heartbeatInterval = setInterval(() => {
|
|
457
462
|
if (heartbeatIntervalMs === void 0) return;
|
|
463
|
+
if (ws.readyState !== WebSocket.OPEN) return;
|
|
458
464
|
if (conn.pendingHeartbeats >= 2) {
|
|
459
|
-
this.callbacks.log("Gateway heartbeat missed");
|
|
465
|
+
this.callbacks.log("Gateway heartbeat missed", { connectionId });
|
|
460
466
|
onConnectionError(new ReconnectError(`Consecutive gateway heartbeats missed (${connectionId})`, attempt));
|
|
461
467
|
return;
|
|
462
468
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","names":["headers: Record<string, string>","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: unknown) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","conn: Connection","extendLeaseInterval: NodeJS.Timeout | undefined","heartbeatInterval: NodeJS.Timeout | undefined"],"sources":["../../../../../src/components/connect/strategies/core/connection.ts"],"sourcesContent":["/**\n * Shared connection core logic used by both SameThreadStrategy and\n * WorkerThreadStrategy.\n *\n * This module extracts the common WebSocket connection management, handshake,\n * heartbeat, lease extension, and reconnection logic.\n */\n\nimport { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport ms from \"ms\";\nimport { headerKeys } from \"../../../../helpers/consts.ts\";\nimport { allProcessEnv, getPlatformName } from \"../../../../helpers/env.ts\";\nimport { resolveApiBaseUrl } from \"../../../../helpers/url.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { version } from \"../../../../version.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"../../messages.ts\";\nimport { getHostname, retrieveSystemAttributes } from \"../../os.ts\";\nimport { ConnectionState } from \"../../types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n ReconnectError,\n waitWithCancel,\n} from \"../../util.ts\";\nimport type { BaseConnectionConfig } from \"./types.ts\";\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\n/**\n * Connection object representing an active WebSocket connection.\n */\nexport interface Connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\n/**\n * Configuration for the connection core.\n * Extends BaseConnectionConfig with connection-specific options.\n */\nexport interface ConnectionCoreConfig extends BaseConnectionConfig {\n instanceId?: string;\n maxWorkerConcurrency?: number;\n rewriteGatewayEndpoint?: (endpoint: string) => string;\n appIds: string[];\n}\n\n/**\n * Callbacks for connection core events.\n */\nexport interface ConnectionCoreCallbacks {\n log: (message: string, data?: unknown) => void;\n onStateChange: (state: ConnectionState) => void;\n getState: () => ConnectionState;\n handleExecutionRequest: (\n request: GatewayExecutorRequestData,\n ) => Promise<Uint8Array>;\n onReplyAck?: (requestId: string) => void;\n onBufferResponse?: (requestId: string, responseBytes: Uint8Array) => void;\n beforeConnect?: (signingKey: string | undefined) => Promise<void>;\n}\n\n/**\n * Core connection manager that handles WebSocket connection lifecycle,\n * handshake, heartbeat, lease extension, and reconnection.\n */\nexport class ConnectionCore {\n private config: ConnectionCoreConfig;\n private callbacks: ConnectionCoreCallbacks;\n\n private currentConnection: Connection | undefined;\n private excludeGateways: Set<string> = new Set();\n\n private inProgressRequests: {\n wg: WaitGroup;\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n constructor(\n config: ConnectionCoreConfig,\n callbacks: ConnectionCoreCallbacks,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n get connection(): Connection | undefined {\n return this.currentConnection;\n }\n\n get connectionId(): string | undefined {\n return this.currentConnection?.id;\n }\n\n /**\n * Wait for all in-progress requests to complete.\n */\n async waitForInProgress(): Promise<void> {\n await this.inProgressRequests.wg.wait();\n }\n\n /**\n * Main connection loop with reconnection logic.\n */\n async connect(attempt = 0, path: string[] = []): Promise<void> {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n const state = this.callbacks.getState();\n if (state === ConnectionState.CLOSING || state === ConnectionState.CLOSED) {\n throw new Error(\"Connection already closed\");\n }\n\n this.callbacks.log(\"Establishing connection\", { attempt });\n\n let useSigningKey = this.config.hashedSigningKey;\n\n while (true) {\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n break;\n }\n\n // Flush any pending messages before attempting connection\n if (this.callbacks.beforeConnect) {\n await this.callbacks.beforeConnect(useSigningKey);\n }\n\n try {\n await this.prepareConnection(useSigningKey, attempt, [...path]);\n return;\n } catch (err) {\n this.callbacks.log(\n \"Failed to connect\",\n err instanceof Error ? err.message : err,\n );\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback =\n useSigningKey === this.config.hashedSigningKey;\n if (switchToFallback) {\n this.callbacks.log(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this.config.hashedFallbackKey\n : this.config.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 }\n\n const delay = expBackoff(attempt);\n this.callbacks.log(`Reconnecting in ${delay}ms`);\n\n const cancelled = await waitWithCancel(delay, () => {\n const s = this.callbacks.getState();\n return s === ConnectionState.CLOSING || s === ConnectionState.CLOSED;\n });\n if (cancelled) {\n this.callbacks.log(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.callbacks.log(\"Exiting connect loop\");\n }\n\n /**\n * Clean up the current connection.\n */\n async cleanup(): Promise<void> {\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\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.config.envName) {\n headers[headerKeys.Environment] = this.config.envName;\n }\n\n const targetUrl = new URL(\"/v0/connect/start\", await this.getApiBaseUrl());\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.config.envName ? ` (env: ${this.config.envName})` : \"\"\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 return startResp;\n }\n\n private async prepareConnection(\n hashedSigningKey: string | undefined,\n attempt: number,\n path: string[] = [],\n ): Promise<Connection> {\n let closed = false;\n\n this.callbacks.log(\"Preparing connection\", { attempt, path });\n\n const startedAt = new Date();\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 let rejectWebsocketConnected: ((reason?: unknown) => void) | undefined;\n const websocketConnectedPromise = new Promise<void>((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.config.rewriteGatewayEndpoint) {\n const rewritten = this.config.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.callbacks.log(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.callbacks.log(\"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 if (closed) {\n this.callbacks.log(\n \"Connection error while initializing but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n this.callbacks.log(\n \"Connection error in connecting state, rejecting promise\",\n { connectionId },\n );\n\n this.excludeGateways.add(startResp.gatewayGroup);\n clearTimeout(connectTimeout);\n\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001,\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 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 const connectMessage = parseConnectMessage(messageBytes);\n\n this.callbacks.log(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n { connectionId },\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.config.envName,\n platform: getPlatformName({ ...allProcessEnv() }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck:\n this.config.connectionData.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: this.config.connectionData.apps,\n capabilities: new TextEncoder().encode(\n this.config.connectionData.marshaledCapabilities,\n ),\n startedAt: startedAt,\n instanceId: this.config.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.config.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 heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue)\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue)\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.callbacks.log(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\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 // Set state to ACTIVE after currentConnection is set, so that\n // connectionId is available in the onStateChange callback.\n this.callbacks.onStateChange(ConnectionState.ACTIVE);\n\n this.callbacks.log(`Connection ready (${connectionId})`);\n\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n if (closed) {\n this.callbacks.log(\n \"Connection error but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.callbacks.onStateChange(ConnectionState.RECONNECTING);\n this.excludeGateways.add(startResp.gatewayGroup);\n\n if (isDraining) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.callbacks.log(\n `Connection error (${connectionId})`,\n error instanceof Error ? error.message : error,\n );\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 const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.callbacks.log(\"Received draining message\", { connectionId });\n try {\n this.callbacks.log(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n await this.connect(0, [...path]);\n await conn.cleanup();\n } catch (err) {\n this.callbacks.log(\n \"Failed to reconnect after receiving draining message\",\n {\n connectionId,\n err: err instanceof Error ? err.message : err,\n },\n );\n\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.callbacks.log(\"Handled gateway heartbeat\", { connectionId });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n const currentState = this.callbacks.getState();\n if (currentState !== ConnectionState.ACTIVE) {\n this.callbacks.log(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.callbacks.log(\"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.callbacks.log(\"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\n if (!this.config.appIds.includes(gatewayExecutorRequest.appName)) {\n this.callbacks.log(\"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 // Send ACK\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 // Start lease extension interval\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n this.callbacks.log(\"Extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\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 leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n try {\n // Handle execution via callback\n const responseBytes = await this.callbacks.handleExecutionRequest(\n gatewayExecutorRequest,\n );\n\n this.callbacks.log(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n if (!this.currentConnection) {\n this.callbacks.log(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n if (this.callbacks.onBufferResponse) {\n this.callbacks.onBufferResponse(\n gatewayExecutorRequest.requestId,\n responseBytes,\n );\n }\n return;\n }\n\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: responseBytes,\n }),\n ).finish(),\n );\n } catch (err) {\n this.callbacks.log(\n `Execution error for request ${gatewayExecutorRequest.requestId}`,\n err instanceof Error ? err.message : err,\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.callbacks.log(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.callbacks.onReplyAck?.(replyAck.requestId);\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.callbacks.log(\"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.callbacks.log(\"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.callbacks.log(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n // Heartbeat interval\n let heartbeatInterval: NodeJS.Timeout | undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n if (conn.pendingHeartbeats >= 2) {\n this.callbacks.log(\"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.callbacks.log(\"Sending worker heartbeat\", { connectionId });\n\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 = async () => {\n if (closed) {\n return;\n }\n closed = true;\n\n this.callbacks.log(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.callbacks.log(\"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.callbacks.log(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n\n await this.inProgressRequests.wg.wait();\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.callbacks.log(\"Cleaning up worker heartbeat\", { connectionId });\n clearInterval(heartbeatInterval);\n };\n\n return conn;\n }\n\n async getApiBaseUrl(): Promise<string> {\n return resolveApiBaseUrl({\n apiBaseUrl: this.config.apiBaseUrl,\n mode: this.config.mode,\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connection.js","names":["headers: Record<string, string>","resolveWebsocketConnected:\n | ((value: void | PromiseLike<void>) => void)\n | undefined","rejectWebsocketConnected: ((reason?: unknown) => void) | undefined","onConnectionError: (error: unknown) => void | Promise<void>","heartbeatIntervalMs: number | undefined","extendLeaseIntervalMs: number | undefined","conn: Connection","extendLeaseInterval: NodeJS.Timeout | undefined","heartbeatInterval: NodeJS.Timeout | undefined"],"sources":["../../../../../src/components/connect/strategies/core/connection.ts"],"sourcesContent":["/**\n * Shared connection core logic used by both SameThreadStrategy and\n * WorkerThreadStrategy.\n *\n * This module extracts the common WebSocket connection management, handshake,\n * heartbeat, lease extension, and reconnection logic.\n */\n\nimport { WaitGroup } from \"@jpwilliams/waitgroup\";\nimport ms from \"ms\";\nimport { headerKeys } from \"../../../../helpers/consts.ts\";\nimport { allProcessEnv, getPlatformName } from \"../../../../helpers/env.ts\";\nimport { resolveApiBaseUrl } from \"../../../../helpers/url.ts\";\nimport {\n ConnectMessage,\n GatewayConnectionReadyData,\n type GatewayExecutorRequestData,\n GatewayMessageType,\n gatewayMessageTypeToJSON,\n WorkerConnectRequestData,\n WorkerDisconnectReason,\n WorkerRequestAckData,\n WorkerRequestExtendLeaseAckData,\n WorkerRequestExtendLeaseData,\n workerDisconnectReasonToJSON,\n} from \"../../../../proto/src/components/connect/protobuf/connect.ts\";\nimport { version } from \"../../../../version.ts\";\nimport {\n createStartRequest,\n parseConnectMessage,\n parseGatewayExecutorRequest,\n parseStartResponse,\n parseWorkerReplyAck,\n} from \"../../messages.ts\";\nimport { getHostname, retrieveSystemAttributes } from \"../../os.ts\";\nimport { ConnectionState } from \"../../types.ts\";\nimport {\n AuthError,\n ConnectionLimitError,\n expBackoff,\n ReconnectError,\n waitWithCancel,\n} from \"../../util.ts\";\nimport type { BaseConnectionConfig } from \"./types.ts\";\n\nconst ConnectWebSocketProtocol = \"v0.connect.inngest.com\";\n\n/**\n * Connection object representing an active WebSocket connection.\n */\nexport interface Connection {\n id: string;\n ws: WebSocket;\n cleanup: () => void | Promise<void>;\n pendingHeartbeats: number;\n}\n\n/**\n * Configuration for the connection core.\n * Extends BaseConnectionConfig with connection-specific options.\n */\nexport interface ConnectionCoreConfig extends BaseConnectionConfig {\n instanceId?: string;\n maxWorkerConcurrency?: number;\n rewriteGatewayEndpoint?: (endpoint: string) => string;\n appIds: string[];\n}\n\n/**\n * Callbacks for connection core events.\n */\nexport interface ConnectionCoreCallbacks {\n log: (message: string, data?: unknown) => void;\n onStateChange: (state: ConnectionState) => void;\n getState: () => ConnectionState;\n handleExecutionRequest: (\n request: GatewayExecutorRequestData,\n ) => Promise<Uint8Array>;\n onReplyAck?: (requestId: string) => void;\n onBufferResponse?: (requestId: string, responseBytes: Uint8Array) => void;\n beforeConnect?: (signingKey: string | undefined) => Promise<void>;\n}\n\n/**\n * Core connection manager that handles WebSocket connection lifecycle,\n * handshake, heartbeat, lease extension, and reconnection.\n */\nexport class ConnectionCore {\n private config: ConnectionCoreConfig;\n private callbacks: ConnectionCoreCallbacks;\n\n private currentConnection: Connection | undefined;\n private excludeGateways: Set<string> = new Set();\n\n private inProgressRequests: {\n wg: WaitGroup;\n requestLeases: Record<string, string>;\n } = {\n wg: new WaitGroup(),\n requestLeases: {},\n };\n\n constructor(\n config: ConnectionCoreConfig,\n callbacks: ConnectionCoreCallbacks,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n get connection(): Connection | undefined {\n return this.currentConnection;\n }\n\n get connectionId(): string | undefined {\n return this.currentConnection?.id;\n }\n\n /**\n * Wait for all in-progress requests to complete.\n */\n async waitForInProgress(): Promise<void> {\n await this.inProgressRequests.wg.wait();\n }\n\n /**\n * Main connection loop with reconnection logic.\n */\n async connect(attempt = 0, path: string[] = []): Promise<void> {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\"WebSockets not supported in current environment\");\n }\n\n const state = this.callbacks.getState();\n if (state === ConnectionState.CLOSED) {\n throw new Error(\"Connection already closed\");\n }\n\n this.callbacks.log(\"Establishing connection\", { attempt });\n\n let useSigningKey = this.config.hashedSigningKey;\n\n while (true) {\n const currentState = this.callbacks.getState();\n if (currentState === ConnectionState.CLOSED) {\n break;\n }\n\n // NOTE: We can get here when the state is CLOSING, therefore it's\n // possible to reconnect while the CLOSING. This is intentional so that\n // the worker can reconnect while waiting for pending requests during a\n // graceful shutdown. If we didn't allow reconnect in that case,\n // heartbeats and lease extensions would stop and the Inngest Server would\n // think the worker died.\n //\n // However, the state can be CLOSING during a shutdown without pending\n // requests. The window of that happening is very small, but it's\n // technically possible that we could mistakenly reconnect during a\n // shutdown if the Inngest Server send a drain message.\n\n // Flush any pending messages before attempting connection\n if (this.callbacks.beforeConnect) {\n await this.callbacks.beforeConnect(useSigningKey);\n }\n\n try {\n await this.prepareConnection(useSigningKey, attempt, [...path]);\n return;\n } catch (err) {\n this.callbacks.log(\n \"Failed to connect\",\n err instanceof Error ? err.message : err,\n );\n\n if (!(err instanceof ReconnectError)) {\n throw err;\n }\n\n attempt = err.attempt;\n\n if (err instanceof AuthError) {\n const switchToFallback =\n useSigningKey === this.config.hashedSigningKey;\n if (switchToFallback) {\n this.callbacks.log(\"Switching to fallback signing key\");\n }\n useSigningKey = switchToFallback\n ? this.config.hashedFallbackKey\n : this.config.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 }\n\n const delay = expBackoff(attempt);\n this.callbacks.log(`Reconnecting in ${delay}ms`);\n\n const cancelled = await waitWithCancel(delay, () => {\n return this.callbacks.getState() === ConnectionState.CLOSED;\n });\n if (cancelled) {\n this.callbacks.log(\"Reconnect backoff cancelled\");\n break;\n }\n\n attempt++;\n }\n }\n\n this.callbacks.log(\"Exiting connect loop\");\n }\n\n /**\n * Clean up the current connection.\n */\n async cleanup(): Promise<void> {\n if (this.currentConnection) {\n await this.currentConnection.cleanup();\n this.currentConnection = undefined;\n }\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.config.envName) {\n headers[headerKeys.Environment] = this.config.envName;\n }\n\n const targetUrl = new URL(\"/v0/connect/start\", await this.getApiBaseUrl());\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.config.envName ? ` (env: ${this.config.envName})` : \"\"\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 return startResp;\n }\n\n private async prepareConnection(\n hashedSigningKey: string | undefined,\n attempt: number,\n path: string[] = [],\n ): Promise<Connection> {\n let closed = false;\n\n this.callbacks.log(\"Preparing connection\", { attempt, path });\n\n const startedAt = new Date();\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 let rejectWebsocketConnected: ((reason?: unknown) => void) | undefined;\n const websocketConnectedPromise = new Promise<void>((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.config.rewriteGatewayEndpoint) {\n const rewritten = this.config.rewriteGatewayEndpoint(\n startResp.gatewayEndpoint,\n );\n this.callbacks.log(\"Rewriting gateway endpoint\", {\n original: startResp.gatewayEndpoint,\n rewritten,\n });\n finalEndpoint = rewritten;\n }\n\n this.callbacks.log(\"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 if (closed) {\n this.callbacks.log(\n \"Connection error while initializing but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n this.callbacks.log(\n \"Connection error in connecting state, rejecting promise\",\n { connectionId },\n );\n\n this.excludeGateways.add(startResp.gatewayGroup);\n clearTimeout(connectTimeout);\n\n ws.onerror = () => {};\n ws.onclose = () => {};\n ws.close(\n 4001,\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 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 const connectMessage = parseConnectMessage(messageBytes);\n\n this.callbacks.log(\n `Received message: ${gatewayMessageTypeToJSON(connectMessage.kind)}`,\n { connectionId },\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.config.envName,\n platform: getPlatformName({ ...allProcessEnv() }),\n sdkVersion: `v${version}`,\n sdkLanguage: \"typescript\",\n framework: \"connect\",\n workerManualReadinessAck:\n this.config.connectionData.manualReadinessAck,\n systemAttributes: await retrieveSystemAttributes(),\n authData: {\n sessionToken: startResp.sessionToken,\n syncToken: startResp.syncToken,\n },\n apps: this.config.connectionData.apps,\n capabilities: new TextEncoder().encode(\n this.config.connectionData.marshaledCapabilities,\n ),\n startedAt: startedAt,\n instanceId: this.config.instanceId || (await getHostname()),\n maxWorkerConcurrency: this.config.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 heartbeatIntervalMs =\n readyPayload.heartbeatInterval.length > 0\n ? ms(readyPayload.heartbeatInterval as ms.StringValue)\n : 10_000;\n extendLeaseIntervalMs =\n readyPayload.extendLeaseInterval.length > 0\n ? ms(readyPayload.extendLeaseInterval as ms.StringValue)\n : 5_000;\n\n resolveWebsocketConnected?.();\n return;\n }\n\n this.callbacks.log(\"Unexpected message type during setup\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n await websocketConnectedPromise;\n\n clearTimeout(connectTimeout);\n\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 // Set state to ACTIVE after currentConnection is set, so that\n // connectionId is available in the onStateChange callback.\n this.callbacks.onStateChange(ConnectionState.ACTIVE);\n\n this.callbacks.log(`Connection ready (${connectionId})`);\n\n let isDraining = false;\n {\n onConnectionError = async (error: unknown) => {\n if (closed) {\n this.callbacks.log(\n \"Connection error but already in closed state, skipping\",\n { connectionId },\n );\n return;\n }\n closed = true;\n\n await conn.cleanup();\n\n const currentState = this.callbacks.getState();\n if (\n currentState === ConnectionState.CLOSING ||\n currentState === ConnectionState.CLOSED\n ) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already closing or closed, skipping`,\n );\n return;\n }\n\n this.callbacks.onStateChange(ConnectionState.RECONNECTING);\n this.excludeGateways.add(startResp.gatewayGroup);\n\n if (isDraining) {\n this.callbacks.log(\n `Connection error (${connectionId}) but already draining, skipping`,\n );\n return;\n }\n\n this.callbacks.log(\n `Connection error (${connectionId})`,\n error instanceof Error ? error.message : error,\n );\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 const connectMessage = parseConnectMessage(messageBytes);\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_CLOSING) {\n isDraining = true;\n this.callbacks.log(\"Received draining message\", { connectionId });\n try {\n this.callbacks.log(\n \"Setting up new connection while keeping previous connection open\",\n { connectionId },\n );\n\n await this.connect(0, [...path]);\n await conn.cleanup();\n } catch (err) {\n this.callbacks.log(\n \"Failed to reconnect after receiving draining message\",\n {\n connectionId,\n err: err instanceof Error ? err.message : err,\n },\n );\n\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.callbacks.log(\"Handled gateway heartbeat\", { connectionId });\n return;\n }\n\n if (connectMessage.kind === GatewayMessageType.GATEWAY_EXECUTOR_REQUEST) {\n const currentState = this.callbacks.getState();\n if (currentState !== ConnectionState.ACTIVE) {\n this.callbacks.log(\"Received request while not active, skipping\", {\n connectionId,\n });\n return;\n }\n\n const gatewayExecutorRequest = parseGatewayExecutorRequest(\n connectMessage.payload,\n );\n\n this.callbacks.log(\"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.callbacks.log(\"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\n if (!this.config.appIds.includes(gatewayExecutorRequest.appName)) {\n this.callbacks.log(\"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 // Send ACK\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 // Start lease extension interval\n let extendLeaseInterval: NodeJS.Timeout | undefined;\n extendLeaseInterval = setInterval(() => {\n if (extendLeaseIntervalMs === undefined) {\n return;\n }\n\n const currentLeaseId =\n this.inProgressRequests.requestLeases[\n gatewayExecutorRequest.requestId\n ];\n if (!currentLeaseId) {\n clearInterval(extendLeaseInterval);\n return;\n }\n\n // Use the current live connection's WebSocket for lease\n // extensions. During a drain, the original WebSocket may be\n // closed by the gateway while the request is still in flight,\n // causing lease extension messages to silently fail and the\n // gateway to time out the request.\n const leaseWs = this.currentConnection?.ws ?? ws;\n\n this.callbacks.log(\"Extending lease\", {\n connectionId,\n leaseId: currentLeaseId,\n });\n\n if (leaseWs.readyState !== WebSocket.OPEN) {\n this.callbacks.log(\n \"Cannot extend lease, no open WebSocket available\",\n {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n },\n );\n return;\n }\n\n leaseWs.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 leaseId: currentLeaseId,\n }),\n ).finish(),\n }),\n ).finish(),\n );\n }, extendLeaseIntervalMs);\n\n try {\n // Handle execution via callback\n const responseBytes = await this.callbacks.handleExecutionRequest(\n gatewayExecutorRequest,\n );\n\n this.callbacks.log(\"Sending worker reply\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n\n if (!this.currentConnection) {\n this.callbacks.log(\"No current WebSocket, buffering response\", {\n connectionId,\n requestId: gatewayExecutorRequest.requestId,\n });\n if (this.callbacks.onBufferResponse) {\n this.callbacks.onBufferResponse(\n gatewayExecutorRequest.requestId,\n responseBytes,\n );\n }\n return;\n }\n\n this.currentConnection.ws.send(\n ConnectMessage.encode(\n ConnectMessage.create({\n kind: GatewayMessageType.WORKER_REPLY,\n payload: responseBytes,\n }),\n ).finish(),\n );\n } catch (err) {\n this.callbacks.log(\n `Execution error for request ${gatewayExecutorRequest.requestId}`,\n err instanceof Error ? err.message : err,\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.callbacks.log(\"Acknowledging reply ack\", {\n connectionId,\n requestId: replyAck.requestId,\n });\n\n this.callbacks.onReplyAck?.(replyAck.requestId);\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.callbacks.log(\"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.callbacks.log(\"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.callbacks.log(\"Unexpected message type\", {\n kind: gatewayMessageTypeToJSON(connectMessage.kind),\n rawKind: connectMessage.kind,\n attempt,\n setupState,\n state: this.callbacks.getState(),\n connectionId,\n });\n };\n\n // Heartbeat interval\n let heartbeatInterval: NodeJS.Timeout | undefined;\n if (heartbeatIntervalMs !== undefined) {\n heartbeatInterval = setInterval(() => {\n if (heartbeatIntervalMs === undefined) {\n return;\n }\n\n // Skip heartbeat ticks when the WebSocket is no longer open. During\n // drain the Gateway may close the old WS while in-flight requests are\n // still running. Sending on a closed socket is a no-op and we must not\n // treat the missing response as a failure.\n //\n // This is safe because each connection gets its own heartbeat\n // interval. Once we reconnect, we can safely skip the old WS\n // heartbeats because the new WS is heartbeating.\n //\n // TODO: We need a better way to handle this. This isn't a horrible\n // hack, but it isn't ideal. Over the life of a worker, it'll have N-1\n // noop heartbeat intervals, where N is the number of times it\n // reconnected.\n if (ws.readyState !== WebSocket.OPEN) {\n return;\n }\n\n if (conn.pendingHeartbeats >= 2) {\n this.callbacks.log(\"Gateway heartbeat missed\", { connectionId });\n void onConnectionError(\n new ReconnectError(\n `Consecutive gateway heartbeats missed (${connectionId})`,\n attempt,\n ),\n );\n return;\n }\n\n this.callbacks.log(\"Sending worker heartbeat\", { connectionId });\n\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 = async () => {\n if (closed) {\n return;\n }\n closed = true;\n\n this.callbacks.log(\"Cleaning up connection\", { connectionId });\n if (ws.readyState === WebSocket.OPEN) {\n this.callbacks.log(\"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.callbacks.log(\"Closing connection\", { connectionId });\n ws.onerror = () => {};\n ws.onclose = () => {};\n\n await this.inProgressRequests.wg.wait();\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.callbacks.log(\"Cleaning up worker heartbeat\", { connectionId });\n clearInterval(heartbeatInterval);\n };\n\n return conn;\n }\n\n async getApiBaseUrl(): Promise<string> {\n return resolveApiBaseUrl({\n apiBaseUrl: this.config.apiBaseUrl,\n mode: this.config.mode,\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ let Attribute = /* @__PURE__ */ function(Attribute$1) {
|
|
|
14
14
|
Attribute$1["InngestAppId1"] = "sdk.app.id";
|
|
15
15
|
Attribute$1["InngestAppId2"] = "sys.app.id";
|
|
16
16
|
Attribute$1["InngestFunctionId"] = "sys.function.id";
|
|
17
|
+
Attribute$1["InngestStepParentSpanId"] = "inngest.step.parentSpanId";
|
|
17
18
|
return Attribute$1;
|
|
18
19
|
}({});
|
|
19
20
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.cjs","names":[],"sources":["../../../../src/components/execution/otel/consts.ts"],"sourcesContent":["export const debugPrefix = \"inngest:otel\";\n\nexport enum TraceStateKey {\n AppId = \"inngest@app\",\n FunctionId = \"inngest@fn\",\n TraceRef = \"inngest@traceref\",\n}\n\nexport enum Attribute {\n InngestTraceparent = \"inngest.traceparent\",\n InngestTraceRef = \"inngest.traceref\",\n InngestRunId = \"sdk.run.id\",\n InngestAppId1 = \"sdk.app.id\",\n InngestAppId2 = \"sys.app.id\",\n InngestFunctionId = \"sys.function.id\",\n}\n"],"mappings":";;AAAA,MAAa,cAAc;AAE3B,IAAY,0DAAL;AACL;AACA;AACA;;;AAGF,IAAY,kDAAL;AACL;AACA;AACA;AACA;AACA;AACA"}
|
|
1
|
+
{"version":3,"file":"consts.cjs","names":[],"sources":["../../../../src/components/execution/otel/consts.ts"],"sourcesContent":["export const debugPrefix = \"inngest:otel\";\n\nexport enum TraceStateKey {\n AppId = \"inngest@app\",\n FunctionId = \"inngest@fn\",\n TraceRef = \"inngest@traceref\",\n}\n\nexport enum Attribute {\n InngestTraceparent = \"inngest.traceparent\",\n InngestTraceRef = \"inngest.traceref\",\n InngestRunId = \"sdk.run.id\",\n InngestAppId1 = \"sdk.app.id\",\n InngestAppId2 = \"sys.app.id\",\n InngestFunctionId = \"sys.function.id\",\n InngestStepParentSpanId = \"inngest.step.parentSpanId\",\n}\n"],"mappings":";;AAAA,MAAa,cAAc;AAE3B,IAAY,0DAAL;AACL;AACA;AACA;;;AAGF,IAAY,kDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA"}
|
|
@@ -13,6 +13,7 @@ let Attribute = /* @__PURE__ */ function(Attribute$1) {
|
|
|
13
13
|
Attribute$1["InngestAppId1"] = "sdk.app.id";
|
|
14
14
|
Attribute$1["InngestAppId2"] = "sys.app.id";
|
|
15
15
|
Attribute$1["InngestFunctionId"] = "sys.function.id";
|
|
16
|
+
Attribute$1["InngestStepParentSpanId"] = "inngest.step.parentSpanId";
|
|
16
17
|
return Attribute$1;
|
|
17
18
|
}({});
|
|
18
19
|
|