@resolveio/server-lib 20.15.9 → 22.0.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.
@@ -33,13 +33,20 @@ var WorkerDispatcherManager = /** @class */ (function () {
33
33
  this._clientRequests = {};
34
34
  this._pendingTasks = new Map();
35
35
  this._debugNoWorkerTaskIds = new Set();
36
+ this._debugCodexTaskIds = new Set();
36
37
  this._taskTimings = new Map();
37
38
  this._dispatchRetryTimer = null;
38
39
  this._dispatchRetryDelayMs = 25;
40
+ this._nonCodexReserve = 0;
41
+ this._publicationWorkerIndexes = null;
42
+ this._publicationWorkerInstances = null;
43
+ this._codexWorkerIndexes = null;
44
+ this._codexWorkerInstances = null;
39
45
  this.MAX_CONCURRENCY = 10;
40
46
  this.WORKER_TASK_LOG_THRESHOLD_MS = 200;
41
47
  this.WORKER_PUBLICATION_SLOW_MS = 20000;
42
48
  this._workerTaskDebug = false;
49
+ this._aiWorkerDebug = false;
43
50
  }
44
51
  WorkerDispatcherManager.create = function (websocketManager, methodManager) {
45
52
  var workerDispatcherManager = new WorkerDispatcherManager();
@@ -47,14 +54,28 @@ var WorkerDispatcherManager = /** @class */ (function () {
47
54
  return workerDispatcherManager;
48
55
  };
49
56
  WorkerDispatcherManager.prototype.initialize = function (websocketManager, methodManager) {
50
- var _a, _b;
57
+ var _a, _b, _c;
51
58
  this._websocketManager = websocketManager;
52
59
  this._methodManager = methodManager;
53
60
  this._workerTaskDebug = this.parseDebugFlag((_a = process.env.WORKER_TASK_DEBUG) !== null && _a !== void 0 ? _a : process.env.WORKER_DISPATCH_DEBUG);
61
+ this._aiWorkerDebug = this.parseDebugFlag(process.env.AI_ASSISTANT_WORKER_DEBUG);
54
62
  var slowPublicationMs = parseInt((_b = process.env.WORKER_PUBLICATION_SLOW_MS) !== null && _b !== void 0 ? _b : '', 10);
55
63
  if (!Number.isNaN(slowPublicationMs) && slowPublicationMs > 0) {
56
64
  this.WORKER_PUBLICATION_SLOW_MS = slowPublicationMs;
57
65
  }
66
+ this._nonCodexReserve = this.parsePositiveInt((_c = process.env.WORKER_NON_CODEX_RESERVE) !== null && _c !== void 0 ? _c : process.env.WORKER_RESERVED_SLOTS, 0);
67
+ this._publicationWorkerIndexes = this.parseWorkerSelector(process.env.PUBLICATION_WORKER_INDEX
68
+ || process.env.SUBSCRIPTION_WORKER_INDEX
69
+ || process.env.WORKER_PUBLICATION_INDEX);
70
+ this._publicationWorkerInstances = this.parseWorkerSelector(process.env.PUBLICATION_WORKER_INSTANCE
71
+ || process.env.SUBSCRIPTION_WORKER_INSTANCE
72
+ || process.env.WORKER_PUBLICATION_INSTANCE);
73
+ this._codexWorkerIndexes = this.parseWorkerSelector(process.env.AI_ASSISTANT_CODEX_WORKER_INDEX
74
+ || process.env.CODEX_WORKER_INDEX
75
+ || process.env.WORKER_CODEX_INDEX);
76
+ this._codexWorkerInstances = this.parseWorkerSelector(process.env.AI_ASSISTANT_CODEX_WORKER_INSTANCE
77
+ || process.env.CODEX_WORKER_INSTANCE
78
+ || process.env.WORKER_CODEX_INSTANCE);
58
79
  };
59
80
  WorkerDispatcherManager.prototype.parseDebugFlag = function (value) {
60
81
  if (value === true) {
@@ -72,6 +93,102 @@ var WorkerDispatcherManager = /** @class */ (function () {
72
93
  }
73
94
  return false;
74
95
  };
96
+ WorkerDispatcherManager.prototype.parsePositiveInt = function (value, fallback) {
97
+ var parsed = parseInt(value !== null && value !== void 0 ? value : '', 10);
98
+ if (Number.isNaN(parsed) || parsed < 0) {
99
+ return fallback;
100
+ }
101
+ return parsed;
102
+ };
103
+ WorkerDispatcherManager.prototype.parseWorkerSelector = function (value) {
104
+ var e_1, _a, e_2, _b, e_3, _c;
105
+ if (value === null || value === undefined) {
106
+ return null;
107
+ }
108
+ var parts = [];
109
+ if (Array.isArray(value)) {
110
+ try {
111
+ for (var value_1 = __values(value), value_1_1 = value_1.next(); !value_1_1.done; value_1_1 = value_1.next()) {
112
+ var item = value_1_1.value;
113
+ var entry = String(item !== null && item !== void 0 ? item : '').split(',');
114
+ try {
115
+ for (var entry_1 = (e_2 = void 0, __values(entry)), entry_1_1 = entry_1.next(); !entry_1_1.done; entry_1_1 = entry_1.next()) {
116
+ var chunk = entry_1_1.value;
117
+ var trimmed = String(chunk !== null && chunk !== void 0 ? chunk : '').trim();
118
+ if (trimmed) {
119
+ parts.push(trimmed);
120
+ }
121
+ }
122
+ }
123
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
124
+ finally {
125
+ try {
126
+ if (entry_1_1 && !entry_1_1.done && (_b = entry_1.return)) _b.call(entry_1);
127
+ }
128
+ finally { if (e_2) throw e_2.error; }
129
+ }
130
+ }
131
+ }
132
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
133
+ finally {
134
+ try {
135
+ if (value_1_1 && !value_1_1.done && (_a = value_1.return)) _a.call(value_1);
136
+ }
137
+ finally { if (e_1) throw e_1.error; }
138
+ }
139
+ }
140
+ else {
141
+ var entry = String(value !== null && value !== void 0 ? value : '').split(',');
142
+ try {
143
+ for (var entry_2 = __values(entry), entry_2_1 = entry_2.next(); !entry_2_1.done; entry_2_1 = entry_2.next()) {
144
+ var chunk = entry_2_1.value;
145
+ var trimmed = String(chunk !== null && chunk !== void 0 ? chunk : '').trim();
146
+ if (trimmed) {
147
+ parts.push(trimmed);
148
+ }
149
+ }
150
+ }
151
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
152
+ finally {
153
+ try {
154
+ if (entry_2_1 && !entry_2_1.done && (_c = entry_2.return)) _c.call(entry_2);
155
+ }
156
+ finally { if (e_3) throw e_3.error; }
157
+ }
158
+ }
159
+ if (!parts.length) {
160
+ return null;
161
+ }
162
+ return new Set(parts);
163
+ };
164
+ WorkerDispatcherManager.prototype.selectorToArray = function (value) {
165
+ if (!value) {
166
+ return null;
167
+ }
168
+ return Array.from(value.values());
169
+ };
170
+ WorkerDispatcherManager.prototype.hasWorkerSelector = function (indexes, instances) {
171
+ return !!(indexes && indexes.size) || !!(instances && instances.size);
172
+ };
173
+ WorkerDispatcherManager.prototype.workerMatchesSelector = function (worker, indexes, instances) {
174
+ if (!this.hasWorkerSelector(indexes, instances)) {
175
+ return false;
176
+ }
177
+ var normalizedIndex = this.normalizeWorkerIndex(worker.workerIndex);
178
+ var normalizedInstance = this.normalizeWorkerIndex(worker.workerInstance);
179
+ var indexMatch = indexes ? (normalizedIndex ? indexes.has(normalizedIndex) : false) : true;
180
+ var instanceMatch = instances ? (normalizedInstance ? instances.has(normalizedInstance) : false) : true;
181
+ return indexMatch && instanceMatch;
182
+ };
183
+ WorkerDispatcherManager.prototype.resolveTaskQueue = function (methodName) {
184
+ var _a;
185
+ var method = (_a = this._methodManager) === null || _a === void 0 ? void 0 : _a.getMethod(methodName);
186
+ var queue = method === null || method === void 0 ? void 0 : method.workerQueue;
187
+ if (queue === 'publication' || queue === 'codex') {
188
+ return queue;
189
+ }
190
+ return 'default';
191
+ };
75
192
  WorkerDispatcherManager.prototype.summarizePublicationValue = function (value) {
76
193
  if (value === null || value === undefined) {
77
194
  return value;
@@ -374,41 +491,51 @@ var WorkerDispatcherManager = /** @class */ (function () {
374
491
  * The main loop that assigns tasks from _taskQueue to any worker that has capacity.
375
492
  */
376
493
  WorkerDispatcherManager.prototype.dispatchQueue = function () {
494
+ var e_4, _a;
495
+ var _this = this;
377
496
  if (!this._taskQueue.length) {
378
497
  return;
379
498
  }
380
499
  if (!this._workers.length) {
381
500
  return;
382
501
  }
502
+ var priorityMatchers = [
503
+ function (task) { return _this.resolveTaskQueue(task.method) === 'publication'; },
504
+ function (task) { return _this.resolveTaskQueue(task.method) === 'default'; },
505
+ function (task) { return _this.resolveTaskQueue(task.method) === 'codex'; }
506
+ ];
507
+ var tryAssignTask = function (matcher) {
508
+ for (var i = 0; i < _this._taskQueue.length; i++) {
509
+ var task = _this._taskQueue[i];
510
+ if (!matcher(task)) {
511
+ continue;
512
+ }
513
+ var targetWorker = _this.findWorkerForTask(task);
514
+ if (targetWorker) {
515
+ _this._taskQueue.splice(i, 1);
516
+ _this.assignTaskToWorker(targetWorker, task);
517
+ return true;
518
+ }
519
+ }
520
+ return false;
521
+ };
383
522
  while (this._taskQueue.length > 0) {
384
523
  var assigned = false;
385
- var hasPublicationTask = this._taskQueue.some(function (task) { return task.method === 'runPublication'; });
386
- if (hasPublicationTask) {
387
- for (var i = 0; i < this._taskQueue.length; i++) {
388
- var task = this._taskQueue[i];
389
- if (task.method !== 'runPublication') {
390
- continue;
391
- }
392
- var targetWorker = this.findWorkerForTask(task);
393
- if (targetWorker) {
394
- this._taskQueue.splice(i, 1);
395
- this.assignTaskToWorker(targetWorker, task);
524
+ try {
525
+ for (var priorityMatchers_1 = (e_4 = void 0, __values(priorityMatchers)), priorityMatchers_1_1 = priorityMatchers_1.next(); !priorityMatchers_1_1.done; priorityMatchers_1_1 = priorityMatchers_1.next()) {
526
+ var matcher = priorityMatchers_1_1.value;
527
+ if (tryAssignTask(matcher)) {
396
528
  assigned = true;
397
529
  break;
398
530
  }
399
531
  }
400
532
  }
401
- if (!assigned) {
402
- for (var i = 0; i < this._taskQueue.length; i++) {
403
- var task = this._taskQueue[i];
404
- var targetWorker = this.findWorkerForTask(task);
405
- if (targetWorker) {
406
- this._taskQueue.splice(i, 1);
407
- this.assignTaskToWorker(targetWorker, task);
408
- assigned = true;
409
- break;
410
- }
533
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
534
+ finally {
535
+ try {
536
+ if (priorityMatchers_1_1 && !priorityMatchers_1_1.done && (_a = priorityMatchers_1.return)) _a.call(priorityMatchers_1);
411
537
  }
538
+ finally { if (e_4) throw e_4.error; }
412
539
  }
413
540
  if (!assigned) {
414
541
  this.logNoWorkerAvailability();
@@ -437,21 +564,83 @@ var WorkerDispatcherManager = /** @class */ (function () {
437
564
  WorkerDispatcherManager.prototype.findWorkerForTask = function (task) {
438
565
  var _this = this;
439
566
  var method = this._methodManager.getMethod(task.method);
567
+ var taskQueue = this.resolveTaskQueue(task.method);
440
568
  var methodLimit = method && method.maxConcurrency && method.maxConcurrency > 0 ? method.maxConcurrency : null;
441
569
  var methodLimitPerInstance = method && method.maxConcurrencyPerInstance && method.maxConcurrencyPerInstance > 0
442
570
  ? method.maxConcurrencyPerInstance
443
571
  : null;
444
572
  var targetWorkerIndex = this.normalizeWorkerIndex(method === null || method === void 0 ? void 0 : method.targetWorkerIndex);
445
573
  var targetWorkerInstance = this.normalizeWorkerIndex(method === null || method === void 0 ? void 0 : method.targetWorkerInstance);
574
+ var hasExplicitTarget = !!targetWorkerIndex || !!targetWorkerInstance;
446
575
  var preferNonZero = !targetWorkerIndex;
576
+ var debugCodex = this._aiWorkerDebug && taskQueue === 'codex';
577
+ var debugState = debugCodex ? {
578
+ taskId: task.taskId,
579
+ method: task.method,
580
+ queueDepth: this._taskQueue.length,
581
+ targetWorkerIndex: targetWorkerIndex || null,
582
+ targetWorkerInstance: targetWorkerInstance || null,
583
+ workerCount: this._workers.length,
584
+ publicationSelector: {
585
+ indexes: this.selectorToArray(this._publicationWorkerIndexes),
586
+ instances: this.selectorToArray(this._publicationWorkerInstances)
587
+ },
588
+ codexSelector: {
589
+ indexes: this.selectorToArray(this._codexWorkerIndexes),
590
+ instances: this.selectorToArray(this._codexWorkerInstances)
591
+ },
592
+ maxConcurrency: this.MAX_CONCURRENCY,
593
+ nonCodexReserve: this._nonCodexReserve
594
+ } : null;
447
595
  var candidates = this._workers.filter(function (x) { return x.activeTasks.length < _this.MAX_CONCURRENCY; });
596
+ if (debugState) {
597
+ debugState.candidatesInitial = candidates.length;
598
+ }
599
+ var hasPublicationSelector = this.hasWorkerSelector(this._publicationWorkerIndexes, this._publicationWorkerInstances);
600
+ if (hasPublicationSelector && !hasExplicitTarget) {
601
+ if (taskQueue === 'publication') {
602
+ candidates = candidates.filter(function (worker) {
603
+ return _this.workerMatchesSelector(worker, _this._publicationWorkerIndexes, _this._publicationWorkerInstances);
604
+ });
605
+ }
606
+ else {
607
+ candidates = candidates.filter(function (worker) {
608
+ return !_this.workerMatchesSelector(worker, _this._publicationWorkerIndexes, _this._publicationWorkerInstances);
609
+ });
610
+ }
611
+ }
612
+ if (debugState) {
613
+ debugState.candidatesAfterPublicationFilter = candidates.length;
614
+ debugState.hasPublicationSelector = hasPublicationSelector;
615
+ }
616
+ var hasCodexSelector = this.hasWorkerSelector(this._codexWorkerIndexes, this._codexWorkerInstances);
617
+ if (hasCodexSelector) {
618
+ if (taskQueue === 'codex') {
619
+ candidates = candidates.filter(function (worker) {
620
+ return _this.workerMatchesSelector(worker, _this._codexWorkerIndexes, _this._codexWorkerInstances);
621
+ });
622
+ }
623
+ else if (!hasExplicitTarget) {
624
+ candidates = candidates.filter(function (worker) {
625
+ return !_this.workerMatchesSelector(worker, _this._codexWorkerIndexes, _this._codexWorkerInstances);
626
+ });
627
+ }
628
+ }
629
+ if (debugState) {
630
+ debugState.candidatesAfterCodexFilter = candidates.length;
631
+ debugState.hasCodexSelector = hasCodexSelector;
632
+ }
448
633
  if (targetWorkerIndex) {
449
634
  candidates = candidates.filter(function (worker) { return _this.normalizeWorkerIndex(worker.workerIndex) === targetWorkerIndex; });
450
635
  }
451
636
  if (targetWorkerInstance) {
452
637
  candidates = candidates.filter(function (worker) { return _this.normalizeWorkerIndex(worker.workerInstance) === targetWorkerInstance; });
453
638
  }
639
+ if (debugState) {
640
+ debugState.candidatesAfterTargetFilter = candidates.length;
641
+ }
454
642
  if (!candidates.length) {
643
+ this.logCodexSelection(debugState, 'noCandidates');
455
644
  return null;
456
645
  }
457
646
  var eligible = candidates.filter(function (worker) {
@@ -478,7 +667,21 @@ var WorkerDispatcherManager = /** @class */ (function () {
478
667
  });
479
668
  return current < methodLimit;
480
669
  });
670
+ if (debugState) {
671
+ debugState.eligibleAfterLimits = eligible.length;
672
+ }
673
+ if (!eligible.length) {
674
+ this.logCodexSelection(debugState, 'limitsExceeded');
675
+ return null;
676
+ }
677
+ if (taskQueue === 'codex' && this._nonCodexReserve > 0) {
678
+ eligible = eligible.filter(function (worker) { return (_this.MAX_CONCURRENCY - worker.activeTasks.length) > _this._nonCodexReserve; });
679
+ }
680
+ if (debugState) {
681
+ debugState.eligibleAfterReserve = eligible.length;
682
+ }
481
683
  if (!eligible.length) {
684
+ this.logCodexSelection(debugState, 'reserveBlocked');
482
685
  return null;
483
686
  }
484
687
  eligible.sort(function (x, y) {
@@ -504,7 +707,29 @@ var WorkerDispatcherManager = /** @class */ (function () {
504
707
  var instY = _this.normalizeWorkerIndex(y.workerInstance) || '';
505
708
  return instX.localeCompare(instY, undefined, { numeric: true, sensitivity: 'base' });
506
709
  });
507
- return eligible[0];
710
+ var selected = eligible[0];
711
+ if (this._aiWorkerDebug && taskQueue === 'codex') {
712
+ console.log(new Date(), '[AI Worker Debug] codex worker selected', {
713
+ taskId: task.taskId,
714
+ method: task.method,
715
+ workerIndex: (selected === null || selected === void 0 ? void 0 : selected.workerIndex) || null,
716
+ workerInstance: (selected === null || selected === void 0 ? void 0 : selected.workerInstance) || null,
717
+ activeTasks: (selected === null || selected === void 0 ? void 0 : selected.activeTasks) ? selected.activeTasks.length : 0,
718
+ queueDepth: this._taskQueue.length
719
+ });
720
+ }
721
+ return selected;
722
+ };
723
+ WorkerDispatcherManager.prototype.logCodexSelection = function (debugState, reason) {
724
+ if (!debugState || !this._aiWorkerDebug) {
725
+ return;
726
+ }
727
+ var taskId = String(debugState.taskId || '');
728
+ if (!taskId || this._debugCodexTaskIds.has(taskId)) {
729
+ return;
730
+ }
731
+ this._debugCodexTaskIds.add(taskId);
732
+ console.warn(new Date(), '[AI Worker Debug] codex worker selection issue', __assign({ reason: reason }, debugState));
508
733
  };
509
734
  WorkerDispatcherManager.prototype.normalizeWorkerIndex = function (value) {
510
735
  if (value === null || value === undefined) {
@@ -643,7 +868,7 @@ var WorkerDispatcherManager = /** @class */ (function () {
643
868
  }
644
869
  };
645
870
  WorkerDispatcherManager.prototype.logNoWorkerAvailability = function () {
646
- var e_1, _a;
871
+ var e_5, _a;
647
872
  var _this = this;
648
873
  if (!this.shouldDebug()) {
649
874
  return;
@@ -686,12 +911,12 @@ var WorkerDispatcherManager = /** @class */ (function () {
686
911
  _loop_1(task);
687
912
  }
688
913
  }
689
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
914
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
690
915
  finally {
691
916
  try {
692
917
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
693
918
  }
694
- finally { if (e_1) throw e_1.error; }
919
+ finally { if (e_5) throw e_5.error; }
695
920
  }
696
921
  };
697
922
  WorkerDispatcherManager.prototype.shouldDebug = function () {