@superdurable/dex 1.20.0 → 1.23.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
@@ -215,12 +215,15 @@ defaults to the logical CPU count, and `idleStreamsPerQueue` defaults to one.
215
215
  Each stream runs one task at a time. When all slots are busy, the Worker rejects
216
216
  additional assignments for reassignment. The Worker keeps idle streams on each
217
217
  queue even when all slots are busy. After tasks finish, it gracefully closes surplus
218
- idle streams while preserving readiness. With `F` registered Flow types, the
218
+ idle streams while preserving readiness. The SDK sends an upstream Pong every
219
+ 20 seconds while a task runs and stops before its final frame. This interval is
220
+ internal and needs no Worker option. With `F` registered Flow types, the
219
221
  steady-state bound after load drops is
220
- `maxConcurrentTasks + (1 + F) * idleStreamsPerQueue` streams. The transient peak
221
- during a burst remains bounded by the matching caps. Size both options for
222
- `matching.maxConcurrentTasksCap` per app Worker ID per matching owner and
223
- `matching.maxStreams` per Matching instance.
222
+ `maxConcurrentTasks + (1 + F) * idleStreamsPerQueue` streams.
223
+ Allow up to `1 + F` additional streams for 30 seconds after reserve declines.
224
+ The transient peak during a burst remains bounded by the matching caps. Size
225
+ both options for `matching.maxConcurrentTasksCap` per app Worker ID per matching
226
+ owner and `matching.maxStreams` per Matching instance.
224
227
 
225
228
  The Worker rejects an unregistered Step or RPC by name. Dex retries that task
226
229
  on another pull Worker without consuming a Step attempt, including when the
@@ -258,11 +261,11 @@ is at least two, otherwise zero. With the CPU-count default, Steps get one fewer
258
261
  slot than before. Set it explicitly to zero to opt out. With one slot and no
259
262
  explicit reserve, Worker start logs one warning: RPCs may wait behind
260
263
  long-running Steps; use a limit of at least two or set the reserve explicitly.
261
- Flows must stay responsive; Dex cannot prioritize synchronous RPCs like workflow
262
- engines prioritize reads. The value must be nonnegative and less than
263
- `maxConcurrentTasks` after its CPU-count default is resolved; invalid values
264
- fail construction. RPC and Step handlers count together: WaitFor and Execute
265
- tasks, including local attempts, are declined with `NO_CAPACITY` when the busy
264
+ Flows must stay responsive because RPCs share Worker task capacity with Steps.
265
+ The value must be nonnegative and less than `maxConcurrentTasks` after its
266
+ CPU-count default is resolved; invalid values fail construction. RPC and Step
267
+ handlers count together. WaitFor and Execute tasks, including local attempts,
268
+ are declined with `NO_CAPACITY` when the busy
266
269
  count reaches the task limit minus the reserve. API-direct and transactional
267
270
  InvokeWorkerRPC tasks can use the full limit.
268
271
 
@@ -274,16 +277,21 @@ A decline lets Dex try another Worker without consuming an attempt. If all
274
277
  Workers remain at their Step limit, a Step can wait until the dispatch wait
275
278
  expires, then receive `NO_WORKER_AVAILABLE`, consume an attempt, and follow its
276
279
  retry policy, as when all Workers are full. Local attempts wait the local
277
- dispatch wait, then fall back according to their policy. Each queue still keeps
278
- its configured idle streams; a reserve decline does not close a stream or change
279
- registration readiness.
280
+ dispatch wait, then fall back according to their policy. A queue that declines
281
+ a Step for reserved RPC capacity keeps one additional idle stream until 30
282
+ seconds after its last decline. Other queues retain their configured count.
283
+ The Worker does not open the extra stream while all task slots are busy. Set
284
+ `idleStreamsPerQueue` to at least two for heavy Step backlogs. A reserve decline
285
+ does not close a stream or change registration readiness.
280
286
 
281
287
  Each reserve decline records the Flow type through node:util debuglog under
282
288
  dex:pull (enable with NODE_DEBUG=dex:pull). Export the cumulative
283
289
  `pullReservedRpcDeclines` Worker value to distinguish reserve pressure from
284
- full-capacity rejections. The count excludes full-capacity rejections and
285
- unknown names, never resets, and remains available after shutdown. Listening
286
- Workers return zero.
290
+ full-capacity rejections. The count excludes full-capacity rejections and unknown
291
+ names. It counts decline events, including repeated declines of the same Step
292
+ dispatch while Dex retries it. Read its rate to assess reserve pressure. It never
293
+ resets and remains available after shutdown.
294
+ Listening Workers return zero.
287
295
 
