@trigger.dev/core 4.0.1 → 4.0.3

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 (145) hide show
  1. package/dist/commonjs/v3/errors.d.ts +1 -0
  2. package/dist/commonjs/v3/errors.js +35 -2
  3. package/dist/commonjs/v3/errors.js.map +1 -1
  4. package/dist/commonjs/v3/heartbeats/api.d.ts +14 -0
  5. package/dist/commonjs/v3/heartbeats/api.js +58 -0
  6. package/dist/commonjs/v3/heartbeats/api.js.map +1 -0
  7. package/dist/commonjs/v3/heartbeats/manager.d.ts +16 -0
  8. package/dist/commonjs/v3/heartbeats/manager.js +72 -0
  9. package/dist/commonjs/v3/heartbeats/manager.js.map +1 -0
  10. package/dist/commonjs/v3/heartbeats/types.d.ts +7 -0
  11. package/dist/commonjs/v3/heartbeats/types.js +3 -0
  12. package/dist/commonjs/v3/heartbeats/types.js.map +1 -0
  13. package/dist/commonjs/v3/heartbeats-api.d.ts +3 -0
  14. package/dist/commonjs/v3/heartbeats-api.js +9 -0
  15. package/dist/commonjs/v3/heartbeats-api.js.map +1 -0
  16. package/dist/commonjs/v3/index.d.ts +1 -0
  17. package/dist/commonjs/v3/index.js +1 -0
  18. package/dist/commonjs/v3/index.js.map +1 -1
  19. package/dist/commonjs/v3/links.d.ts +1 -0
  20. package/dist/commonjs/v3/links.js +1 -0
  21. package/dist/commonjs/v3/links.js.map +1 -1
  22. package/dist/commonjs/v3/runEngineWorker/index.d.ts +1 -0
  23. package/dist/commonjs/v3/runEngineWorker/index.js +1 -0
  24. package/dist/commonjs/v3/runEngineWorker/index.js.map +1 -1
  25. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.d.ts +71 -0
  26. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.js +316 -0
  27. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.js.map +1 -0
  28. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.test.d.ts +1 -0
  29. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.test.js +589 -0
  30. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPool.test.js.map +1 -0
  31. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPoolMetrics.d.ts +43 -0
  32. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPoolMetrics.js +131 -0
  33. package/dist/commonjs/v3/runEngineWorker/supervisor/consumerPoolMetrics.js.map +1 -0
  34. package/dist/commonjs/v3/runEngineWorker/supervisor/http.d.ts +2 -0
  35. package/dist/commonjs/v3/runEngineWorker/supervisor/queueConsumer.d.ts +7 -4
  36. package/dist/commonjs/v3/runEngineWorker/supervisor/queueConsumer.js.map +1 -1
  37. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.d.ts +76 -0
  38. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.js +161 -0
  39. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.js.map +1 -0
  40. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.d.ts +1 -0
  41. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.js +293 -0
  42. package/dist/commonjs/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.js.map +1 -0
  43. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.d.ts +67 -0
  44. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.js +153 -0
  45. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.js.map +1 -0
  46. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.test.d.ts +1 -0
  47. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.test.js +235 -0
  48. package/dist/commonjs/v3/runEngineWorker/supervisor/scalingStrategies.test.js.map +1 -0
  49. package/dist/commonjs/v3/runEngineWorker/supervisor/schemas.d.ts +6 -0
  50. package/dist/commonjs/v3/runEngineWorker/supervisor/session.d.ts +5 -2
  51. package/dist/commonjs/v3/runEngineWorker/supervisor/session.js +14 -8
  52. package/dist/commonjs/v3/runEngineWorker/supervisor/session.js.map +1 -1
  53. package/dist/commonjs/v3/runEngineWorker/workload/http.d.ts +81 -111
  54. package/dist/commonjs/v3/runEngineWorker/workload/http.js +36 -14
  55. package/dist/commonjs/v3/runEngineWorker/workload/http.js.map +1 -1
  56. package/dist/commonjs/v3/runEngineWorker/workload/schemas.d.ts +3 -0
  57. package/dist/commonjs/v3/schemas/api.d.ts +144 -0
  58. package/dist/commonjs/v3/schemas/api.js +11 -3
  59. package/dist/commonjs/v3/schemas/api.js.map +1 -1
  60. package/dist/commonjs/v3/schemas/checkpoints.d.ts +3 -0
  61. package/dist/commonjs/v3/schemas/runEngine.d.ts +3 -0
  62. package/dist/commonjs/v3/schemas/runEngine.js +1 -0
  63. package/dist/commonjs/v3/schemas/runEngine.js.map +1 -1
  64. package/dist/commonjs/v3/utils/globals.d.ts +2 -0
  65. package/dist/commonjs/v3/utils/globals.js.map +1 -1
  66. package/dist/commonjs/v3/utils/ioSerialization.d.ts +1 -0
  67. package/dist/commonjs/v3/utils/ioSerialization.js +92 -3
  68. package/dist/commonjs/v3/utils/ioSerialization.js.map +1 -1
  69. package/dist/commonjs/v3/workers/index.d.ts +1 -0
  70. package/dist/commonjs/v3/workers/index.js +3 -1
  71. package/dist/commonjs/v3/workers/index.js.map +1 -1
  72. package/dist/commonjs/version.js +1 -1
  73. package/dist/esm/v3/errors.d.ts +1 -0
  74. package/dist/esm/v3/errors.js +34 -2
  75. package/dist/esm/v3/errors.js.map +1 -1
  76. package/dist/esm/v3/heartbeats/api.d.ts +14 -0
  77. package/dist/esm/v3/heartbeats/api.js +54 -0
  78. package/dist/esm/v3/heartbeats/api.js.map +1 -0
  79. package/dist/esm/v3/heartbeats/manager.d.ts +16 -0
  80. package/dist/esm/v3/heartbeats/manager.js +68 -0
  81. package/dist/esm/v3/heartbeats/manager.js.map +1 -0
  82. package/dist/esm/v3/heartbeats/types.d.ts +7 -0
  83. package/dist/esm/v3/heartbeats/types.js +2 -0
  84. package/dist/esm/v3/heartbeats/types.js.map +1 -0
  85. package/dist/esm/v3/heartbeats-api.d.ts +3 -0
  86. package/dist/esm/v3/heartbeats-api.js +6 -0
  87. package/dist/esm/v3/heartbeats-api.js.map +1 -0
  88. package/dist/esm/v3/index.d.ts +1 -0
  89. package/dist/esm/v3/index.js +1 -0
  90. package/dist/esm/v3/index.js.map +1 -1
  91. package/dist/esm/v3/links.d.ts +1 -0
  92. package/dist/esm/v3/links.js +1 -0
  93. package/dist/esm/v3/links.js.map +1 -1
  94. package/dist/esm/v3/runEngineWorker/index.d.ts +1 -0
  95. package/dist/esm/v3/runEngineWorker/index.js +1 -0
  96. package/dist/esm/v3/runEngineWorker/index.js.map +1 -1
  97. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.d.ts +71 -0
  98. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.js +312 -0
  99. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.js.map +1 -0
  100. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.test.d.ts +1 -0
  101. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.test.js +587 -0
  102. package/dist/esm/v3/runEngineWorker/supervisor/consumerPool.test.js.map +1 -0
  103. package/dist/esm/v3/runEngineWorker/supervisor/consumerPoolMetrics.d.ts +43 -0
  104. package/dist/esm/v3/runEngineWorker/supervisor/consumerPoolMetrics.js +127 -0
  105. package/dist/esm/v3/runEngineWorker/supervisor/consumerPoolMetrics.js.map +1 -0
  106. package/dist/esm/v3/runEngineWorker/supervisor/http.d.ts +2 -0
  107. package/dist/esm/v3/runEngineWorker/supervisor/queueConsumer.d.ts +7 -4
  108. package/dist/esm/v3/runEngineWorker/supervisor/queueConsumer.js.map +1 -1
  109. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.d.ts +76 -0
  110. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.js +157 -0
  111. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.js.map +1 -0
  112. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.d.ts +1 -0
  113. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.js +291 -0
  114. package/dist/esm/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.js.map +1 -0
  115. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.d.ts +67 -0
  116. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.js +146 -0
  117. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.js.map +1 -0
  118. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.test.d.ts +1 -0
  119. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.test.js +233 -0
  120. package/dist/esm/v3/runEngineWorker/supervisor/scalingStrategies.test.js.map +1 -0
  121. package/dist/esm/v3/runEngineWorker/supervisor/schemas.d.ts +6 -0
  122. package/dist/esm/v3/runEngineWorker/supervisor/session.d.ts +5 -2
  123. package/dist/esm/v3/runEngineWorker/supervisor/session.js +14 -8
  124. package/dist/esm/v3/runEngineWorker/supervisor/session.js.map +1 -1
  125. package/dist/esm/v3/runEngineWorker/workload/http.d.ts +81 -111
  126. package/dist/esm/v3/runEngineWorker/workload/http.js +37 -15
  127. package/dist/esm/v3/runEngineWorker/workload/http.js.map +1 -1
  128. package/dist/esm/v3/runEngineWorker/workload/schemas.d.ts +3 -0
  129. package/dist/esm/v3/schemas/api.d.ts +144 -0
  130. package/dist/esm/v3/schemas/api.js +8 -0
  131. package/dist/esm/v3/schemas/api.js.map +1 -1
  132. package/dist/esm/v3/schemas/checkpoints.d.ts +3 -0
  133. package/dist/esm/v3/schemas/runEngine.d.ts +3 -0
  134. package/dist/esm/v3/schemas/runEngine.js +1 -0
  135. package/dist/esm/v3/schemas/runEngine.js.map +1 -1
  136. package/dist/esm/v3/utils/globals.d.ts +2 -0
  137. package/dist/esm/v3/utils/globals.js.map +1 -1
  138. package/dist/esm/v3/utils/ioSerialization.d.ts +1 -0
  139. package/dist/esm/v3/utils/ioSerialization.js +92 -3
  140. package/dist/esm/v3/utils/ioSerialization.js.map +1 -1
  141. package/dist/esm/v3/workers/index.d.ts +1 -0
  142. package/dist/esm/v3/workers/index.js +1 -0
  143. package/dist/esm/v3/workers/index.js.map +1 -1
  144. package/dist/esm/version.js +1 -1
  145. package/package.json +1 -1
