@camunda8/orchestration-cluster-api 10.0.0-alpha.20 → 10.0.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # [10.0.0-alpha.21](https://github.com/camunda/orchestration-cluster-api-js/compare/v10.0.0-alpha.20...v10.0.0-alpha.21) (2026-08-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **worker:** buffer start() until the transport is ready ([ad4d37f](https://github.com/camunda/orchestration-cluster-api-js/commit/ad4d37f6eeadffb89532af351bd80d404ffc2fde))
7
+ * **worker:** buffer start() until the transport is ready ([708b544](https://github.com/camunda/orchestration-cluster-api-js/commit/708b544f79ffec9ef9060de0dea21ac8ecb2b207)), closes [#401](https://github.com/camunda/orchestration-cluster-api-js/issues/401)
8
+
1
9
  # [10.0.0-alpha.20](https://github.com/camunda/orchestration-cluster-api-js/compare/v10.0.0-alpha.19...v10.0.0-alpha.20) (2026-08-02)
2
10
 
3
11
 
@@ -317,6 +317,50 @@ function createVariableSearchFetchPage(params) {
317
317
  };
318
318
  }
319
319
 
320
+ // src/runtime/workerStartGate.ts
321
+ var WorkerStartGate = class {
322
+ /**
323
+ * @param transportReady Resolves when the worker's transport can service polls.
324
+ * @param isStopped Reports whether the worker was stopped while the gate was buffering.
325
+ */
326
+ constructor(_transportReady, _isStopped) {
327
+ this._transportReady = _transportReady;
328
+ this._isStopped = _isStopped;
329
+ }
330
+ _transportReady;
331
+ _isStopped;
332
+ _requested = false;
333
+ /** True once a start request has been accepted and not since released. */
334
+ get requested() {
335
+ return this._requested;
336
+ }
337
+ /**
338
+ * Record a start request.
339
+ *
340
+ * The first accepted request invokes `onReady` once the transport resolves,
341
+ * and only if the worker has not been stopped in the meantime. If the
342
+ * transport fails to come up, `onError` is invoked and the gate is released so
343
+ * a later `start()` can retry.
344
+ *
345
+ * @returns `false` when the request was dropped as redundant.
346
+ */
347
+ request(onReady, onError) {
348
+ if (this._requested) return false;
349
+ this._requested = true;
350
+ void this._transportReady().then(
351
+ () => {
352
+ if (this._isStopped()) return;
353
+ onReady();
354
+ },
355
+ (err) => {
356
+ this._requested = false;
357
+ onError(err);
358
+ }
359
+ );
360
+ return true;
361
+ }
362
+ };
363
+
320
364
  // src/runtime/jobWorker.ts
321
365
  var JobActionReceipt = "JOB_ACTION_RECEIPT";
322
366
  var _workerCounter = 0;
@@ -333,6 +377,7 @@ var JobWorker = class {
333
377
  _inFlightActivation = null;
334
378
  // CancelablePromise-like
335
379
  _log;
380
+ _startGate;
336
381
  constructor(client2, cfg) {
337
382
  this._client = client2;
338
383
  this._cfg = {
@@ -353,6 +398,10 @@ var JobWorker = class {
353
398
  { maxBackoffTimeMs: cfg.maxBackoffTimeMs }
354
399
  ]);
355
400
  }
401
+ this._startGate = new WorkerStartGate(
402
+ () => Promise.resolve(),
403
+ () => this._stopped
404
+ );
356
405
  if (this._cfg.autoStart) this.start();
357
406
  }
358
407
  get name() {
@@ -364,10 +413,25 @@ var JobWorker = class {
364
413
  get stopped() {
365
414
  return this._stopped;
366
415
  }
416
+ /**
417
+ * Begin polling for jobs. Safe to call at any point: the request is buffered
418
+ * until the transport is ready, and redundant calls (including an explicit
419
+ * call on an `autoStart` worker) are dropped rather than starting a second
420
+ * poll loop. Once the worker is stopped, `start()` is a no-op.
421
+ */
367
422
  start() {
368
423
  if (this._stopped) return;
369
- if (this._pollTimer) return;
424
+ const accepted = this._startGate.request(
425
+ () => this._beginPolling(),
426
+ (err) => this._log.error("worker.start.transportError", err)
427
+ );
428
+ if (!accepted) {
429
+ this._log.debug("worker.start.alreadyRequested");
430
+ return;
431
+ }
370
432
  this._log.info("worker.start");
433
+ }
434
+ _beginPolling() {
371
435
  const jitterMax = this._cfg.startupJitterMaxSeconds ?? 0;
372
436
  if (jitterMax > 0) {
373
437
  const jitterMs = Math.floor(Math.random() * jitterMax * 1e3);
@@ -4783,7 +4847,7 @@ function installAuthInterceptor(client2, getStrategy, getAuthHeaders) {
4783
4847
  }
4784
4848
 
4785
4849
  // src/runtime/version.ts
4786
- var packageVersion = "10.0.0-alpha.20";
4850
+ var packageVersion = "10.0.0-alpha.21";
4787
4851
 
4788
4852
  // src/runtime/supportLogger.ts
4789
4853
  var NoopSupportLogger = class {
@@ -5890,6 +5954,7 @@ var ThreadedJobWorker = class {
5890
5954
  _inFlightActivation = null;
5891
5955
  _log;
5892
5956
  _jobQueue = [];
5957
+ _startGate;
5893
5958
  constructor(client2, pool, cfg) {
5894
5959
  this._client = client2;
5895
5960
  this._pool = pool;
@@ -5906,6 +5971,10 @@ var ThreadedJobWorker = class {
5906
5971
  this._name = cfg.workerName || `threaded-worker-${cfg.jobType}-${++_workerCounter2}`;
5907
5972
  this._log = this._client.logger().scope(`worker:${this._name}`);
5908
5973
  this._pool.onThreadReady = () => this._drainQueue();
5974
+ this._startGate = new WorkerStartGate(
5975
+ () => this._pool.ready,
5976
+ () => this._stopped
5977
+ );
5909
5978
  if (this._cfg.autoStart) this.start();
5910
5979
  }
5911
5980
  get name() {
@@ -5929,10 +5998,25 @@ var ThreadedJobWorker = class {
5929
5998
  get ready() {
5930
5999
  return this._pool.ready;
5931
6000
  }
6001
+ /**
6002
+ * Begin polling for jobs. Safe to call at any point: the request is buffered
6003
+ * until the shared thread pool is ready, and redundant calls (including an
6004
+ * explicit call on an `autoStart` worker) are dropped rather than starting a
6005
+ * second poll loop. Once the worker is stopped, `start()` is a no-op.
6006
+ */
5932
6007
  start() {
5933
6008
  if (this._stopped) return;
5934
- if (this._pollTimer) return;
6009
+ const accepted = this._startGate.request(
6010
+ () => this._beginPolling(),
6011
+ (err) => this._log.error("worker.start.transportError", err)
6012
+ );
6013
+ if (!accepted) {
6014
+ this._log.debug("worker.start.alreadyRequested");
6015
+ return;
6016
+ }
5935
6017
  this._log.info("worker.start");
6018
+ }
6019
+ _beginPolling() {
5936
6020
  const jitterMax = this._cfg.startupJitterMaxSeconds ?? 0;
5937
6021
  if (jitterMax > 0) {
5938
6022
  const jitterMs = Math.floor(Math.random() * jitterMax * 1e3);
@@ -19103,4 +19187,4 @@ export {
19103
19187
  withTimeoutTE,
19104
19188
  eventuallyTE
19105
19189
  };
19106
- //# sourceMappingURL=chunk-QZDJRG7I.js.map
19190
+ //# sourceMappingURL=chunk-7SBI6PGB.js.map