@devrev/ts-adaas 1.12.3-beta.6 → 1.12.3-beta.7
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/dist/common/constants.d.ts +1 -0
- package/dist/common/constants.d.ts.map +1 -1
- package/dist/common/constants.js +2 -1
- package/dist/common/worker-memory.d.ts +59 -0
- package/dist/common/worker-memory.d.ts.map +1 -0
- package/dist/common/worker-memory.js +177 -0
- package/dist/tests/oom-handling/extraction.d.ts +11 -0
- package/dist/tests/oom-handling/extraction.d.ts.map +1 -0
- package/dist/tests/oom-handling/extraction.js +29 -0
- package/dist/tests/oom-handling/jest.setup.d.ts +7 -0
- package/dist/tests/oom-handling/jest.setup.d.ts.map +1 -0
- package/dist/tests/oom-handling/jest.setup.js +26 -0
- package/dist/tests/oom-handling/oom-after-emit-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-after-emit-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-after-emit-worker.js +35 -0
- package/dist/tests/oom-handling/oom-attachments-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-attachments-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-attachments-worker.js +29 -0
- package/dist/tests/oom-handling/oom-external-sync-units-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-external-sync-units-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-external-sync-units-worker.js +29 -0
- package/dist/tests/oom-handling/oom-gradual-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-gradual-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-gradual-worker.js +47 -0
- package/dist/tests/oom-handling/oom-handling.test.d.ts +2 -0
- package/dist/tests/oom-handling/oom-handling.test.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-handling.test.js +407 -0
- package/dist/tests/oom-handling/oom-metadata-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-metadata-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-metadata-worker.js +29 -0
- package/dist/tests/oom-handling/oom-worker.d.ts +2 -0
- package/dist/tests/oom-handling/oom-worker.d.ts.map +1 -0
- package/dist/tests/oom-handling/oom-worker.js +55 -0
- package/dist/tests/oom-handling/worker-memory.test.d.ts +2 -0
- package/dist/tests/oom-handling/worker-memory.test.d.ts.map +1 -0
- package/dist/tests/oom-handling/worker-memory.test.js +306 -0
- package/dist/types/common.d.ts +3 -0
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/workers.d.ts +58 -0
- package/dist/types/workers.d.ts.map +1 -1
- package/dist/uploader/uploader.d.ts.map +1 -1
- package/dist/uploader/uploader.js +13 -5
- package/dist/workers/create-worker.d.ts +20 -2
- package/dist/workers/create-worker.d.ts.map +1 -1
- package/dist/workers/create-worker.js +38 -3
- package/dist/workers/create-worker.test.js +113 -14
- package/dist/workers/spawn.d.ts +10 -1
- package/dist/workers/spawn.d.ts.map +1 -1
- package/dist/workers/spawn.js +77 -3
- package/package.json +2 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const worker_memory_1 = require("../../common/worker-memory");
|
|
4
|
+
describe('worker-memory utilities', () => {
|
|
5
|
+
const originalEnv = process.env;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
jest.resetModules();
|
|
8
|
+
process.env = Object.assign({}, originalEnv);
|
|
9
|
+
});
|
|
10
|
+
afterAll(() => {
|
|
11
|
+
process.env = originalEnv;
|
|
12
|
+
});
|
|
13
|
+
describe('isLambdaEnvironment', () => {
|
|
14
|
+
it('should return false when not in Lambda', () => {
|
|
15
|
+
delete process.env.AWS_LAMBDA_FUNCTION_NAME;
|
|
16
|
+
delete process.env.AWS_EXECUTION_ENV;
|
|
17
|
+
delete process.env.LAMBDA_TASK_ROOT;
|
|
18
|
+
expect((0, worker_memory_1.isLambdaEnvironment)()).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it('should return true when AWS_LAMBDA_FUNCTION_NAME is set', () => {
|
|
21
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
22
|
+
expect((0, worker_memory_1.isLambdaEnvironment)()).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('should return true when AWS_EXECUTION_ENV is set', () => {
|
|
25
|
+
process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs18.x';
|
|
26
|
+
expect((0, worker_memory_1.isLambdaEnvironment)()).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it('should return true when LAMBDA_TASK_ROOT is set', () => {
|
|
29
|
+
process.env.LAMBDA_TASK_ROOT = '/var/task';
|
|
30
|
+
expect((0, worker_memory_1.isLambdaEnvironment)()).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('getLambdaMemoryLimitMb', () => {
|
|
34
|
+
it('should return null when not in Lambda', () => {
|
|
35
|
+
delete process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
36
|
+
expect((0, worker_memory_1.getLambdaMemoryLimitMb)()).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
it('should return memory limit when AWS_LAMBDA_FUNCTION_MEMORY_SIZE is set', () => {
|
|
39
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1024';
|
|
40
|
+
expect((0, worker_memory_1.getLambdaMemoryLimitMb)()).toBe(1024);
|
|
41
|
+
});
|
|
42
|
+
it('should return null for invalid memory size', () => {
|
|
43
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = 'invalid';
|
|
44
|
+
expect((0, worker_memory_1.getLambdaMemoryLimitMb)()).toBeNull();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('getTotalAvailableMemoryMb', () => {
|
|
48
|
+
it('should use Lambda memory when in Lambda environment', () => {
|
|
49
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '2048';
|
|
50
|
+
const result = (0, worker_memory_1.getTotalAvailableMemoryMb)(false);
|
|
51
|
+
expect(result).toBe(2048);
|
|
52
|
+
});
|
|
53
|
+
it('should cap at LOCAL_DEV_MAX_TOTAL_MEMORY_MB for local development', () => {
|
|
54
|
+
delete process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
55
|
+
const result = (0, worker_memory_1.getTotalAvailableMemoryMb)(true);
|
|
56
|
+
expect(result).toBeLessThanOrEqual(worker_memory_1.MEMORY_CONSTANTS.LOCAL_DEV_MAX_TOTAL_MEMORY_MB);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('calculateWorkerMemoryConfig', () => {
|
|
60
|
+
it('should calculate memory config for local development', () => {
|
|
61
|
+
delete process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
62
|
+
delete process.env.AWS_LAMBDA_FUNCTION_NAME;
|
|
63
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(true);
|
|
64
|
+
expect(config.isLocalDevelopment).toBe(true);
|
|
65
|
+
expect(config.isLambda).toBe(false);
|
|
66
|
+
expect(config.workerMemoryPercentage).toBe(worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE);
|
|
67
|
+
expect(config.maxOldGenerationSizeMb).toBeGreaterThanOrEqual(worker_memory_1.MEMORY_CONSTANTS.MIN_WORKER_HEAP_SIZE_MB);
|
|
68
|
+
// For local dev, should be capped
|
|
69
|
+
expect(config.totalAvailableMemoryMb).toBeLessThanOrEqual(worker_memory_1.MEMORY_CONSTANTS.LOCAL_DEV_MAX_TOTAL_MEMORY_MB);
|
|
70
|
+
});
|
|
71
|
+
it('should calculate memory config for Lambda environment', () => {
|
|
72
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1024';
|
|
73
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
74
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
75
|
+
expect(config.isLambda).toBe(true);
|
|
76
|
+
expect(config.totalAvailableMemoryMb).toBe(1024);
|
|
77
|
+
// Worker should get 75% of Lambda memory
|
|
78
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(1024 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('isOOMError', () => {
|
|
82
|
+
describe('with Error objects', () => {
|
|
83
|
+
it('should detect ERR_WORKER_OUT_OF_MEMORY error code on Error object', () => {
|
|
84
|
+
const error = new Error('Worker terminated due to reaching memory limit');
|
|
85
|
+
error.code = worker_memory_1.ERR_WORKER_OUT_OF_MEMORY;
|
|
86
|
+
expect((0, worker_memory_1.isOOMError)(error)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
it('should detect OOM from Error message when code is not set', () => {
|
|
89
|
+
const error = new Error('JavaScript heap out of memory');
|
|
90
|
+
expect((0, worker_memory_1.isOOMError)(error)).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
it('should detect OOM from Error message with other error codes', () => {
|
|
93
|
+
const error = new Error('FATAL ERROR: Reached heap limit');
|
|
94
|
+
error.code = 'SOME_OTHER_CODE';
|
|
95
|
+
expect((0, worker_memory_1.isOOMError)(error)).toBe(true);
|
|
96
|
+
});
|
|
97
|
+
it('should return false for non-OOM Error objects', () => {
|
|
98
|
+
const error = new Error('Connection timeout');
|
|
99
|
+
error.code = 'ECONNREFUSED';
|
|
100
|
+
expect((0, worker_memory_1.isOOMError)(error)).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
it('should prioritize error code over message', () => {
|
|
103
|
+
// Error with OOM code but non-OOM message - should still be detected as OOM
|
|
104
|
+
const error = new Error('Some generic error');
|
|
105
|
+
error.code = worker_memory_1.ERR_WORKER_OUT_OF_MEMORY;
|
|
106
|
+
expect((0, worker_memory_1.isOOMError)(error)).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('with string messages', () => {
|
|
110
|
+
it('should detect JavaScript heap out of memory', () => {
|
|
111
|
+
expect((0, worker_memory_1.isOOMError)('JavaScript heap out of memory')).toBe(true);
|
|
112
|
+
expect((0, worker_memory_1.isOOMError)('FATAL ERROR: JavaScript heap out of memory')).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it('should detect allocation failed errors', () => {
|
|
115
|
+
expect((0, worker_memory_1.isOOMError)('Allocation failed - JavaScript heap out of memory')).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
it('should detect heap limit errors', () => {
|
|
118
|
+
expect((0, worker_memory_1.isOOMError)('FATAL ERROR: Reached heap limit')).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
it('should detect CALL_AND_RETRY_LAST errors', () => {
|
|
121
|
+
expect((0, worker_memory_1.isOOMError)('FATAL ERROR: CALL_AND_RETRY_LAST')).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
it('should detect ERR_WORKER_OUT_OF_MEMORY in string message', () => {
|
|
124
|
+
expect((0, worker_memory_1.isOOMError)('ERR_WORKER_OUT_OF_MEMORY')).toBe(true);
|
|
125
|
+
expect((0, worker_memory_1.isOOMError)('Error [ERR_WORKER_OUT_OF_MEMORY]: Worker terminated due to reaching memory limit')).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
it('should detect Worker terminated due to reaching memory limit', () => {
|
|
128
|
+
expect((0, worker_memory_1.isOOMError)('Worker terminated due to reaching memory limit')).toBe(true);
|
|
129
|
+
expect((0, worker_memory_1.isOOMError)('Worker terminated due to reaching memory limit: JavaScript heap out of memory')).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
it('should detect JS heap out of memory (abbreviated)', () => {
|
|
132
|
+
expect((0, worker_memory_1.isOOMError)('JS heap out of memory')).toBe(true);
|
|
133
|
+
expect((0, worker_memory_1.isOOMError)('FATAL ERROR: JS heap out of memory')).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
it('should detect memory allocation failed', () => {
|
|
136
|
+
expect((0, worker_memory_1.isOOMError)('memory allocation failed')).toBe(true);
|
|
137
|
+
expect((0, worker_memory_1.isOOMError)('Error: memory allocation failed during processing')).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
it('should return false for non-OOM errors', () => {
|
|
140
|
+
expect((0, worker_memory_1.isOOMError)('Connection timeout')).toBe(false);
|
|
141
|
+
expect((0, worker_memory_1.isOOMError)('File not found')).toBe(false);
|
|
142
|
+
expect((0, worker_memory_1.isOOMError)('Permission denied')).toBe(false);
|
|
143
|
+
expect((0, worker_memory_1.isOOMError)('ENOENT: no such file or directory')).toBe(false);
|
|
144
|
+
expect((0, worker_memory_1.isOOMError)('ECONNREFUSED')).toBe(false);
|
|
145
|
+
expect((0, worker_memory_1.isOOMError)('TypeError: undefined is not a function')).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
it('should handle empty and undefined-like inputs', () => {
|
|
148
|
+
expect((0, worker_memory_1.isOOMError)('')).toBe(false);
|
|
149
|
+
expect((0, worker_memory_1.isOOMError)(' ')).toBe(false);
|
|
150
|
+
expect((0, worker_memory_1.isOOMError)('null')).toBe(false);
|
|
151
|
+
expect((0, worker_memory_1.isOOMError)('undefined')).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
it('should be case insensitive', () => {
|
|
154
|
+
expect((0, worker_memory_1.isOOMError)('JAVASCRIPT HEAP OUT OF MEMORY')).toBe(true);
|
|
155
|
+
expect((0, worker_memory_1.isOOMError)('javascript heap out of memory')).toBe(true);
|
|
156
|
+
expect((0, worker_memory_1.isOOMError)('JavaScript Heap Out Of Memory')).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe('edge cases for memory calculations', () => {
|
|
161
|
+
it('should handle very low Lambda memory (128MB)', () => {
|
|
162
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128';
|
|
163
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
164
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
165
|
+
expect(config.isLambda).toBe(true);
|
|
166
|
+
expect(config.totalAvailableMemoryMb).toBe(128);
|
|
167
|
+
// Worker should get 75% of 128MB = 96MB, but MIN is 128MB
|
|
168
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.max(Math.floor(128 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE), worker_memory_1.MEMORY_CONSTANTS.MIN_WORKER_HEAP_SIZE_MB));
|
|
169
|
+
});
|
|
170
|
+
it('should enforce MIN_WORKER_HEAP_SIZE_MB when calculated value is too low', () => {
|
|
171
|
+
// Simulate a very low memory environment
|
|
172
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '64';
|
|
173
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
174
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
175
|
+
// 64MB * 0.75 = 48MB, which is below MIN_WORKER_HEAP_SIZE_MB (128MB)
|
|
176
|
+
expect(config.maxOldGenerationSizeMb).toBe(worker_memory_1.MEMORY_CONSTANTS.MIN_WORKER_HEAP_SIZE_MB);
|
|
177
|
+
});
|
|
178
|
+
it('should handle zero memory size gracefully', () => {
|
|
179
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '0';
|
|
180
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
181
|
+
// 0 is not > 0, so should return null
|
|
182
|
+
expect(result).toBeNull();
|
|
183
|
+
});
|
|
184
|
+
it('should handle negative memory size gracefully', () => {
|
|
185
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '-512';
|
|
186
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
187
|
+
// Negative is not > 0, so should return null
|
|
188
|
+
expect(result).toBeNull();
|
|
189
|
+
});
|
|
190
|
+
it('should handle very large Lambda memory (10240MB)', () => {
|
|
191
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '10240';
|
|
192
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
193
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
194
|
+
expect(config.isLambda).toBe(true);
|
|
195
|
+
expect(config.totalAvailableMemoryMb).toBe(10240);
|
|
196
|
+
// Worker should get 75% of 10240MB = 7680MB
|
|
197
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(10240 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
198
|
+
});
|
|
199
|
+
it('should handle floating point memory size', () => {
|
|
200
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1024.5';
|
|
201
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
202
|
+
// parseInt should truncate to 1024
|
|
203
|
+
expect(result).toBe(1024);
|
|
204
|
+
});
|
|
205
|
+
it('should handle memory size with leading zeros', () => {
|
|
206
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '00512';
|
|
207
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
208
|
+
expect(result).toBe(512);
|
|
209
|
+
});
|
|
210
|
+
it('should handle memory size with whitespace', () => {
|
|
211
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = ' 1024 ';
|
|
212
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
213
|
+
// parseInt handles leading whitespace
|
|
214
|
+
expect(result).toBe(1024);
|
|
215
|
+
});
|
|
216
|
+
it('should return null for empty string memory size', () => {
|
|
217
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '';
|
|
218
|
+
const result = (0, worker_memory_1.getLambdaMemoryLimitMb)();
|
|
219
|
+
expect(result).toBeNull();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('Lambda environment simulation', () => {
|
|
223
|
+
it('should correctly detect Lambda environment with all env vars set', () => {
|
|
224
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-function';
|
|
225
|
+
process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs18.x';
|
|
226
|
+
process.env.LAMBDA_TASK_ROOT = '/var/task';
|
|
227
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '512';
|
|
228
|
+
expect((0, worker_memory_1.isLambdaEnvironment)()).toBe(true);
|
|
229
|
+
expect((0, worker_memory_1.getLambdaMemoryLimitMb)()).toBe(512);
|
|
230
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
231
|
+
expect(config.isLambda).toBe(true);
|
|
232
|
+
expect(config.isLocalDevelopment).toBe(false);
|
|
233
|
+
expect(config.totalAvailableMemoryMb).toBe(512);
|
|
234
|
+
});
|
|
235
|
+
it('should calculate correct worker memory for Lambda 256MB', () => {
|
|
236
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-256';
|
|
237
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '256';
|
|
238
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
239
|
+
expect(config.totalAvailableMemoryMb).toBe(256);
|
|
240
|
+
// 256 * 0.75 = 192MB for worker, but MIN is 128MB
|
|
241
|
+
const expectedWorkerMemory = Math.max(Math.floor(256 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE), worker_memory_1.MEMORY_CONSTANTS.MIN_WORKER_HEAP_SIZE_MB);
|
|
242
|
+
expect(config.maxOldGenerationSizeMb).toBe(expectedWorkerMemory);
|
|
243
|
+
});
|
|
244
|
+
it('should calculate correct worker memory for Lambda 512MB', () => {
|
|
245
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-512';
|
|
246
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '512';
|
|
247
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
248
|
+
expect(config.totalAvailableMemoryMb).toBe(512);
|
|
249
|
+
// 512 * 0.75 = 384MB for worker
|
|
250
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(512 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
251
|
+
});
|
|
252
|
+
it('should calculate correct worker memory for Lambda 1024MB', () => {
|
|
253
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-1024';
|
|
254
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1024';
|
|
255
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
256
|
+
expect(config.totalAvailableMemoryMb).toBe(1024);
|
|
257
|
+
// 1024 * 0.75 = 768MB for worker
|
|
258
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(1024 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
259
|
+
});
|
|
260
|
+
it('should calculate correct worker memory for Lambda 3008MB (max)', () => {
|
|
261
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-3008';
|
|
262
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '3008';
|
|
263
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
264
|
+
expect(config.totalAvailableMemoryMb).toBe(3008);
|
|
265
|
+
// 3008 * 0.75 = 2256MB for worker
|
|
266
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(3008 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
267
|
+
});
|
|
268
|
+
it('should use local dev memory cap even when Lambda env vars are not set', () => {
|
|
269
|
+
delete process.env.AWS_LAMBDA_FUNCTION_NAME;
|
|
270
|
+
delete process.env.AWS_EXECUTION_ENV;
|
|
271
|
+
delete process.env.LAMBDA_TASK_ROOT;
|
|
272
|
+
delete process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE;
|
|
273
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(true); // isLocalDevelopment = true
|
|
274
|
+
expect(config.isLambda).toBe(false);
|
|
275
|
+
expect(config.isLocalDevelopment).toBe(true);
|
|
276
|
+
expect(config.totalAvailableMemoryMb).toBeLessThanOrEqual(worker_memory_1.MEMORY_CONSTANTS.LOCAL_DEV_MAX_TOTAL_MEMORY_MB);
|
|
277
|
+
});
|
|
278
|
+
it('should prefer Lambda memory over local dev cap when in Lambda', () => {
|
|
279
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test-function';
|
|
280
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '2048';
|
|
281
|
+
// Even with isLocalDevelopment=true, Lambda memory should be used
|
|
282
|
+
// because getLambdaMemoryLimitMb() returns a value
|
|
283
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(true);
|
|
284
|
+
expect(config.totalAvailableMemoryMb).toBe(2048);
|
|
285
|
+
expect(config.isLambda).toBe(true);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
describe('memory percentage allocation', () => {
|
|
289
|
+
it('should allocate WORKER_MEMORY_PERCENTAGE to worker', () => {
|
|
290
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1000';
|
|
291
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test';
|
|
292
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
293
|
+
expect(config.workerMemoryPercentage).toBe(worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE);
|
|
294
|
+
expect(config.maxOldGenerationSizeMb).toBe(Math.floor(1000 * worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE));
|
|
295
|
+
});
|
|
296
|
+
it('should leave ~25% for parent thread', () => {
|
|
297
|
+
process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '1000';
|
|
298
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = 'test';
|
|
299
|
+
const config = (0, worker_memory_1.calculateWorkerMemoryConfig)(false);
|
|
300
|
+
const parentMemory = config.totalAvailableMemoryMb - config.maxOldGenerationSizeMb;
|
|
301
|
+
const parentPercentage = parentMemory / config.totalAvailableMemoryMb;
|
|
302
|
+
// Parent should get approximately 25% (1 - 0.75)
|
|
303
|
+
expect(parentPercentage).toBeCloseTo(1 - worker_memory_1.MEMORY_CONSTANTS.WORKER_MEMORY_PERCENTAGE, 2);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
package/dist/types/common.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Artifact } from '../uploader/uploader.interfaces';
|
|
2
|
+
import { OOMErrorInfo } from './workers';
|
|
2
3
|
/**
|
|
3
4
|
* ErrorLevel is an enum that represents the level of an error.
|
|
4
5
|
* @deprecated
|
|
@@ -13,6 +14,8 @@ export declare enum ErrorLevel {
|
|
|
13
14
|
*/
|
|
14
15
|
export interface ErrorRecord {
|
|
15
16
|
message: string;
|
|
17
|
+
/** OOM error information, present when worker died due to out-of-memory */
|
|
18
|
+
oom_error_info?: OOMErrorInfo;
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
21
|
* LogRecord is an interface that defines the structure of a log record.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/types/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;;GAGG;AACH,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,IAAI,SAAS;CACd;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,YAAY,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,oBAAY,QAAQ;IAClB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;CACpB"}
|
package/dist/types/workers.d.ts
CHANGED
|
@@ -25,12 +25,17 @@ export interface WorkerAdapterInterface<ConnectorState> {
|
|
|
25
25
|
* @param {number=} timeout - The timeout for the worker thread
|
|
26
26
|
* @param {number=} batchSize - Maximum number of extracted items in a batch
|
|
27
27
|
* @param {Record<EventType, string>=} workerPathOverrides - A map of event types to custom worker paths to override default worker paths
|
|
28
|
+
* @param {boolean=} enableMemoryLimits - Whether to enable automatic memory limits for worker threads (default: true)
|
|
29
|
+
* @param {number=} testMemoryLimitMb - Override memory limit for testing purposes (only used when enableMemoryLimits is true)
|
|
28
30
|
*/
|
|
29
31
|
export interface WorkerAdapterOptions {
|
|
30
32
|
isLocalDevelopment?: boolean;
|
|
31
33
|
timeout?: number;
|
|
32
34
|
batchSize?: number;
|
|
33
35
|
workerPathOverrides?: WorkerPathOverrides;
|
|
36
|
+
enableMemoryLimits?: boolean;
|
|
37
|
+
/** Override memory limit for testing purposes (only used when enableMemoryLimits is true) */
|
|
38
|
+
testMemoryLimitMb?: number;
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* SpawnInterface is an interface for Spawn class.
|
|
@@ -38,6 +43,8 @@ export interface WorkerAdapterOptions {
|
|
|
38
43
|
* @constructor
|
|
39
44
|
* @param {AirdropEvent} event - The event object received from the platform
|
|
40
45
|
* @param {Worker} worker - The worker thread
|
|
46
|
+
* @param {WorkerMemoryConfig} memoryConfig - Memory configuration for the worker
|
|
47
|
+
* @param {WorkerResourceLimits} resourceLimits - Resource limits applied to the worker
|
|
41
48
|
*/
|
|
42
49
|
export interface SpawnInterface {
|
|
43
50
|
event: AirdropEvent;
|
|
@@ -45,6 +52,23 @@ export interface SpawnInterface {
|
|
|
45
52
|
options?: WorkerAdapterOptions;
|
|
46
53
|
resolve: (value: void | PromiseLike<void>) => void;
|
|
47
54
|
originalConsole?: Console;
|
|
55
|
+
memoryConfig?: WorkerMemoryConfig;
|
|
56
|
+
resourceLimits?: WorkerResourceLimits;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Memory configuration for worker threads.
|
|
60
|
+
*/
|
|
61
|
+
export interface WorkerMemoryConfig {
|
|
62
|
+
/** Maximum heap size in MB for the worker thread */
|
|
63
|
+
maxOldGenerationSizeMb: number;
|
|
64
|
+
/** Total available memory in MB (for logging/debugging) */
|
|
65
|
+
totalAvailableMemoryMb: number;
|
|
66
|
+
/** Whether running in Lambda environment */
|
|
67
|
+
isLambda: boolean;
|
|
68
|
+
/** Whether running in local development mode */
|
|
69
|
+
isLocalDevelopment: boolean;
|
|
70
|
+
/** The percentage of memory allocated to the worker (0-1) */
|
|
71
|
+
workerMemoryPercentage: number;
|
|
48
72
|
}
|
|
49
73
|
/**
|
|
50
74
|
* SpawnFactoryInterface is an interface for Spawn class factory.
|
|
@@ -145,4 +169,38 @@ export interface GetWorkerPathInterface {
|
|
|
145
169
|
* WorkerPathOverrides represents a mapping of event types to custom worker paths.
|
|
146
170
|
*/
|
|
147
171
|
export type WorkerPathOverrides = Partial<Record<EventType, string>>;
|
|
172
|
+
/**
|
|
173
|
+
* WorkerResourceLimits represents the resource limits applied to a worker thread.
|
|
174
|
+
*/
|
|
175
|
+
export interface WorkerResourceLimits {
|
|
176
|
+
/** Maximum size of the main (old generation) heap in MB */
|
|
177
|
+
maxOldGenerationSizeMb: number;
|
|
178
|
+
/** Maximum size of the young generation heap in MB (optional) */
|
|
179
|
+
maxYoungGenerationSizeMb?: number;
|
|
180
|
+
/** Size of pre-allocated memory range for generated code in MB (optional) */
|
|
181
|
+
codeRangeSizeMb?: number;
|
|
182
|
+
/** Maximum stack size in MB (optional) */
|
|
183
|
+
stackSizeMb?: number;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* OOMErrorInfo represents detailed information about an OOM (Out-Of-Memory) error.
|
|
187
|
+
*/
|
|
188
|
+
export interface OOMErrorInfo {
|
|
189
|
+
/** Error type identifier */
|
|
190
|
+
type: 'OOM_ERROR';
|
|
191
|
+
/** Human-readable error message */
|
|
192
|
+
message: string;
|
|
193
|
+
/** Memory limit that was configured for the worker in MB */
|
|
194
|
+
memoryLimitMb: number;
|
|
195
|
+
/** Total available memory at spawn time in MB */
|
|
196
|
+
totalAvailableMemoryMb: number;
|
|
197
|
+
/** Whether running in Lambda environment */
|
|
198
|
+
isLambda: boolean;
|
|
199
|
+
/** Whether running in local development mode */
|
|
200
|
+
isLocalDevelopment: boolean;
|
|
201
|
+
/** Exit code from the worker (if available) */
|
|
202
|
+
exitCode?: number;
|
|
203
|
+
/** The event type being processed when OOM occurred */
|
|
204
|
+
eventType?: string;
|
|
205
|
+
}
|
|
148
206
|
//# sourceMappingURL=workers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../src/types/workers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE3E,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB,CAAC,cAAc;IACpD,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC;AAED
|
|
1
|
+
{"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../src/types/workers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/uploader/uploader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/uploader/uploader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EAEL,gBAAgB,EAChB,cAAc,EACd,wBAAwB,EACzB,MAAM,uBAAuB,CAAC;AAE/B,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,kBAAkB,CAAC,CAAU;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAyB;gBAEnC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,wBAAwB;IAWxD;;;;;;;;OAQG;IACG,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,GAChC,OAAO,CAAC,cAAc,CAAC;IAwDpB,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAuB7B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAmB1B,cAAc,CAClB,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,aAAa,GACxB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAqC1B,qBAAqB,CACzB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAwBhC;;;OAGG;IACH,OAAO,CAAC,aAAa;IAef,4BAA4B,CAAC,EACjC,QAAQ,GACT,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QACV,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;QACrC,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7B,CAAC;YAqCY,sBAAsB;YAyBtB,gBAAgB;IAe9B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,UAAU;IASZ,yBAAyB,CAAC,EAC9B,UAAU,EACV,SAAiB,GAClB,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC;YAyBvB,eAAe;CAgC9B"}
|
|
@@ -42,6 +42,7 @@ const fs_1 = __importStar(require("fs"));
|
|
|
42
42
|
const js_jsonl_1 = require("js-jsonl");
|
|
43
43
|
const zlib_1 = __importDefault(require("zlib"));
|
|
44
44
|
const axios_client_internal_1 = require("../http/axios-client-internal");
|
|
45
|
+
const constants_1 = require("../common/constants");
|
|
45
46
|
const helpers_1 = require("../common/helpers");
|
|
46
47
|
const logger_1 = require("../logger/logger");
|
|
47
48
|
class Uploader {
|
|
@@ -145,13 +146,20 @@ class Uploader {
|
|
|
145
146
|
formData.append(field, artifact.form_data[field]);
|
|
146
147
|
}
|
|
147
148
|
formData.append('file', fileStream.data);
|
|
149
|
+
if (fileStream.headers['content-length'] > constants_1.MAX_DEVREV_ARTIFACT_SIZE) {
|
|
150
|
+
console.warn(`File size exceeds the maximum limit of ${constants_1.MAX_DEVREV_ARTIFACT_SIZE} bytes.`);
|
|
151
|
+
this.destroyStream(fileStream);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
148
154
|
try {
|
|
149
155
|
const response = await axios_client_internal_1.axiosClient.post(artifact.upload_url, formData, {
|
|
150
|
-
headers: Object.assign({}, formData.getHeaders()),
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
156
|
+
headers: Object.assign(Object.assign({}, formData.getHeaders()), (!fileStream.headers['content-length']
|
|
157
|
+
? {
|
|
158
|
+
'Content-Length': constants_1.MAX_DEVREV_ARTIFACT_SIZE,
|
|
159
|
+
}
|
|
160
|
+
: {})),
|
|
161
|
+
maxRedirects: 0, // Prevents buffering
|
|
162
|
+
validateStatus: () => true, // Prevents errors on redirects
|
|
155
163
|
});
|
|
156
164
|
this.destroyStream(fileStream);
|
|
157
165
|
return response;
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { Worker } from 'node:worker_threads';
|
|
2
|
-
import { WorkerData } from '../types/workers';
|
|
3
|
-
|
|
2
|
+
import { WorkerData, WorkerMemoryConfig, WorkerResourceLimits } from '../types/workers';
|
|
3
|
+
/**
|
|
4
|
+
* Result of creating a worker, including memory configuration.
|
|
5
|
+
*/
|
|
6
|
+
export interface CreateWorkerResult {
|
|
7
|
+
worker: Worker;
|
|
8
|
+
memoryConfig: WorkerMemoryConfig;
|
|
9
|
+
resourceLimits: WorkerResourceLimits;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a worker thread with optional memory limits.
|
|
13
|
+
* Memory limits are calculated based on the environment:
|
|
14
|
+
* - For Lambda: Uses AWS_LAMBDA_FUNCTION_MEMORY_SIZE (75% for worker)
|
|
15
|
+
* - For local development: Caps total at 1024MB (75% for worker = ~768MB)
|
|
16
|
+
* - For other environments: Uses system memory or V8 heap limit
|
|
17
|
+
*
|
|
18
|
+
* @param workerData - Worker data including event, state, and options
|
|
19
|
+
* @returns Promise resolving to CreateWorkerResult with worker and memory config
|
|
20
|
+
*/
|
|
21
|
+
declare function createWorker<ConnectorState>(workerData: WorkerData<ConnectorState>): Promise<CreateWorkerResult>;
|
|
4
22
|
export { createWorker };
|
|
5
23
|
//# sourceMappingURL=create-worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-worker.d.ts","sourceRoot":"","sources":["../../src/workers/create-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"create-worker.d.ts","sourceRoot":"","sources":["../../src/workers/create-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAiB,MAAM,qBAAqB,CAAC;AAG1E,OAAO,EACL,UAAU,EAEV,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,kBAAkB,CAAC;IACjC,cAAc,EAAE,oBAAoB,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,iBAAe,YAAY,CAAC,cAAc,EACxC,UAAU,EAAE,UAAU,CAAC,cAAc,CAAC,GACrC,OAAO,CAAC,kBAAkB,CAAC,CA8D7B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -2,23 +2,58 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createWorker = createWorker;
|
|
4
4
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
5
|
+
const worker_memory_1 = require("../common/worker-memory");
|
|
5
6
|
const workers_1 = require("../types/workers");
|
|
7
|
+
/**
|
|
8
|
+
* Creates a worker thread with optional memory limits.
|
|
9
|
+
* Memory limits are calculated based on the environment:
|
|
10
|
+
* - For Lambda: Uses AWS_LAMBDA_FUNCTION_MEMORY_SIZE (75% for worker)
|
|
11
|
+
* - For local development: Caps total at 1024MB (75% for worker = ~768MB)
|
|
12
|
+
* - For other environments: Uses system memory or V8 heap limit
|
|
13
|
+
*
|
|
14
|
+
* @param workerData - Worker data including event, state, and options
|
|
15
|
+
* @returns Promise resolving to CreateWorkerResult with worker and memory config
|
|
16
|
+
*/
|
|
6
17
|
async function createWorker(workerData) {
|
|
7
18
|
return new Promise((resolve, reject) => {
|
|
19
|
+
var _a, _b, _c, _d;
|
|
8
20
|
if (node_worker_threads_1.isMainThread) {
|
|
9
21
|
const workerFile = __dirname + '/worker.js';
|
|
10
|
-
|
|
22
|
+
// Calculate memory configuration based on environment
|
|
23
|
+
const isLocalDevelopment = (_b = (_a = workerData.options) === null || _a === void 0 ? void 0 : _a.isLocalDevelopment) !== null && _b !== void 0 ? _b : false;
|
|
24
|
+
const enableMemoryLimits = ((_c = workerData.options) === null || _c === void 0 ? void 0 : _c.enableMemoryLimits) !== false;
|
|
25
|
+
const testMemoryLimitMb = (_d = workerData.options) === null || _d === void 0 ? void 0 : _d.testMemoryLimitMb;
|
|
26
|
+
const memoryConfig = (0, worker_memory_1.calculateWorkerMemoryConfig)(isLocalDevelopment);
|
|
27
|
+
// Allow test override for memory limit
|
|
28
|
+
const effectiveMemoryLimitMb = testMemoryLimitMb !== null && testMemoryLimitMb !== void 0 ? testMemoryLimitMb : memoryConfig.maxOldGenerationSizeMb;
|
|
29
|
+
const resourceLimits = {
|
|
30
|
+
maxOldGenerationSizeMb: effectiveMemoryLimitMb,
|
|
31
|
+
};
|
|
32
|
+
// Build worker options
|
|
33
|
+
const workerOptions = {
|
|
11
34
|
workerData,
|
|
12
|
-
}
|
|
35
|
+
};
|
|
36
|
+
// Apply resource limits if enabled
|
|
37
|
+
if (enableMemoryLimits) {
|
|
38
|
+
workerOptions.resourceLimits = {
|
|
39
|
+
maxOldGenerationSizeMb: resourceLimits.maxOldGenerationSizeMb,
|
|
40
|
+
};
|
|
41
|
+
console.info(`Worker memory limits configured: ` +
|
|
42
|
+
`maxOldGenerationSizeMb=${resourceLimits.maxOldGenerationSizeMb}MB, ` +
|
|
43
|
+
`totalAvailable=${memoryConfig.totalAvailableMemoryMb.toFixed(0)}MB, ` +
|
|
44
|
+
`isLambda=${memoryConfig.isLambda}, ` +
|
|
45
|
+
`isLocalDevelopment=${memoryConfig.isLocalDevelopment}`);
|
|
46
|
+
}
|
|
47
|
+
const worker = new node_worker_threads_1.Worker(workerFile, workerOptions);
|
|
13
48
|
worker.on(workers_1.WorkerEvent.WorkerError, (error) => {
|
|
14
49
|
console.error('Worker error', error);
|
|
15
50
|
reject(error);
|
|
16
51
|
});
|
|
17
52
|
worker.on(workers_1.WorkerEvent.WorkerOnline, () => {
|
|
18
|
-
resolve(worker);
|
|
19
53
|
console.info('Worker is online. Started processing the task with event type: ' +
|
|
20
54
|
workerData.event.payload.event_type +
|
|
21
55
|
'.');
|
|
56
|
+
resolve({ worker, memoryConfig, resourceLimits });
|
|
22
57
|
});
|
|
23
58
|
}
|
|
24
59
|
else {
|