@@ -0,0 +1,291 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { QueueMetricsProcessor } from "./queueMetricsProcessor.js";
3
+ describe("QueueMetricsProcessor", () => {
4
+ let processor;
5
+ beforeEach(() => {
6
+ vi.useFakeTimers();
7
+ });
8
+ afterEach(() => {
9
+ vi.useRealTimers();
10
+ });
11
+ describe("Constructor validation", () => {
12
+ it("should throw error for invalid ewmaAlpha", () => {
13
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: -0.1, batchWindowMs: 1000 })).toThrow("ewmaAlpha must be between 0 and 1");
14
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: 1.1, batchWindowMs: 1000 })).toThrow("ewmaAlpha must be between 0 and 1");
15
+ });
16
+ it("should throw error for invalid batchWindowMs", () => {
17
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 0 })).toThrow("batchWindowMs must be positive");
18
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: -100 })).toThrow("batchWindowMs must be positive");
19
+ });
20
+ it("should accept valid parameters", () => {
21
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: 0, batchWindowMs: 1 })).not.toThrow();
22
+ expect(() => new QueueMetricsProcessor({ ewmaAlpha: 1, batchWindowMs: 5000 })).not.toThrow();
23
+ });
24
+ });
25
+ describe("Sample collection", () => {
26
+ beforeEach(() => {
27
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
28
+ });
29
+ it("should collect samples without limit", () => {
30
+ for (let i = 0; i < 100; i++) {
31
+ processor.addSample(i);
32
+ }
33
+ expect(processor.getCurrentSampleCount()).toBe(100);
34
+ expect(processor.getCurrentSamples()).toHaveLength(100);
35
+ });
36
+ it("should throw error for negative queue lengths", () => {
37
+ expect(() => processor.addSample(-1)).toThrow("Queue length cannot be negative");
38
+ });
39
+ it("should accept zero queue length", () => {
40
+ expect(() => processor.addSample(0)).not.toThrow();
41
+ expect(processor.getCurrentSampleCount()).toBe(1);
42
+ });
43
+ it("should handle empty queue with all zero samples", () => {
44
+ processor.addSample(0);
45
+ processor.addSample(0);
46
+ processor.addSample(0);
47
+ const result = processor.processBatch();
48
+ expect(result).not.toBeNull();
49
+ expect(result.median).toBe(0);
50
+ expect(result.smoothedValue).toBe(0);
51
+ expect(processor.getSmoothedValue()).toBe(0);
52
+ });
53
+ it("should properly transition from zero to non-zero queue", () => {
54
+ // Start with empty queue
55
+ processor.addSample(0);
56
+ processor.addSample(0);
57
+ let result = processor.processBatch();
58
+ expect(result.median).toBe(0);
59
+ expect(result.smoothedValue).toBe(0);
60
+ // Queue starts filling
61
+ processor.addSample(10);
62
+ processor.addSample(15);
63
+ result = processor.processBatch();
64
+ expect(result.median).toBeGreaterThan(0);
65
+ // EWMA: 0.3 * median + 0.7 * 0
66
+ expect(result.smoothedValue).toBeGreaterThan(0);
67
+ });
68
+ it("should properly transition from non-zero to zero queue", () => {
69
+ // Start with non-empty queue
70
+ processor.addSample(10);
71
+ processor.addSample(15);
72
+ let result = processor.processBatch();
73
+ const initialSmoothed = result.smoothedValue;
74
+ expect(initialSmoothed).toBeGreaterThan(0);
75
+ // Queue becomes empty
76
+ processor.addSample(0);
77
+ processor.addSample(0);
78
+ processor.addSample(0);
79
+ result = processor.processBatch();
80
+ expect(result.median).toBe(0);
81
+ // EWMA should gradually decrease: 0.3 * 0 + 0.7 * initialSmoothed
82
+ expect(result.smoothedValue).toBe(0.7 * initialSmoothed);
83
+ });
84
+ });
85
+ describe("Batch processing timing", () => {
86
+ beforeEach(() => {
87
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
88
+ });
89
+ it("should not process batch before window expires", () => {
90
+ processor.addSample(10, 1000);
91
+ expect(processor.shouldProcessBatch(1500)).toBe(false); // 500ms later
92
+ expect(processor.shouldProcessBatch(1999)).toBe(false); // 999ms later
93
+ });
94
+ it("should process batch when window expires", () => {
95
+ processor.addSample(10, 1000);
96
+ expect(processor.shouldProcessBatch(2000)).toBe(true); // 1000ms later
97
+ expect(processor.shouldProcessBatch(2500)).toBe(true); // 1500ms later
98
+ });
99
+ it("should not process empty batch", () => {
100
+ expect(processor.shouldProcessBatch(5000)).toBe(false);
101
+ });
102
+ });
103
+ describe("EWMA calculation", () => {
104
+ it("should initialize with first value", () => {
105
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
106
+ processor.addSample(10);
107
+ const result = processor.processBatch();
108
+ expect(result).not.toBeNull();
109
+ expect(result.median).toBe(10);
110
+ expect(result.smoothedValue).toBe(10);
111
+ expect(processor.getSmoothedValue()).toBe(10);
112
+ });
113
+ it("should apply EWMA formula correctly", () => {
114
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
115
+ // First batch: smoothed = 10
116
+ processor.addSample(10);
117
+ processor.processBatch();
118
+ expect(processor.getSmoothedValue()).toBe(10);
119
+ // Second batch: smoothed = 0.3 * 20 + 0.7 * 10 = 6 + 7 = 13
120
+ processor.addSample(20);
121
+ processor.processBatch();
122
+ expect(processor.getSmoothedValue()).toBe(13);
123
+ // Third batch: smoothed = 0.3 * 5 + 0.7 * 13 = 1.5 + 9.1 = 10.6
124
+ processor.addSample(5);
125
+ processor.processBatch();
126
+ expect(processor.getSmoothedValue()).toBe(10.6);
127
+ });
128
+ it("should test different alpha values", () => {
129
+ // High alpha (0.8) - more responsive
130
+ const highAlphaProcessor = new QueueMetricsProcessor({ ewmaAlpha: 0.8, batchWindowMs: 1000 });
131
+ highAlphaProcessor.addSample(10);
132
+ highAlphaProcessor.processBatch();
133
+ highAlphaProcessor.addSample(20);
134
+ highAlphaProcessor.processBatch();
135
+ // Low alpha (0.1) - more smoothing
136
+ const lowAlphaProcessor = new QueueMetricsProcessor({ ewmaAlpha: 0.1, batchWindowMs: 1000 });
137
+ lowAlphaProcessor.addSample(10);
138
+ lowAlphaProcessor.processBatch();
139
+ lowAlphaProcessor.addSample(20);
140
+ lowAlphaProcessor.processBatch();
141
+ // High alpha should be closer to recent value (20)
142
+ expect(highAlphaProcessor.getSmoothedValue()).toBeCloseTo(18); // 0.8 * 20 + 0.2 * 10 = 18
143
+ // Low alpha should be closer to previous value (10)
144
+ expect(lowAlphaProcessor.getSmoothedValue()).toBeCloseTo(11); // 0.1 * 20 + 0.9 * 10 = 11
145
+ });
146
+ });
147
+ describe("Median filtering", () => {
148
+ beforeEach(() => {
149
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
150
+ });
151
+ it("should calculate median of single sample", () => {
152
+ processor.addSample(42);
153
+ const result = processor.processBatch();
154
+ expect(result.median).toBe(42);
155
+ expect(result.sampleCount).toBe(1);
156
+ expect(result.smoothedValue).toBe(42); // First batch initializes to median
157
+ });
158
+ it("should calculate median of odd number of samples", () => {
159
+ processor.addSample(1);
160
+ processor.addSample(10);
161
+ processor.addSample(5);
162
+ const result = processor.processBatch();
163
+ expect(result.median).toBe(5);
164
+ });
165
+ it("should calculate median of even number of samples", () => {
166
+ processor.addSample(1);
167
+ processor.addSample(10);
168
+ processor.addSample(5);
169
+ processor.addSample(8);
170
+ const result = processor.processBatch();
171
+ // With even count, we average the two middle values
172
+ // Sorted: [1, 5, 8, 10], median = (5 + 8) / 2 = 6.5
173
+ expect(result.median).toBe(6.5);
174
+ });
175
+ it("should filter outliers using median", () => {
176
+ // Add mostly low values with one outlier
177
+ processor.addSample(5);
178
+ processor.addSample(5);
179
+ processor.addSample(5);
180
+ processor.addSample(100); // outlier
181
+ processor.addSample(5);
182
+ const result = processor.processBatch();
183
+ // Sorted: [5, 5, 5, 5, 100], median = 5 (filters out outlier)
184
+ expect(result.median).toBe(5);
185
+ });
186
+ });
187
+ describe("Batch result", () => {
188
+ beforeEach(() => {
189
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
190
+ });
191
+ it("should return comprehensive batch result", () => {
192
+ processor.addSample(10);
193
+ processor.addSample(20);
194
+ processor.addSample(15);
195
+ const result = processor.processBatch();
196
+ expect(result).not.toBeNull();
197
+ expect(result.median).toBe(15);
198
+ expect(result.smoothedValue).toBe(15); // First batch
199
+ expect(result.sampleCount).toBe(3);
200
+ expect(result.samples).toEqual([10, 20, 15]);
201
+ });
202
+ it("should return null for empty batch", () => {
203
+ const result = processor.processBatch();
204
+ expect(result).toBeNull();
205
+ });
206
+ it("should clear samples after processing", () => {
207
+ processor.addSample(10);
208
+ processor.addSample(20);
209
+ expect(processor.getCurrentSampleCount()).toBe(2);
210
+ processor.processBatch();
211
+ expect(processor.getCurrentSampleCount()).toBe(0);
212
+ expect(processor.getCurrentSamples()).toHaveLength(0);
213
+ });
214
+ });
215
+ describe("Reset functionality", () => {
216
+ beforeEach(() => {
217
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
218
+ });
219
+ it("should reset all state", () => {
220
+ processor.addSample(10);
221
+ processor.processBatch();
222
+ processor.addSample(20);
223
+ expect(processor.getSmoothedValue()).toBe(10);
224
+ expect(processor.getCurrentSampleCount()).toBe(1);
225
+ processor.reset();
226
+ expect(processor.getSmoothedValue()).toBe(0);
227
+ expect(processor.getCurrentSampleCount()).toBe(0);
228
+ expect(processor.getCurrentSamples()).toHaveLength(0);
229
+ });
230
+ it("should reinitialize correctly after reset", () => {
231
+ // Process some data
232
+ processor.addSample(10);
233
+ processor.processBatch();
234
+ processor.addSample(20);
235
+ processor.processBatch();
236
+ processor.reset();
237
+ // Should initialize with first value again
238
+ processor.addSample(30);
239
+ const result = processor.processBatch();
240
+ expect(result.smoothedValue).toBe(30);
241
+ expect(processor.getSmoothedValue()).toBe(30);
242
+ });
243
+ });
244
+ describe("Configuration", () => {
245
+ it("should return configuration", () => {
246
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.5, batchWindowMs: 2000 });
247
+ const config = processor.getConfig();
248
+ expect(config.ewmaAlpha).toBe(0.5);
249
+ expect(config.batchWindowMs).toBe(2000);
250
+ });
251
+ });
252
+ describe("Real-world simulation", () => {
253
+ it("should handle high-frequency samples from multiple consumers", () => {
254
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
255
+ // Simulate 40 consumers reporting queue lengths within 1 second
256
+ const baseTime = 1000;
257
+ for (let i = 0; i < 40; i++) {
258
+ const queueLength = 100 - i * 2; // Queue decreasing as consumers work
259
+ processor.addSample(queueLength, baseTime + i * 25); // Spread over 1 second
260
+ }
261
+ const result = processor.processBatch(baseTime + 1000);
262
+ expect(result).not.toBeNull();
263
+ expect(result.sampleCount).toBe(40);
264
+ // Median should be around middle values (queue lengths 60-80)
265
+ expect(result.median).toBeGreaterThanOrEqual(60);
266
+ expect(result.median).toBeLessThanOrEqual(80);
267
+ });
268
+ it("should demonstrate EWMA smoothing over time", () => {
269
+ processor = new QueueMetricsProcessor({ ewmaAlpha: 0.3, batchWindowMs: 1000 });
270
+ const results = [];
271
+ // Simulate queue spike and recovery
272
+ const scenarios = [
273
+ { samples: [5, 5, 5], expected: 5 }, // Baseline
274
+ { samples: [50, 50, 50], expected: 18.5 }, // Spike: 0.3 * 50 + 0.7 * 5 = 18.5
275
+ { samples: [5, 5, 5], expected: 10.05 }, // Recovery: 0.3 * 5 + 0.7 * 18.5 = 14.45
276
+ ];
277
+ for (const scenario of scenarios) {
278
+ for (const sample of scenario.samples) {
279
+ processor.addSample(sample);
280
+ }
281
+ const result = processor.processBatch();
282
+ results.push(result.smoothedValue);
283
+ }
284
+ // Should show gradual change due to EWMA smoothing
285
+ expect(results[0]).toBe(5); // Initial
286
+ expect(results[1]).toBeCloseTo(18.5); // Spike response
287
+ expect(results[2]).toBeCloseTo(14.45); // Gradual recovery
288
+ });
289
+ });
290
+ });
291
+ //# sourceMappingURL=queueMetricsProcessor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queueMetricsProcessor.test.js","sourceRoot":"","sources":["../../../../../src/v3/runEngineWorker/supervisor/queueMetricsProcessor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { QueueMetricsProcessor } from "./queueMetricsProcessor.js";
2
+ export type ScalingStrategyKind = "none" | "smooth" | "aggressive";
3
+ export interface ScalingStrategyOptions {
4
+ metricsProcessor?: QueueMetricsProcessor;
5
+ dampingFactor?: number;
6
+ minConsumerCount: number;
7
+ maxConsumerCount: number;
8
+ targetRatio: number;
9
+ }
10
+ export declare abstract class ScalingStrategy {
11
+ abstract readonly name: string;
12
+ private readonly minConsumerCount;
13
+ private readonly maxConsumerCount;
14
+ protected readonly targetRatio: number;
15
+ constructor(options?: ScalingStrategyOptions);
16
+ /**
17
+ * Calculates the target consumer count with clamping to min/max bounds
18
+ * Uses template method pattern to ensure consistent clamping across all strategies
19
+ */
20
+ calculateTargetCount(currentCount: number): number;
21
+ /**
22
+ * Internal method for subclasses to implement their specific scaling logic
23
+ * Should return the unclamped target count
24
+ */
25
+ protected abstract calculateTargetCountInternal(currentCount: number): number;
26
+ /**
27
+ * Creates a scaling strategy by name
28
+ */
29
+ static create(strategy: ScalingStrategyKind, options?: ScalingStrategyOptions): ScalingStrategy;
30
+ }
31
+ /**
32
+ * Static scaling strategy - maintains a fixed number of consumers
33
+ */
34
+ export declare class NoneScalingStrategy extends ScalingStrategy {
35
+ readonly name = "none";
36
+ constructor(options?: ScalingStrategyOptions);
37
+ protected calculateTargetCountInternal(currentCount: number): number;
38
+ }
39
+ /**
40
+ * Smooth scaling strategy with EWMA smoothing and damping
41
+ * Uses exponentially weighted moving average for queue length smoothing
42
+ * and applies damping to prevent rapid oscillations.
43
+ */
44
+ export declare class SmoothScalingStrategy extends ScalingStrategy {
45
+ readonly name = "smooth";
46
+ private readonly dampingFactor;
47
+ private readonly metricsProcessor;
48
+ constructor(options?: ScalingStrategyOptions);
49
+ protected calculateTargetCountInternal(currentCount: number): number;
50
+ }
51
+ /**
52
+ * Aggressive scaling strategy with threshold-based zones
53
+ * Uses threshold-based zones for different scaling behaviors.
54
+ * Scales up quickly when load increases but scales down cautiously.
55
+ */
56
+ export declare class AggressiveScalingStrategy extends ScalingStrategy {
57
+ readonly name = "aggressive";
58
+ private readonly metricsProcessor;
59
+ constructor(options?: ScalingStrategyOptions);
60
+ protected calculateTargetCountInternal(currentCount: number): number;
61
+ getThresholds(targetRatio: number): {
62
+ scaleDownThreshold: number;
63
+ scaleUpThreshold: number;
64
+ criticalThreshold: number;
65
+ highThreshold: number;
66
+ };
67
+ }
@@ -0,0 +1,146 @@
1
+ export class ScalingStrategy {
2
+ minConsumerCount;
3
+ maxConsumerCount;
4
+ targetRatio;
5
+ constructor(options) {
6
+ this.minConsumerCount = options?.minConsumerCount ?? 1;
7
+ this.maxConsumerCount = options?.maxConsumerCount ?? 10;
8
+ this.targetRatio = options?.targetRatio ?? 1;
9
+ }
10
+ /**
11
+ * Calculates the target consumer count with clamping to min/max bounds
12
+ * Uses template method pattern to ensure consistent clamping across all strategies
13
+ */
14
+ calculateTargetCount(currentCount) {
15
+ const targetCount = this.calculateTargetCountInternal(currentCount);
16
+ // Apply consistent clamping to all strategies
17
+ return Math.min(Math.max(targetCount, this.minConsumerCount), this.maxConsumerCount);
18
+ }
19
+ /**
20
+ * Creates a scaling strategy by name
21
+ */
22
+ static create(strategy, options) {
23
+ switch (strategy) {
24
+ case "none":
25
+ return new NoneScalingStrategy(options);
26
+ case "smooth":
27
+ return new SmoothScalingStrategy(options);
28
+ case "aggressive":
29
+ return new AggressiveScalingStrategy(options);
30
+ default:
31
+ throw new Error(`Unknown scaling strategy: ${strategy}`);
32
+ }
33
+ }
34
+ }
35
+ /**
36
+ * Static scaling strategy - maintains a fixed number of consumers
37
+ */
38
+ export class NoneScalingStrategy extends ScalingStrategy {
39
+ name = "none";
40
+ constructor(options) {
41
+ super(options);
42
+ }
43
+ calculateTargetCountInternal(currentCount) {
44
+ return currentCount;
45
+ }
46
+ }
47
+ /**
48
+ * Smooth scaling strategy with EWMA smoothing and damping
49
+ * Uses exponentially weighted moving average for queue length smoothing
50
+ * and applies damping to prevent rapid oscillations.
51
+ */
52
+ export class SmoothScalingStrategy extends ScalingStrategy {
53
+ name = "smooth";
54
+ dampingFactor;
55
+ metricsProcessor;
56
+ constructor(options) {
57
+ super(options);
58
+ const dampingFactor = options?.dampingFactor ?? 0.7;
59
+ if (dampingFactor < 0 || dampingFactor > 1) {
60
+ throw new Error("dampingFactor must be between 0 and 1");
61
+ }
62
+ if (!options?.metricsProcessor) {
63
+ throw new Error("metricsProcessor is required for smooth scaling strategy");
64
+ }
65
+ this.dampingFactor = dampingFactor;
66
+ this.metricsProcessor = options.metricsProcessor;
67
+ }
68
+ calculateTargetCountInternal(currentCount) {
69
+ const smoothedQueueLength = this.metricsProcessor.getSmoothedValue();
70
+ // Calculate target consumers based on the configured ratio
71
+ const targetConsumers = Math.ceil(smoothedQueueLength / this.targetRatio);
72
+ // Apply damping factor to smooth out changes
73
+ // This prevents oscillation by only moving toward the target gradually
74
+ const dampedTarget = currentCount + (targetConsumers - currentCount) * this.dampingFactor;
75
+ // Return rounded value without clamping (handled by base class)
76
+ return Math.round(dampedTarget);
77
+ }
78
+ }
79
+ /**
80
+ * Aggressive scaling strategy with threshold-based zones
81
+ * Uses threshold-based zones for different scaling behaviors.
82
+ * Scales up quickly when load increases but scales down cautiously.
83
+ */
84
+ export class AggressiveScalingStrategy extends ScalingStrategy {
85
+ name = "aggressive";
86
+ metricsProcessor;
87
+ constructor(options) {
88
+ super(options);
89
+ if (!options?.metricsProcessor) {
90
+ throw new Error("metricsProcessor is required for aggressive scaling strategy");
91
+ }
92
+ this.metricsProcessor = options.metricsProcessor;
93
+ }
94
+ calculateTargetCountInternal(currentCount) {
95
+ const smoothedQueueLength = this.metricsProcessor.getSmoothedValue();
96
+ // Calculate queue items per consumer,
97
+ const queuePerConsumer = smoothedQueueLength / (currentCount || 1);
98
+ // Define zones based on targetRatio
99
+ // Optimal zone: 0.5x to 2x the target ratio
100
+ const scaleDownThreshold = this.targetRatio * 0.5;
101
+ const scaleUpThreshold = this.targetRatio * 2.0;
102
+ if (queuePerConsumer < scaleDownThreshold) {
103
+ // Zone 1: Under-utilized (< 0.5x target ratio)
104
+ // Scale down gradually to avoid removing too many consumers
105
+ const reductionFactor = Math.max(0.9, 1 - (scaleDownThreshold - queuePerConsumer) * 0.1);
106
+ // Return without min clamping (handled by base class)
107
+ return Math.floor(currentCount * reductionFactor);
108
+ }
109
+ else if (queuePerConsumer > scaleUpThreshold) {
110
+ // Zone 3: Over-utilized (> 2x target ratio)
111
+ // Scale up aggressively based on queue pressure
112
+ let scaleFactor;
113
+ if (queuePerConsumer >= this.targetRatio * 5) {
114
+ // Critical: Queue is 5x target ratio or higher
115
+ scaleFactor = 1.5; // 50% increase
116
+ }
117
+ else if (queuePerConsumer >= this.targetRatio * 3) {
118
+ // High: Queue is 3x target ratio
119
+ scaleFactor = 1.3; // 30% increase
120
+ }
121
+ else {
122
+ // Moderate: Queue is 2x target ratio
123
+ scaleFactor = 1.1; // 10% increase
124
+ }
125
+ const targetCount = Math.ceil(currentCount * scaleFactor);
126
+ // Cap increase at 50% to prevent overshooting
127
+ const maxIncrement = Math.ceil(currentCount * 0.5);
128
+ // Return without max clamping (handled by base class)
129
+ return Math.min(currentCount + maxIncrement, targetCount);
130
+ }
131
+ else {
132
+ // Zone 2: Optimal (0.5x - 2x target ratio)
133
+ // Maintain current consumer count
134
+ return currentCount;
135
+ }
136
+ }
137
+ getThresholds(targetRatio) {
138
+ return {
139
+ scaleDownThreshold: targetRatio * 0.5,
140
+ scaleUpThreshold: targetRatio * 2.0,
141
+ criticalThreshold: targetRatio * 5.0,
142
+ highThreshold: targetRatio * 3.0,
143
+ };
144
+ }
145
+ }
146
+ //# sourceMappingURL=scalingStrategies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scalingStrategies.js","sourceRoot":"","sources":["../../../../../src/v3/runEngineWorker/supervisor/scalingStrategies.ts"],"names":[],"mappings":"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"}