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.
Files changed (46) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/api/schema.d.cts +2 -2
  3. package/api/schema.d.cts.map +1 -1
  4. package/api/schema.d.ts +2 -2
  5. package/api/schema.d.ts.map +1 -1
  6. package/components/connect/strategies/core/connection.cjs +14 -8
  7. package/components/connect/strategies/core/connection.cjs.map +1 -1
  8. package/components/connect/strategies/core/connection.js +14 -8
  9. package/components/connect/strategies/core/connection.js.map +1 -1
  10. package/components/execution/otel/consts.cjs +1 -0
  11. package/components/execution/otel/consts.cjs.map +1 -1
  12. package/components/execution/otel/consts.js +1 -0
  13. package/components/execution/otel/consts.js.map +1 -1
  14. package/components/execution/otel/processor.cjs +56 -5
  15. package/components/execution/otel/processor.cjs.map +1 -1
  16. package/components/execution/otel/processor.d.cts +11 -0
  17. package/components/execution/otel/processor.d.cts.map +1 -1
  18. package/components/execution/otel/processor.d.ts +11 -0
  19. package/components/execution/otel/processor.d.ts.map +1 -1
  20. package/components/execution/otel/processor.js +56 -5
  21. package/components/execution/otel/processor.js.map +1 -1
  22. package/components/execution/v1.cjs +4 -0
  23. package/components/execution/v1.cjs.map +1 -1
  24. package/components/execution/v1.d.cts.map +1 -1
  25. package/components/execution/v1.d.ts.map +1 -1
  26. package/components/execution/v1.js +4 -0
  27. package/components/execution/v1.js.map +1 -1
  28. package/components/execution/v2.cjs +4 -0
  29. package/components/execution/v2.cjs.map +1 -1
  30. package/components/execution/v2.d.cts.map +1 -1
  31. package/components/execution/v2.d.ts.map +1 -1
  32. package/components/execution/v2.js +4 -0
  33. package/components/execution/v2.js.map +1 -1
  34. package/helpers/deterministicId.cjs +298 -0
  35. package/helpers/deterministicId.cjs.map +1 -0
  36. package/helpers/deterministicId.js +296 -0
  37. package/helpers/deterministicId.js.map +1 -0
  38. package/package.json +1 -1
  39. package/types.d.cts +1 -1
  40. package/types.d.ts +1 -1
  41. package/version.cjs +1 -1
  42. package/version.cjs.map +1 -1
  43. package/version.d.cts +1 -1
  44. package/version.d.ts +1 -1
  45. package/version.js +1 -1
  46. 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: {
@@ -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;;;;QAHsB,EAAA,MAAA;EAAA,KAAA,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"}
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: {
@@ -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;;;;QAHsB,EAAA,MAAA;EAAA,KAAA,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"}
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
- const state = this.callbacks.getState();
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
- const currentState = this.callbacks.getState();
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
- const s = this.callbacks.getState();
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
- ws.send(require_connect.ConnectMessage.encode(require_connect.ConnectMessage.create({
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":";;;;;;;;;;;;;;;;;;;;;;AA6CA,MAAM,2BAA2B;;;;;AA0CjC,IAAa,iBAAb,MAA4B;CAC1B,AAAQ;CACR,AAAQ;CAER,AAAQ;CACR,AAAQ,kCAA+B,IAAI,KAAK;CAEhD,AAAQ,qBAGJ;EACF,IAAI,IAAIA,kCAAW;EACnB,eAAe,EAAE;EAClB;CAED,YACE,QACA,WACA;AACA,OAAK,SAAS;AACd,OAAK,YAAY;;CAGnB,IAAI,aAAqC;AACvC,SAAO,KAAK;;CAGd,IAAI,eAAmC;AACrC,SAAO,KAAK,mBAAmB;;;;;CAMjC,MAAM,oBAAmC;AACvC,QAAM,KAAK,mBAAmB,GAAG,MAAM;;;;;CAMzC,MAAM,QAAQ,UAAU,GAAG,OAAiB,EAAE,EAAiB;AAC7D,MAAI,OAAO,cAAc,YACvB,OAAM,IAAI,MAAM,kDAAkD;AAIpE,MADc,KAAK,UAAU,UAAU,KACzBC,8BAAgB,OAC5B,OAAM,IAAI,MAAM,4BAA4B;AAG9C,OAAK,UAAU,IAAI,2BAA2B,EAAE,SAAS,CAAC;EAE1D,IAAI,gBAAgB,KAAK,OAAO;AAEhC,SAAO,MAAM;AAEX,OADqB,KAAK,UAAU,UAAU,KACzBA,8BAAgB,OACnC;AAgBF,OAAI,KAAK,UAAU,cACjB,OAAM,KAAK,UAAU,cAAc,cAAc;AAGnD,OAAI;AACF,UAAM,KAAK,kBAAkB,eAAe,SAAS,CAAC,GAAG,KAAK,CAAC;AAC/D;YACO,KAAK;AACZ,SAAK,UAAU,IACb,qBACA,eAAe,QAAQ,IAAI,UAAU,IACtC;AAED,QAAI,EAAE,eAAeC,6BACnB,OAAM;AAGR,cAAU,IAAI;AAEd,QAAI,eAAeC,wBAAW;KAC5B,MAAM,mBACJ,kBAAkB,KAAK,OAAO;AAChC,SAAI,iBACF,MAAK,UAAU,IAAI,oCAAoC;AAEzD,qBAAgB,mBACZ,KAAK,OAAO,oBACZ,KAAK,OAAO;;AAGlB,QAAI,eAAeC,kCACjB,SAAQ,MACN,qHACD;IAGH,MAAM,QAAQC,wBAAW,QAAQ;AACjC,SAAK,UAAU,IAAI,mBAAmB,MAAM,IAAI;AAKhD,QAHkB,MAAMC,4BAAe,aAAa;AAClD,YAAO,KAAK,UAAU,UAAU,KAAKL,8BAAgB;MACrD,EACa;AACb,UAAK,UAAU,IAAI,8BAA8B;AACjD;;AAGF;;;AAIJ,OAAK,UAAU,IAAI,uBAAuB;;;;;CAM5C,MAAM,UAAyB;AAC7B,MAAI,KAAK,mBAAmB;AAC1B,SAAM,KAAK,kBAAkB,SAAS;AACtC,QAAK,oBAAoB;;;CAI7B,MAAc,iBACZ,kBACA,SACA;EACA,MAAM,MAAMM,oCAAmB,MAAM,KAAK,KAAK,gBAAgB,CAAC;EAEhE,MAAMC,UAAkC;GACtC,gBAAgB;GAChB,GAAI,mBACA,EAAE,eAAe,UAAU,oBAAoB,GAC/C,EAAE;GACP;AAED,MAAI,KAAK,OAAO,QACd,SAAQC,0BAAW,eAAe,KAAK,OAAO;EAGhD,MAAM,YAAY,IAAI,IAAI,qBAAqB,MAAM,KAAK,eAAe,CAAC;EAE1E,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,MAAM,WAAW;IAC5B,QAAQ;IACR,MAAM,IAAI,WAAW,IAAI;IAChB;IACV,CAAC;WACK,KAAK;GACZ,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,SAAM,IAAIP,4BACR,2CAA2C,UAAU,UAAU,CAAC,IAAI,UACpE,QACD;;AAGH,MAAI,CAAC,KAAK,IAAI;AACZ,OAAI,KAAK,WAAW,IAClB,OAAM,IAAIC,uBACR,2CAA2C,UAAU,UAAU,GAC7D,KAAK,OAAO,UAAU,UAAU,KAAK,OAAO,QAAQ,KAAK,GAC1D,IAAI,MAAM,KAAK,MAAM,IACtB,QACD;AAGH,OAAI,KAAK,WAAW,IAClB,OAAM,IAAIC,kCAAqB,QAAQ;AAGzC,SAAM,IAAIF,4BACR,2CAA2C,UAAU,UAAU,CAAC,IAAI,MAAM,KAAK,MAAM,IACrF,QACD;;AAIH,SADkB,MAAMQ,oCAAmB,KAAK;;CAIlD,MAAc,kBACZ,kBACA,SACA,OAAiB,EAAE,EACE;EACrB,IAAI,SAAS;AAEb,OAAK,UAAU,IAAI,wBAAwB;GAAE;GAAS;GAAM,CAAC;EAE7D,MAAM,4BAAY,IAAI,MAAM;EAC5B,MAAM,YAAY,MAAM,KAAK,iBAAiB,kBAAkB,QAAQ;EAExE,MAAM,eAAe,UAAU;AAC/B,OAAK,KAAK,aAAa;EAEvB,IAAIC;EAGJ,IAAIC;EACJ,MAAM,4BAA4B,IAAI,SAAe,SAAS,WAAW;AACvE,+BAA4B;AAC5B,8BAA2B;IAC3B;EAEF,MAAM,iBAAiB,iBAAiB;AACtC,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAChD,8BACE,IAAIV,4BAAe,cAAc,aAAa,aAAa,QAAQ,CACpE;KACA,IAAO;EAEV,IAAI,gBAAgB,UAAU;AAC9B,MAAI,KAAK,OAAO,wBAAwB;GACtC,MAAM,YAAY,KAAK,OAAO,uBAC5B,UAAU,gBACX;AACD,QAAK,UAAU,IAAI,8BAA8B;IAC/C,UAAU,UAAU;IACpB;IACD,CAAC;AACF,mBAAgB;;AAGlB,OAAK,UAAU,IAAI,yBAAyB;GAC1C,UAAU;GACV,cAAc,UAAU;GACxB;GACD,CAAC;EAEF,MAAM,KAAK,IAAI,UAAU,eAAe,CAAC,yBAAyB,CAAC;AACnE,KAAG,aAAa;EAEhB,IAAIW,qBAEmB,UAAmB;AACtC,OAAI,QAAQ;AACV,SAAK,UAAU,IACb,6EACA,EAAE,cAAc,CACjB;AACD;;AAEF,YAAS;AAET,QAAK,UAAU,IACb,2DACA,EAAE,cAAc,CACjB;AAED,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAChD,gBAAa,eAAe;AAE5B,MAAG,gBAAgB;AACnB,MAAG,gBAAgB;AACnB,MAAG,MACD,MACAC,6CAA6BC,uCAAuB,WAAW,CAChE;AAED,8BACE,IAAIb,4BACF,2BAA2B,aAAa,KACtC,iBAAiB,QAAQ,MAAM,UAAU,mBAE3C,QACD,CACF;;AAGH,KAAG,WAAW,QAAQ,kBAAkB,IAAI;AAC5C,KAAG,WAAW,OAAO;AACnB,GAAK,kBACH,IAAIA,4BACF,cAAc,aAAa,WAAW,GAAG,UACzC,QACD,CACF;;EAIL,MAAM,aAAa;GACjB,sBAAsB;GACtB,mBAAmB;GACnB,yBAAyB;GAC1B;EAED,IAAIc;EACJ,IAAIC;AAEJ,KAAG,YAAY,OAAO,UAAU;GAE9B,MAAM,iBAAiBC,qCADF,IAAI,WAAW,MAAM,KAAoB,CACN;AAExD,QAAK,UAAU,IACb,qBAAqBC,yCAAyB,eAAe,KAAK,IAClE,EAAE,cAAc,CACjB;AAED,OAAI,CAAC,WAAW,sBAAsB;AACpC,QAAI,eAAe,SAASC,mCAAmB,eAAe;AAC5D,KAAK,kBACH,IAAIlB,4BACF,+BAA+BiB,yCAC7B,eAAe,KAChB,IACD,QACD,CACF;AACD;;AAEF,eAAW,uBAAuB;;AAGpC,OAAI,CAAC,WAAW,mBAAmB;IACjC,MAAM,0BAA0BE,yCAAyB,OAAO;KAC9D,cAAc,UAAU;KACxB,aAAa,KAAK,OAAO;KACzB,UAAUC,4BAAgB,EAAE,GAAGC,2BAAe,EAAE,CAAC;KACjD,YAAY,IAAIC;KAChB,aAAa;KACb,WAAW;KACX,0BACE,KAAK,OAAO,eAAe;KAC7B,kBAAkB,MAAMC,qCAA0B;KAClD,UAAU;MACR,cAAc,UAAU;MACxB,WAAW,UAAU;MACtB;KACD,MAAM,KAAK,OAAO,eAAe;KACjC,cAAc,IAAI,aAAa,CAAC,OAC9B,KAAK,OAAO,eAAe,sBAC5B;KACU;KACX,YAAY,KAAK,OAAO,cAAe,MAAMC,wBAAa;KAC1D,sBAAsB,KAAK,OAAO;KACnC,CAAC;IAEF,MAAM,+BAA+BL,yCAAyB,OAC5D,wBACD,CAAC,QAAQ;AAEV,OAAG,KACDM,+BAAe,OACbA,+BAAe,OAAO;KACpB,MAAMP,mCAAmB;KACzB,SAAS;KACV,CAAC,CACH,CAAC,QAAQ,CACX;AAED,eAAW,oBAAoB;AAC/B;;AAGF,OAAI,CAAC,WAAW,yBAAyB;AACvC,QACE,eAAe,SAASA,mCAAmB,0BAC3C;AACA,KAAK,kBACH,IAAIlB,4BACF,+BAA+BiB,yCAC7B,eAAe,KAChB,IACD,QACD,CACF;AACD;;IAGF,MAAM,eAAeS,2CAA2B,OAC9C,eAAe,QAChB;AAED,eAAW,0BAA0B;AAErC,0BACE,aAAa,kBAAkB,SAAS,oBACjC,aAAa,kBAAoC,GACpD;AACN,4BACE,aAAa,oBAAoB,SAAS,oBACnC,aAAa,oBAAsC,GACtD;AAEN,iCAA6B;AAC7B;;AAGF,QAAK,UAAU,IAAI,wCAAwC;IACzD,MAAMT,yCAAyB,eAAe,KAAK;IACnD,SAAS,eAAe;IACxB;IACA;IACA,OAAO,KAAK,UAAU,UAAU;IAChC;IACD,CAAC;;AAGJ,QAAM;AAEN,eAAa,eAAe;AAE5B,OAAK,gBAAgB,OAAO,UAAU,aAAa;AAEnD,YAAU;EAEV,MAAMU,OAAmB;GACvB,IAAI;GACJ;GACA,eAAe;AACb,QAAI,OACF;AAEF,aAAS;AACT,OAAG,gBAAgB;AACnB,OAAG,gBAAgB;AACnB,OAAG,OAAO;;GAEZ,mBAAmB;GACpB;AACD,OAAK,oBAAoB;AAIzB,OAAK,UAAU,cAAc5B,8BAAgB,OAAO;AAEpD,OAAK,UAAU,IAAI,qBAAqB,aAAa,GAAG;EAExD,IAAI,aAAa;AAEf,sBAAoB,OAAO,UAAmB;AAC5C,OAAI,QAAQ;AACV,SAAK,UAAU,IACb,0DACA,EAAE,cAAc,CACjB;AACD;;AAEF,YAAS;AAET,SAAM,KAAK,SAAS;GAEpB,MAAM,eAAe,KAAK,UAAU,UAAU;AAC9C,OACE,iBAAiBA,8BAAgB,WACjC,iBAAiBA,8BAAgB,QACjC;AACA,SAAK,UAAU,IACb,qBAAqB,aAAa,2CACnC;AACD;;AAGF,QAAK,UAAU,cAAcA,8BAAgB,aAAa;AAC1D,QAAK,gBAAgB,IAAI,UAAU,aAAa;AAEhD,OAAI,YAAY;AACd,SAAK,UAAU,IACb,qBAAqB,aAAa,kCACnC;AACD;;AAGF,QAAK,UAAU,IACb,qBAAqB,aAAa,IAClC,iBAAiB,QAAQ,MAAM,UAAU,MAC1C;AACD,QAAK,QAAQ,UAAU,GAAG,CAAC,GAAG,MAAM,oBAAoB,CAAC;;AAG3D,KAAG,WAAW,QAAQ,kBAAkB,IAAI;AAC5C,KAAG,WAAW,OAAO;AACnB,GAAK,kBACH,IAAIC,4BAAe,sBAAsB,GAAG,UAAU,QAAQ,CAC/D;;AAIL,KAAG,YAAY,OAAO,UAAU;GAE9B,MAAM,iBAAiBgB,qCADF,IAAI,WAAW,MAAM,KAAoB,CACN;AAExD,OAAI,eAAe,SAASE,mCAAmB,iBAAiB;AAC9D,iBAAa;AACb,SAAK,UAAU,IAAI,6BAA6B,EAAE,cAAc,CAAC;AACjE,QAAI;AACF,UAAK,UAAU,IACb,oEACA,EAAE,cAAc,CACjB;AAED,WAAM,KAAK,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC;AAChC,WAAM,KAAK,SAAS;aACb,KAAK;AACZ,UAAK,UAAU,IACb,wDACA;MACE;MACA,KAAK,eAAe,QAAQ,IAAI,UAAU;MAC3C,CACF;AAED,WAAM,KAAK,SAAS;AAEpB,KAAK,kBACH,IAAIlB,4BACF,yDAAyD,aAAa,IACtE,QACD,CACF;;AAEH;;AAGF,OAAI,eAAe,SAASkB,mCAAmB,mBAAmB;AAChE,SAAK,oBAAoB;AACzB,SAAK,UAAU,IAAI,6BAA6B,EAAE,cAAc,CAAC;AACjE;;AAGF,OAAI,eAAe,SAASA,mCAAmB,0BAA0B;AAEvE,QADqB,KAAK,UAAU,UAAU,KACzBnB,8BAAgB,QAAQ;AAC3C,UAAK,UAAU,IAAI,+CAA+C,EAChE,cACD,CAAC;AACF;;IAGF,MAAM,yBAAyB6B,6CAC7B,eAAe,QAChB;AAED,SAAK,UAAU,IAAI,qCAAqC;KACtD,WAAW,uBAAuB;KAClC,OAAO,uBAAuB;KAC9B,SAAS,uBAAuB;KAChC,cAAc,uBAAuB;KACrC,QAAQ,uBAAuB;KAC/B;KACD,CAAC;AAEF,QACE,OAAO,uBAAuB,YAAY,YAC1C,uBAAuB,QAAQ,WAAW,GAC1C;AACA,UAAK,UAAU,IAAI,oCAAoC;MACrD,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,QAAQ,uBAAuB;MAC/B;MACD,CAAC;AACF;;AAGF,QAAI,CAAC,KAAK,OAAO,OAAO,SAAS,uBAAuB,QAAQ,EAAE;AAChE,UAAK,UAAU,IAAI,8CAA8C;MAC/D,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,SAAS,uBAAuB;MAChC,cAAc,uBAAuB;MACrC,QAAQ,uBAAuB;MAC/B;MACD,CAAC;AACF;;AAIF,OAAG,KACDH,+BAAe,OACbA,+BAAe,OAAO;KACpB,MAAMP,mCAAmB;KACzB,SAASW,qCAAqB,OAC5BA,qCAAqB,OAAO;MAC1B,WAAW,uBAAuB;MAClC,OAAO,uBAAuB;MAC9B,OAAO,uBAAuB;MAC9B,cAAc,uBAAuB;MACrC,WAAW,uBAAuB;MAClC,QAAQ,uBAAuB;MAC/B,cAAc,uBAAuB;MACrC,gBAAgB,uBAAuB;MACvC,OAAO,uBAAuB;MAC/B,CAAC,CACH,CAAC,QAAQ;KACX,CAAC,CACH,CAAC,QAAQ,CACX;AAED,SAAK,mBAAmB,GAAG,IAAI,EAAE;AACjC,SAAK,mBAAmB,cACtB,uBAAuB,aACrB,uBAAuB;IAG3B,IAAIC;AACJ,0BAAsB,kBAAkB;AACtC,SAAI,0BAA0B,OAC5B;KAGF,MAAM,iBACJ,KAAK,mBAAmB,cACtB,uBAAuB;AAE3B,SAAI,CAAC,gBAAgB;AACnB,oBAAc,oBAAoB;AAClC;;KAQF,MAAM,UAAU,KAAK,mBAAmB,MAAM;AAE9C,UAAK,UAAU,IAAI,mBAAmB;MACpC;MACA,SAAS;MACV,CAAC;AAEF,SAAI,QAAQ,eAAe,UAAU,MAAM;AACzC,WAAK,UAAU,IACb,oDACA;OACE;OACA,WAAW,uBAAuB;OACnC,CACF;AACD;;AAGF,aAAQ,KACNL,+BAAe,OACbA,+BAAe,OAAO;MACpB,MAAMP,mCAAmB;MACzB,SAASa,6CAA6B,OACpCA,6CAA6B,OAAO;OAClC,WAAW,uBAAuB;OAClC,OAAO,uBAAuB;OAC9B,OAAO,uBAAuB;OAC9B,cAAc,uBAAuB;OACrC,WAAW,uBAAuB;OAClC,QAAQ,uBAAuB;OAC/B,OAAO,uBAAuB;OAC9B,cAAc,uBAAuB;OACrC,gBAAgB,uBAAuB;OACvC,SAAS;OACV,CAAC,CACH,CAAC,QAAQ;MACX,CAAC,CACH,CAAC,QAAQ,CACX;OACA,sBAAsB;AAEzB,QAAI;KAEF,MAAM,gBAAgB,MAAM,KAAK,UAAU,uBACzC,uBACD;AAED,UAAK,UAAU,IAAI,wBAAwB;MACzC;MACA,WAAW,uBAAuB;MACnC,CAAC;AAEF,SAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,UAAU,IAAI,4CAA4C;OAC7D;OACA,WAAW,uBAAuB;OACnC,CAAC;AACF,UAAI,KAAK,UAAU,iBACjB,MAAK,UAAU,iBACb,uBAAuB,WACvB,cACD;AAEH;;AAGF,UAAK,kBAAkB,GAAG,KACxBN,+BAAe,OACbA,+BAAe,OAAO;MACpB,MAAMP,mCAAmB;MACzB,SAAS;MACV,CAAC,CACH,CAAC,QAAQ,CACX;aACM,KAAK;AACZ,UAAK,UAAU,IACb,+BAA+B,uBAAuB,aACtD,eAAe,QAAQ,IAAI,UAAU,IACtC;cACO;AACR,UAAK,mBAAmB,GAAG,MAAM;AACjC,YAAO,KAAK,mBAAmB,cAC7B,uBAAuB;AAEzB,mBAAc,oBAAoB;;AAGpC;;AAGF,OAAI,eAAe,SAASA,mCAAmB,kBAAkB;IAC/D,MAAM,WAAWc,qCAAoB,eAAe,QAAQ;AAE5D,SAAK,UAAU,IAAI,2BAA2B;KAC5C;KACA,WAAW,SAAS;KACrB,CAAC;AAEF,SAAK,UAAU,aAAa,SAAS,UAAU;AAC/C;;AAGF,OACE,eAAe,SACfd,mCAAmB,iCACnB;IACA,MAAM,iBAAiBe,gDAAgC,OACrD,eAAe,QAChB;AAED,SAAK,UAAU,IAAI,6BAA6B;KAC9C;KACA,YAAY,eAAe;KAC5B,CAAC;AAEF,QAAI,eAAe,WACjB,MAAK,mBAAmB,cAAc,eAAe,aACnD,eAAe;SACZ;AACL,UAAK,UAAU,IAAI,0BAA0B;MAC3C;MACA,WAAW,eAAe;MAC3B,CAAC;AACF,YAAO,KAAK,mBAAmB,cAC7B,eAAe;;AAInB;;AAGF,QAAK,UAAU,IAAI,2BAA2B;IAC5C,MAAMhB,yCAAyB,eAAe,KAAK;IACnD,SAAS,eAAe;IACxB;IACA;IACA,OAAO,KAAK,UAAU,UAAU;IAChC;IACD,CAAC;;EAIJ,IAAIiB;AACJ,MAAI,wBAAwB,OAC1B,qBAAoB,kBAAkB;AACpC,OAAI,wBAAwB,OAC1B;AAgBF,OAAI,GAAG,eAAe,UAAU,KAC9B;AAGF,OAAI,KAAK,qBAAqB,GAAG;AAC/B,SAAK,UAAU,IAAI,4BAA4B,EAAE,cAAc,CAAC;AAChE,IAAK,kBACH,IAAIlC,4BACF,0CAA0C,aAAa,IACvD,QACD,CACF;AACD;;AAGF,QAAK,UAAU,IAAI,4BAA4B,EAAE,cAAc,CAAC;AAEhE,QAAK;AACL,MAAG,KACDyB,+BAAe,OACbA,+BAAe,OAAO,EACpB,MAAMP,mCAAmB,kBAC1B,CAAC,CACH,CAAC,QAAQ,CACX;KACA,oBAAoB;AAGzB,OAAK,UAAU,YAAY;AACzB,OAAI,OACF;AAEF,YAAS;AAET,QAAK,UAAU,IAAI,0BAA0B,EAAE,cAAc,CAAC;AAC9D,OAAI,GAAG,eAAe,UAAU,MAAM;AACpC,SAAK,UAAU,IAAI,yBAAyB,EAAE,cAAc,CAAC;AAC7D,OAAG,KACDO,+BAAe,OACbA,+BAAe,OAAO,EACpB,MAAMP,mCAAmB,cAC1B,CAAC,CACH,CAAC,QAAQ,CACX;;AAGH,QAAK,UAAU,IAAI,sBAAsB,EAAE,cAAc,CAAC;AAC1D,MAAG,gBAAgB;AACnB,MAAG,gBAAgB;AAEnB,SAAM,KAAK,mBAAmB,GAAG,MAAM;AAEvC,MAAG,MACD,KACAN,6CAA6BC,uCAAuB,gBAAgB,CACrE;AAED,OAAI,KAAK,mBAAmB,OAAO,aACjC,MAAK,oBAAoB;AAG3B,QAAK,UAAU,IAAI,gCAAgC,EAAE,cAAc,CAAC;AACpE,iBAAc,kBAAkB;;AAGlC,SAAO;;CAGT,MAAM,gBAAiC;AACrC,SAAOsB,8BAAkB;GACvB,YAAY,KAAK,OAAO;GACxB,MAAM,KAAK,OAAO;GACnB,CAAC"}
@@ -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
- const state = this.callbacks.getState();
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
- const currentState = this.callbacks.getState();
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
- const s = this.callbacks.getState();
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
- ws.send(ConnectMessage.encode(ConnectMessage.create({
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