@superdurable/dex 1.11.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -191,6 +191,24 @@ try {
191
191
  }
192
192
  ```
193
193
 
194
+ After `await worker.start()`, call `await worker.waitPullRegistered({ timeoutMs: 10_000 })`
195
+ to wait until every Flow type queue and the app Worker ID queue has registered at least once.
196
+ The wait also accepts an `AbortSignal` as `signal`. It is safe before startup and for concurrent
197
+ callers. It rejects with `PullRegistrationError` (queue and original gRPC `cause`) if a permanent
198
+ rejection leaves a queue without another registered stream before readiness. Startup failures
199
+ and shutdown before readiness also reject the wait. Once registration succeeds, later waits
200
+ resolve even after shutdown.
201
+
202
+ Use `worker.pullRegistrationState().isReady` for ongoing probes. Snapshots include `queues`
203
+ with `queue`, `hasRegisteredStream`, and `lastPermanentError`. Readiness does not flap during
204
+ reconnects or transient errors. A permanent rejection without another registered stream makes
205
+ it false; re-registration clears that queue's error. Closing does not reset readiness.
206
+
207
+ Set `pull.stopOnPermanentStreamRejection: true` to drain and stop on such a permanent rejection
208
+ before or after readiness. It defaults to false, retaining indefinite retries. `worker.run()`
209
+ rejects with `PullRegistrationError` after draining; `start()` keeps its non-blocking startup
210
+ behavior. Always call `close()`, which remains safe after `run()` returns.
211
+
194
212
  Pull mode polls the Worker's sticky queue and every registered Flow type queue.
195
213
  Flow type names must be unique within one Dex server. `maxConcurrentTasks`
196
214
  defaults to the logical CPU count, and `idleStreamsPerQueue` defaults to one.
@@ -200,6 +218,14 @@ queue even when all slots are busy, so it can hold up to
200
218
  `(1 + F) * (idleStreamsPerQueue + maxConcurrentTasks)` streams, where `F` is the
201
219
  number of registered Flow types. Size both options for the server's stream cap.
202
220
 
221
+ The Worker rejects an unregistered Step or RPC by name. Dex retries that task
222
+ on another pull Worker without consuming a Step attempt, including when the
223
+ Flow was sticky to the rejecting Worker. If no capable Worker accepts it within
224
+ the server's dispatch wait (10 seconds by default, or the local Step attempt),
225
+ the Step follows its failure and retry policy; an RPC caller receives the named
226
+ error. This reassignment requires a Dex Server that supports it. Against older
227
+ Servers, the Worker returns the not-registered error as before.
228
+
203
229
  The default `appWorkerID` uses the first nonempty value from
204
230
  `DEX_WORKER_INSTANCE`, `POD_NAME`, `HOSTNAME`, or the system hostname, followed by
205
231
  eight random base32 characters. An override must identify one Worker process
@@ -10,13 +10,19 @@ export declare enum PollWorkerTaskRejectReason {
10
10
  POLL_WORKER_TASK_REJECT_REASON_UNSPECIFIED = 0,
11
11
  /** POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY - All Worker execution slots are occupied. */
12
12
  POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY = 1,
13
+ /** POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_STEP - The Flow has no registration for the requested Step type. */
14
+ POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_STEP = 2,
15
+ /** POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_RPC - The Flow has no registration for the requested RPC name. */
16
+ POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_RPC = 3,
13
17
  UNRECOGNIZED = -1
14
18
  }
15
- /** Distinguishes absence of a Worker from loss of an assigned Worker. */
19
+ /** Distinguishes no available Worker, a disconnected Worker, and a missing Step or RPC registration. */
16
20
  export declare enum DispatchTaskErrorReason {
17
21
  DISPATCH_TASK_ERROR_REASON_UNSPECIFIED = 0,
18
22
  DISPATCH_TASK_ERROR_REASON_NO_WORKER_AVAILABLE = 1,
19
23
  DISPATCH_TASK_ERROR_REASON_WORKER_DISCONNECTED = 2,
24
+ /** DISPATCH_TASK_ERROR_REASON_UNKNOWN_NAME - A matched Worker does not register the requested Step type or RPC name. */
25
+ DISPATCH_TASK_ERROR_REASON_UNKNOWN_NAME = 3,
20
26
  UNRECOGNIZED = -1
21
27
  }
22
28
  export declare enum IndexType {
@@ -227,7 +233,7 @@ export interface PollWorkerTaskRequest {
227
233
  $case: "taskFrame";
228
234
  value: PollWorkerTaskFrame;
229
235
  } | //
230
- /** Declines an assigned task when the Worker has no capacity. */
236
+ /** Declines an assigned task before output when the Worker lacks capacity or the named handler. */
231
237
  {
232
238
  $case: "reject";
233
239
  value: PollWorkerTaskReject;
@@ -318,6 +324,8 @@ export interface PollWorkerTaskResponse {
318
324
  }
319
325
  /** Confirms that Dex accepted the queue registration. */
320
326
  export interface PollWorkerTaskRegistered {
327
+ /** Allows this queue-owner stream to reject an assigned unknown Step type or RPC name. */
328
+ supportsUnknownNameRejection: boolean;
321
329
  }
322
330
  /** Assigns one task to this stream until its final result, error, or rejection. */
323
331
  export interface PollWorkerTask {
@@ -383,6 +391,14 @@ export interface DispatchTaskRequest {
383
391
  } | undefined;
384
392
  /** Allows matching to send assignment state frames to capable callers. */
385
393
  supportsAssignmentState: boolean;
394
+ /** Worker processes already found unable to serve this task. */
395
+ excludedAppWorkerIds: string[];
396
+ /** Ends an internal sticky queue search immediately after an unknown-name rejection. */
397
+ stopAfterUnknownName: boolean;
398
+ /** Ends an internal sticky queue search when no Worker streams remain connected. */
399
+ stopWhenQueueHasNoStreams: boolean;
400
+ /** Allows matching to return UNKNOWN_NAME after a Worker rejects an unknown Step type or RPC name. */
401
+ supportsUnknownNameError: boolean;
386
402
  }
387
403
  /** Reports assignment changes, relays Worker output, then ends with a result, Worker error, or dispatch error. */
388
404
  export interface DispatchTaskResponse {
@@ -414,6 +430,8 @@ export interface DispatchTaskResponse {
414
430
  } | undefined;
415
431
  /** Identifies the Worker that produced the final result or Worker error. */
416
432
  servedByAppWorkerId: string;
433
+ /** Identifies a Worker that rejected the task's Step type or RPC name. */
434
+ rejectedByAppWorkerId: string;
417
435
  }
418
436
  /** Reports a failure before Dex receives a Worker result. */
419
437
  export interface DispatchTaskError {
@@ -1604,6 +1622,8 @@ export interface StartSubFlowActivityInput {
1604
1622
  parentFlowConfig: FlowConfig | undefined;
1605
1623
  /** Source Step; activity context supplies parent Flow and run IDs. */
1606
1624
  parentStepExecutionId: string;
1625
+ /** Preserve legacy activity errors when older interpreter versions schedule this activity. */
1626
+ typedRejectionEnabled: boolean;
1607
1627
  }
1608
1628
  export interface StartSubFlowActivityOutput {
1609
1629
  immediateFlowResult: FlowResult | undefined;
@@ -17,14 +17,20 @@ export var PollWorkerTaskRejectReason;
17
17
  PollWorkerTaskRejectReason[PollWorkerTaskRejectReason["POLL_WORKER_TASK_REJECT_REASON_UNSPECIFIED"] = 0] = "POLL_WORKER_TASK_REJECT_REASON_UNSPECIFIED";
18
18
  /** POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY - All Worker execution slots are occupied. */
19
19
  PollWorkerTaskRejectReason[PollWorkerTaskRejectReason["POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY"] = 1] = "POLL_WORKER_TASK_REJECT_REASON_NO_CAPACITY";
20
+ /** POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_STEP - The Flow has no registration for the requested Step type. */
21
+ PollWorkerTaskRejectReason[PollWorkerTaskRejectReason["POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_STEP"] = 2] = "POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_STEP";
22
+ /** POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_RPC - The Flow has no registration for the requested RPC name. */
23
+ PollWorkerTaskRejectReason[PollWorkerTaskRejectReason["POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_RPC"] = 3] = "POLL_WORKER_TASK_REJECT_REASON_UNKNOWN_RPC";
20
24
  PollWorkerTaskRejectReason[PollWorkerTaskRejectReason["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
21
25
  })(PollWorkerTaskRejectReason || (PollWorkerTaskRejectReason = {}));
22
- /** Distinguishes absence of a Worker from loss of an assigned Worker. */
26
+ /** Distinguishes no available Worker, a disconnected Worker, and a missing Step or RPC registration. */
23
27
  export var DispatchTaskErrorReason;
24
28
  (function (DispatchTaskErrorReason) {
25
29
  DispatchTaskErrorReason[DispatchTaskErrorReason["DISPATCH_TASK_ERROR_REASON_UNSPECIFIED"] = 0] = "DISPATCH_TASK_ERROR_REASON_UNSPECIFIED";
26
30
  DispatchTaskErrorReason[DispatchTaskErrorReason["DISPATCH_TASK_ERROR_REASON_NO_WORKER_AVAILABLE"] = 1] = "DISPATCH_TASK_ERROR_REASON_NO_WORKER_AVAILABLE";
27
31
  DispatchTaskErrorReason[DispatchTaskErrorReason["DISPATCH_TASK_ERROR_REASON_WORKER_DISCONNECTED"] = 2] = "DISPATCH_TASK_ERROR_REASON_WORKER_DISCONNECTED";
32
+ /** DISPATCH_TASK_ERROR_REASON_UNKNOWN_NAME - A matched Worker does not register the requested Step type or RPC name. */
33
+ DispatchTaskErrorReason[DispatchTaskErrorReason["DISPATCH_TASK_ERROR_REASON_UNKNOWN_NAME"] = 3] = "DISPATCH_TASK_ERROR_REASON_UNKNOWN_NAME";
28
34
  DispatchTaskErrorReason[DispatchTaskErrorReason["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
29
35
  })(DispatchTaskErrorReason || (DispatchTaskErrorReason = {}));
30
36
  export var IndexType;
@@ -788,10 +794,13 @@ export const PollWorkerTaskResponse = {
788
794
  },
789
795
  };
790
796
  function createBasePollWorkerTaskRegistered() {
791
- return {};
797
+ return { supportsUnknownNameRejection: false };
792
798
  }
793
799
  export const PollWorkerTaskRegistered = {
794
- encode(_, writer = new BinaryWriter()) {
800
+ encode(message, writer = new BinaryWriter()) {
801
+ if (message.supportsUnknownNameRejection !== false) {
802
+ writer.uint32(8).bool(message.supportsUnknownNameRejection);
803
+ }
795
804
  return writer;
796
805
  },
797
806
  decode(input, length) {
@@ -801,6 +810,13 @@ export const PollWorkerTaskRegistered = {
801
810
  while (reader.pos < end) {
802
811
  const tag = reader.uint32();
803
812
  switch (tag >>> 3) {
813
+ case 1: {
814
+ if (tag !== 8) {
815
+ break;
816
+ }
817
+ message.supportsUnknownNameRejection = reader.bool();
818
+ continue;
819
+ }
804
820
  }
805
821
  if ((tag & 7) === 4 || tag === 0) {
806
822
  break;
@@ -812,8 +828,9 @@ export const PollWorkerTaskRegistered = {
812
828
  create(base) {
813
829
  return PollWorkerTaskRegistered.fromPartial(base ?? {});
814
830
  },
815
- fromPartial(_) {
831
+ fromPartial(object) {
816
832
  const message = createBasePollWorkerTaskRegistered();
833
+ message.supportsUnknownNameRejection = object.supportsUnknownNameRejection ?? false;
817
834
  return message;
818
835
  },
819
836
  };
@@ -1044,6 +1061,10 @@ function createBaseDispatchTaskRequest() {
1044
1061
  taskId: "",
1045
1062
  request: undefined,
1046
1063
  supportsAssignmentState: false,
1064
+ excludedAppWorkerIds: [],
1065
+ stopAfterUnknownName: false,
1066
+ stopWhenQueueHasNoStreams: false,
1067
+ supportsUnknownNameError: false,
1047
1068
  };
1048
1069
  }
1049
1070
  export const DispatchTaskRequest = {
@@ -1083,6 +1104,18 @@ export const DispatchTaskRequest = {
1083
1104
  if (message.supportsAssignmentState !== false) {
1084
1105
  writer.uint32(88).bool(message.supportsAssignmentState);
1085
1106
  }
1107
+ for (const v of message.excludedAppWorkerIds) {
1108
+ writer.uint32(98).string(v);
1109
+ }
1110
+ if (message.stopAfterUnknownName !== false) {
1111
+ writer.uint32(104).bool(message.stopAfterUnknownName);
1112
+ }
1113
+ if (message.stopWhenQueueHasNoStreams !== false) {
1114
+ writer.uint32(112).bool(message.stopWhenQueueHasNoStreams);
1115
+ }
1116
+ if (message.supportsUnknownNameError !== false) {
1117
+ writer.uint32(120).bool(message.supportsUnknownNameError);
1118
+ }
1086
1119
  return writer;
1087
1120
  },
1088
1121
  decode(input, length) {
@@ -1169,6 +1202,34 @@ export const DispatchTaskRequest = {
1169
1202
  message.supportsAssignmentState = reader.bool();
1170
1203
  continue;
1171
1204
  }
1205
+ case 12: {
1206
+ if (tag !== 98) {
1207
+ break;
1208
+ }
1209
+ message.excludedAppWorkerIds.push(reader.string());
1210
+ continue;
1211
+ }
1212
+ case 13: {
1213
+ if (tag !== 104) {
1214
+ break;
1215
+ }
1216
+ message.stopAfterUnknownName = reader.bool();
1217
+ continue;
1218
+ }
1219
+ case 14: {
1220
+ if (tag !== 112) {
1221
+ break;
1222
+ }
1223
+ message.stopWhenQueueHasNoStreams = reader.bool();
1224
+ continue;
1225
+ }
1226
+ case 15: {
1227
+ if (tag !== 120) {
1228
+ break;
1229
+ }
1230
+ message.supportsUnknownNameError = reader.bool();
1231
+ continue;
1232
+ }
1172
1233
  }
1173
1234
  if ((tag & 7) === 4 || tag === 0) {
1174
1235
  break;
@@ -1214,11 +1275,15 @@ export const DispatchTaskRequest = {
1214
1275
  }
1215
1276
  }
1216
1277
  message.supportsAssignmentState = object.supportsAssignmentState ?? false;
1278
+ message.excludedAppWorkerIds = object.excludedAppWorkerIds?.map((e) => e) || [];
1279
+ message.stopAfterUnknownName = object.stopAfterUnknownName ?? false;
1280
+ message.stopWhenQueueHasNoStreams = object.stopWhenQueueHasNoStreams ?? false;
1281
+ message.supportsUnknownNameError = object.supportsUnknownNameError ?? false;
1217
1282
  return message;
1218
1283
  },
1219
1284
  };
1220
1285
  function createBaseDispatchTaskResponse() {
1221
- return { output: undefined, servedByAppWorkerId: "" };
1286
+ return { output: undefined, servedByAppWorkerId: "", rejectedByAppWorkerId: "" };
1222
1287
  }
1223
1288
  export const DispatchTaskResponse = {
1224
1289
  encode(message, writer = new BinaryWriter()) {
@@ -1248,6 +1313,9 @@ export const DispatchTaskResponse = {
1248
1313
  if (message.servedByAppWorkerId !== "") {
1249
1314
  writer.uint32(50).string(message.servedByAppWorkerId);
1250
1315
  }
1316
+ if (message.rejectedByAppWorkerId !== "") {
1317
+ writer.uint32(74).string(message.rejectedByAppWorkerId);
1318
+ }
1251
1319
  return writer;
1252
1320
  },
1253
1321
  decode(input, length) {
@@ -1313,6 +1381,13 @@ export const DispatchTaskResponse = {
1313
1381
  message.servedByAppWorkerId = reader.string();
1314
1382
  continue;
1315
1383
  }
1384
+ case 9: {
1385
+ if (tag !== 74) {
1386
+ break;
1387
+ }
1388
+ message.rejectedByAppWorkerId = reader.string();
1389
+ continue;
1390
+ }
1316
1391
  }
1317
1392
  if ((tag & 7) === 4 || tag === 0) {
1318
1393
  break;
@@ -1371,6 +1446,7 @@ export const DispatchTaskResponse = {
1371
1446
  }
1372
1447
  }
1373
1448
  message.servedByAppWorkerId = object.servedByAppWorkerId ?? "";
1449
+ message.rejectedByAppWorkerId = object.rejectedByAppWorkerId ?? "";
1374
1450
  return message;
1375
1451
  },
1376
1452
  };
@@ -14576,7 +14652,7 @@ export const SyncAttributeBatchActivityInput = {
14576
14652
  },
14577
14653
  };
14578
14654
  function createBaseStartSubFlowActivityInput() {
14579
- return { condition: undefined, parentFlowConfig: undefined, parentStepExecutionId: "" };
14655
+ return { condition: undefined, parentFlowConfig: undefined, parentStepExecutionId: "", typedRejectionEnabled: false };
14580
14656
  }
14581
14657
  export const StartSubFlowActivityInput = {
14582
14658
  encode(message, writer = new BinaryWriter()) {
@@ -14589,6 +14665,9 @@ export const StartSubFlowActivityInput = {
14589
14665
  if (message.parentStepExecutionId !== "") {
14590
14666
  writer.uint32(26).string(message.parentStepExecutionId);
14591
14667
  }
14668
+ if (message.typedRejectionEnabled !== false) {
14669
+ writer.uint32(48).bool(message.typedRejectionEnabled);
14670
+ }
14592
14671
  return writer;
14593
14672
  },
14594
14673
  decode(input, length) {
@@ -14619,6 +14698,13 @@ export const StartSubFlowActivityInput = {
14619
14698
  message.parentStepExecutionId = reader.string();
14620
14699
  continue;
14621
14700
  }
14701
+ case 6: {
14702
+ if (tag !== 48) {
14703
+ break;
14704
+ }
14705
+ message.typedRejectionEnabled = reader.bool();
14706
+ continue;
14707
+ }
14622
14708
  }
14623
14709
  if ((tag & 7) === 4 || tag === 0) {
14624
14710
  break;
@@ -14639,6 +14725,7 @@ export const StartSubFlowActivityInput = {
14639
14725
  ? FlowConfig.fromPartial(object.parentFlowConfig)
14640
14726
  : undefined;
14641
14727
  message.parentStepExecutionId = object.parentStepExecutionId ?? "";
14728
+ message.typedRejectionEnabled = object.typedRejectionEnabled ?? false;
14642
14729
  return message;
14643
14730
  },
14644
14731
  };