288
296
  ### Canceling Step executions
289
297
 
@@ -36,7 +36,7 @@ export declare enum PollWorkerTaskRejectReason {
36
36
  }
37
37
  /**
38
38
  * Distinguishes no available Worker, a disconnected Worker, and a missing Step or RPC registration.
39
- * Go Server internals; server-zd does not serve or persist them.
39
+ * Go persists; server-zd does not.
40
40
  */
41
41
  export declare enum DispatchTaskErrorReason {
42
42
  DISPATCH_TASK_ERROR_REASON_UNSPECIFIED = 0,
@@ -481,6 +481,8 @@ export interface DispatchTaskResponse {
481
481
  servedByAppWorkerId: string;
482
482
  /** Identifies a Worker that rejected the task's Step type or RPC name. */
483
483
  rejectedByAppWorkerId: string;
484
+ /** Actual queue served; absent on older matching nodes, so consumers may infer it from Worker IDs. */
485
+ queueSource: PullRoutingSource;
484
486
  }
485
487
  /**
486
488
  * Reports a failure before Dex receives a Worker result.
@@ -1293,6 +1295,7 @@ export interface ServiceErrorResponse {
1293
1295
  originalWorkerErrorType: string;
1294
1296
  originalWorkerErrorStatus: number;
1295
1297
  originalWorkerErrorStackTrace: string;
1298
+ dispatchTaskErrorReason: DispatchTaskErrorReason;
1296
1299
  }
1297
1300
  export interface WorkerErrorResponse {
1298
1301
  detail: string;
@@ -1307,6 +1310,7 @@ export interface InternalActivityError {
1307
1310
  workerGrpcStatus: number;
1308
1311
  workerError: InternalWorkerError | undefined;
1309
1312
  pullRouting: PullRouting | undefined;
1313
+ dispatchTaskErrorReason: DispatchTaskErrorReason;
1310
1314
  }
1311
1315
  export interface InternalWorkerError {
1312
1316
  detail: string;
@@ -44,7 +44,7 @@ export var PollWorkerTaskRejectReason;
44
44
  })(PollWorkerTaskRejectReason || (PollWorkerTaskRejectReason = {}));
45
45
  /**
46
46
  * Distinguishes no available Worker, a disconnected Worker, and a missing Step or RPC registration.
47
- * Go Server internals; server-zd does not serve or persist them.
47
+ * Go persists; server-zd does not.
48
48
  */
49
49
  export var DispatchTaskErrorReason;
50
50
  (function (DispatchTaskErrorReason) {
@@ -1337,7 +1337,7 @@ export const DispatchTaskRequest = {
1337
1337
  },
1338
1338
  };
1339
1339
  function createBaseDispatchTaskResponse() {
1340
- return { output: undefined, servedByAppWorkerId: "", rejectedByAppWorkerId: "" };
1340
+ return { output: undefined, servedByAppWorkerId: "", rejectedByAppWorkerId: "", queueSource: 0 };
1341
1341
  }
1342
1342
  export const DispatchTaskResponse = {
1343
1343
  encode(message, writer = new BinaryWriter()) {
@@ -1370,6 +1370,9 @@ export const DispatchTaskResponse = {
1370
1370
  if (message.rejectedByAppWorkerId !== "") {
1371
1371
  writer.uint32(74).string(message.rejectedByAppWorkerId);
1372
1372
  }
1373
+ if (message.queueSource !== 0) {
1374
+ writer.uint32(80).int32(message.queueSource);
1375
+ }
1373
1376
  return writer;
1374
1377
  },
1375
1378
  decode(input, length) {
@@ -1442,6 +1445,13 @@ export const DispatchTaskResponse = {
1442
1445
  message.rejectedByAppWorkerId = reader.string();
1443
1446
  continue;
1444
1447
  }
1448
+ case 10: {
1449
+ if (tag !== 80) {
1450
+ break;
1451
+ }
1452
+ message.queueSource = reader.int32();
1453
+ continue;
1454
+ }
1445
1455
  }
1446
1456
  if ((tag & 7) === 4 || tag === 0) {
1447
1457
  break;
@@ -1501,6 +1511,7 @@ export const DispatchTaskResponse = {
1501
1511
  }
1502
1512
  message.servedByAppWorkerId = object.servedByAppWorkerId ?? "";
1503
1513
  message.rejectedByAppWorkerId = object.rejectedByAppWorkerId ?? "";
1514
+ message.queueSource = object.queueSource ?? 0;
1504
1515
  return message;
1505
1516
  },
1506
1517
  };
@@ -9720,6 +9731,7 @@ function createBaseServiceErrorResponse() {
9720
9731
  originalWorkerErrorType: "",
9721
9732
  originalWorkerErrorStatus: 0,
9722
9733
  originalWorkerErrorStackTrace: "",
9734
+ dispatchTaskErrorReason: 0,
9723
9735
  };
9724
9736
  }
9725
9737
  export const ServiceErrorResponse = {
@@ -9742,6 +9754,9 @@ export const ServiceErrorResponse = {
9742
9754
  if (message.originalWorkerErrorStackTrace !== "") {
9743
9755
  writer.uint32(50).string(message.originalWorkerErrorStackTrace);
9744
9756
  }
9757
+ if (message.dispatchTaskErrorReason !== 0) {
9758
+ writer.uint32(56).int32(message.dispatchTaskErrorReason);
9759
+ }
9745
9760
  return writer;
9746
9761
  },
9747
9762
  decode(input, length) {
@@ -9793,6 +9808,13 @@ export const ServiceErrorResponse = {
9793
9808
  message.originalWorkerErrorStackTrace = reader.string();
9794
9809
  continue;
9795
9810
  }
9811
+ case 7: {
9812
+ if (tag !== 56) {
9813
+ break;
9814
+ }
9815
+ message.dispatchTaskErrorReason = reader.int32();
9816
+ continue;
9817
+ }
9796
9818
  }
9797
9819
  if ((tag & 7) === 4 || tag === 0) {
9798
9820
  break;
@@ -9812,6 +9834,7 @@ export const ServiceErrorResponse = {
9812
9834
  message.originalWorkerErrorType = object.originalWorkerErrorType ?? "";
9813
9835
  message.originalWorkerErrorStatus = object.originalWorkerErrorStatus ?? 0;
9814
9836
  message.originalWorkerErrorStackTrace = object.originalWorkerErrorStackTrace ?? "";
9837
+ message.dispatchTaskErrorReason = object.dispatchTaskErrorReason ?? 0;
9815
9838
  return message;
9816
9839
  },
9817
9840
  };
@@ -9901,7 +9924,13 @@ export const WorkerErrorResponse = {
9901
9924
  },
9902
9925
  };
9903
9926
  function createBaseInternalActivityError() {
9904
- return { serverDetail: "", workerGrpcStatus: 0, workerError: undefined, pullRouting: undefined };
9927
+ return {
9928
+ serverDetail: "",
9929
+ workerGrpcStatus: 0,
9930
+ workerError: undefined,
9931
+ pullRouting: undefined,
9932
+ dispatchTaskErrorReason: 0,
9933
+ };
9905
9934
  }
9906
9935
  export const InternalActivityError = {
9907
9936
  encode(message, writer = new BinaryWriter()) {
@@ -9917,6 +9946,9 @@ export const InternalActivityError = {
9917
9946
  if (message.pullRouting !== undefined) {
9918
9947
  PullRouting.encode(message.pullRouting, writer.uint32(34).fork()).join();
9919
9948
  }
9949
+ if (message.dispatchTaskErrorReason !== 0) {
9950
+ writer.uint32(40).int32(message.dispatchTaskErrorReason);
9951
+ }
9920
9952
  return writer;
9921
9953
  },
9922
9954
  decode(input, length) {
@@ -9954,6 +9986,13 @@ export const InternalActivityError = {
9954
9986
  message.pullRouting = PullRouting.decode(reader, reader.uint32());
9955
9987
  continue;
9956
9988
  }
9989
+ case 5: {
9990
+ if (tag !== 40) {
9991
+ break;
9992
+ }
9993
+ message.dispatchTaskErrorReason = reader.int32();
9994
+ continue;
9995
+ }
9957
9996
  }
9958
9997
  if ((tag & 7) === 4 || tag === 0) {
9959
9998
  break;
@@ -9975,6 +10014,7 @@ export const InternalActivityError = {
9975
10014
  message.pullRouting = (object.pullRouting !== undefined && object.pullRouting !== null)
9976
10015
  ? PullRouting.fromPartial(object.pullRouting)
9977
10016
  : undefined;
10017
+ message.dispatchTaskErrorReason = object.dispatchTaskErrorReason ?? 0;
9978
10018
  return message;
9979
10019
  },
9980
10020
  };