@devrev/airsync-sdk 2.0.0-beta.2 → 2.0.0-beta.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.
- package/dist/airsync-sdk.d.ts +414 -157
- package/dist/attachments-streaming/attachments-streaming-pool.d.ts +2 -1
- package/dist/attachments-streaming/attachments-streaming-pool.d.ts.map +1 -1
- package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts +8 -2
- package/dist/attachments-streaming/attachments-streaming-pool.interfaces.d.ts.map +1 -1
- package/dist/attachments-streaming/attachments-streaming-pool.js +14 -14
- package/dist/attachments-streaming/attachments-streaming-pool.test.js +47 -23
- package/dist/common/time-value-resolver.d.ts +2 -2
- package/dist/common/time-value-resolver.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/multithreading/adapters/base-adapter.d.ts +56 -0
- package/dist/multithreading/adapters/base-adapter.d.ts.map +1 -0
- package/dist/multithreading/adapters/base-adapter.emit.test.d.ts +2 -0
- package/dist/multithreading/adapters/base-adapter.emit.test.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.emit.test.js → adapters/base-adapter.emit.test.js} +66 -53
- package/dist/multithreading/adapters/base-adapter.js +105 -0
- package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts +2 -0
- package/dist/multithreading/adapters/extraction-adapter.artifacts.test.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.artifacts.test.js → adapters/extraction-adapter.artifacts.test.js} +6 -6
- package/dist/multithreading/adapters/extraction-adapter.d.ts +58 -0
- package/dist/multithreading/adapters/extraction-adapter.d.ts.map +1 -0
- package/dist/multithreading/adapters/extraction-adapter.js +325 -0
- package/dist/multithreading/adapters/extraction-adapter.test.d.ts +2 -0
- package/dist/multithreading/adapters/extraction-adapter.test.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.extraction.test.js → adapters/extraction-adapter.test.js} +41 -51
- package/dist/multithreading/adapters/loading-adapter.d.ts +44 -0
- package/dist/multithreading/adapters/loading-adapter.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.helpers.d.ts → adapters/loading-adapter.helpers.d.ts} +1 -1
- package/dist/multithreading/adapters/loading-adapter.helpers.d.ts.map +1 -0
- package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts +2 -0
- package/dist/multithreading/adapters/loading-adapter.helpers.test.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.helpers.test.js → adapters/loading-adapter.helpers.test.js} +26 -26
- package/dist/multithreading/adapters/loading-adapter.js +461 -0
- package/dist/multithreading/adapters/loading-adapter.test.d.ts +2 -0
- package/dist/multithreading/adapters/loading-adapter.test.d.ts.map +1 -0
- package/dist/multithreading/{worker-adapter/worker-adapter.loading.test.js → adapters/loading-adapter.test.js} +19 -26
- package/dist/multithreading/adapters/serialization.test.d.ts +2 -0
- package/dist/multithreading/adapters/serialization.test.d.ts.map +1 -0
- package/dist/multithreading/process-task.d.ts +16 -1
- package/dist/multithreading/process-task.d.ts.map +1 -1
- package/dist/multithreading/process-task.js +97 -49
- package/dist/multithreading/process-task.test.js +15 -15
- package/dist/state/base-state.d.ts +75 -0
- package/dist/state/base-state.d.ts.map +1 -0
- package/dist/state/base-state.js +261 -0
- package/dist/state/extraction-state.d.ts +29 -0
- package/dist/state/extraction-state.d.ts.map +1 -0
- package/dist/state/extraction-state.js +122 -0
- package/dist/state/loading-state.d.ts +19 -0
- package/dist/state/loading-state.d.ts.map +1 -0
- package/dist/state/loading-state.js +40 -0
- package/dist/state/state.extract-window.test.js +7 -7
- package/dist/state/state.interfaces.d.ts +32 -25
- package/dist/state/state.interfaces.d.ts.map +1 -1
- package/dist/state/state.interfaces.js +15 -4
- package/dist/state/state.pending-boundaries.test.js +15 -15
- package/dist/state/state.post-state.test.js +9 -8
- package/dist/state/state.test.js +22 -19
- package/dist/state/state.time-value-resolution.test.js +8 -8
- package/dist/types/extraction.d.ts +3 -3
- package/dist/types/extraction.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/workers.d.ts +16 -15
- package/dist/types/workers.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.artifacts.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.d.ts +0 -97
- package/dist/multithreading/worker-adapter/worker-adapter.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.emit.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.extraction.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.helpers.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.helpers.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.js +0 -846
- package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.loading.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.serialization.test.d.ts.map +0 -1
- package/dist/state/state.d.ts +0 -36
- package/dist/state/state.d.ts.map +0 -1
- package/dist/state/state.js +0 -265
- /package/dist/multithreading/{worker-adapter/worker-adapter.helpers.js → adapters/loading-adapter.helpers.js} +0 -0
- /package/dist/multithreading/{worker-adapter/worker-adapter.serialization.test.js → adapters/serialization.test.js} +0 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const constants_1 = require("../../common/constants");
|
|
4
|
-
const
|
|
4
|
+
const extraction_state_1 = require("../../state/extraction-state");
|
|
5
|
+
const loading_state_1 = require("../../state/loading-state");
|
|
5
6
|
const jest_setup_1 = require("../../tests/jest.setup");
|
|
6
7
|
const test_utils_1 = require("../../common/test-utils");
|
|
7
8
|
const types_1 = require("../../types");
|
|
8
9
|
const loading_1 = require("../../types/loading");
|
|
9
|
-
const
|
|
10
|
+
const extraction_adapter_1 = require("./extraction-adapter");
|
|
11
|
+
const loading_adapter_1 = require("./loading-adapter");
|
|
10
12
|
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
11
13
|
jest.mock('../../common/control-protocol', () => ({
|
|
12
14
|
emit: jest.fn().mockResolvedValue({}),
|
|
@@ -28,20 +30,32 @@ function makeAdapter(eventType = types_1.EventType.StartExtractingData) {
|
|
|
28
30
|
});
|
|
29
31
|
const initialState = {
|
|
30
32
|
attachments: { completed: false },
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
};
|
|
34
|
+
const adapterState = new extraction_state_1.ExtractionState({ event, initialState });
|
|
35
|
+
adapterState.sdkState.snapInVersionId = '';
|
|
36
|
+
adapterState.sdkState.toDevRev = {
|
|
37
|
+
attachmentsMetadata: {
|
|
38
|
+
artifactIds: [],
|
|
39
|
+
lastProcessed: 0,
|
|
40
|
+
lastProcessedAttachmentsIdsList: [],
|
|
38
41
|
},
|
|
39
42
|
};
|
|
40
|
-
const
|
|
41
|
-
const adapter = new worker_adapter_1.WorkerAdapter({ event, adapterState });
|
|
43
|
+
const adapter = new extraction_adapter_1.ExtractionAdapter({ event, adapterState });
|
|
42
44
|
return { adapter, event, adapterState };
|
|
43
45
|
}
|
|
44
|
-
|
|
46
|
+
function makeLoadingAdapter(eventType = types_1.EventType.StartLoadingData) {
|
|
47
|
+
const event = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
|
|
48
|
+
payload: { event_type: eventType },
|
|
49
|
+
});
|
|
50
|
+
const initialState = {
|
|
51
|
+
attachments: { completed: false },
|
|
52
|
+
};
|
|
53
|
+
const adapterState = new loading_state_1.LoadingState({ event, initialState });
|
|
54
|
+
adapterState.sdkState.snapInVersionId = '';
|
|
55
|
+
const adapter = new loading_adapter_1.LoadingAdapter({ event, adapterState });
|
|
56
|
+
return { adapter, event, adapterState };
|
|
57
|
+
}
|
|
58
|
+
describe(`${extraction_adapter_1.ExtractionAdapter.name}.emit`, () => {
|
|
45
59
|
let adapter;
|
|
46
60
|
let mockPostMessage;
|
|
47
61
|
beforeEach(() => {
|
|
@@ -150,14 +164,16 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
|
|
|
150
164
|
it('should include reports and processed_files in data for loader events', async () => {
|
|
151
165
|
// Arrange
|
|
152
166
|
const { emit: mockEmit } = require('../../common/control-protocol');
|
|
153
|
-
adapter
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
const { adapter: loadingAdapter } = makeLoadingAdapter();
|
|
168
|
+
loadingAdapter['adapterState'].postState = jest
|
|
169
|
+
.fn()
|
|
170
|
+
.mockResolvedValue(undefined);
|
|
171
|
+
loadingAdapter['loaderReports'] = [
|
|
156
172
|
{ item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
|
|
157
173
|
];
|
|
158
|
-
|
|
174
|
+
loadingAdapter['_processedFiles'] = ['file-1', 'file-2'];
|
|
159
175
|
// Act
|
|
160
|
-
await
|
|
176
|
+
await loadingAdapter.emit(types_1.LoaderEventType.DataLoadingDone);
|
|
161
177
|
// Assert
|
|
162
178
|
expect(mockEmit).toHaveBeenCalledWith(expect.objectContaining({
|
|
163
179
|
data: expect.objectContaining({
|
|
@@ -178,10 +194,6 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
|
|
|
178
194
|
adapter['_artifacts'] = [
|
|
179
195
|
{ id: 'art-1', item_count: 10, item_type: 'issues' },
|
|
180
196
|
];
|
|
181
|
-
adapter['loaderReports'] = [
|
|
182
|
-
{ item_type: 'tasks', [loading_1.ActionType.CREATED]: 5 },
|
|
183
|
-
];
|
|
184
|
-
adapter['_processedFiles'] = ['file-1'];
|
|
185
197
|
// Act
|
|
186
198
|
await adapter.emit('SOME_UNKNOWN_EVENT');
|
|
187
199
|
// Assert
|
|
@@ -227,15 +239,15 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
|
|
|
227
239
|
types_1.LoaderEventType.AttachmentLoadingDone,
|
|
228
240
|
types_1.LoaderEventType.AttachmentLoadingProgress,
|
|
229
241
|
];
|
|
242
|
+
const { adapter: loadingAdapter } = makeLoadingAdapter();
|
|
243
|
+
loadingAdapter['adapterState'].postState = jest
|
|
244
|
+
.fn()
|
|
245
|
+
.mockResolvedValue(undefined);
|
|
230
246
|
for (const eventType of loaderEvents) {
|
|
231
247
|
jest.clearAllMocks();
|
|
232
|
-
|
|
233
|
-
adapter['adapterState'].postState = jest
|
|
234
|
-
.fn()
|
|
235
|
-
.mockResolvedValue(undefined);
|
|
236
|
-
adapter.uploadAllRepos = jest.fn().mockResolvedValue(undefined);
|
|
248
|
+
loadingAdapter.hasWorkerEmitted = false;
|
|
237
249
|
// Act
|
|
238
|
-
await
|
|
250
|
+
await loadingAdapter.emit(eventType);
|
|
239
251
|
// Assert
|
|
240
252
|
const callData = (_b = (_a = mockEmit.mock.calls[0]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.data;
|
|
241
253
|
expect(callData).toHaveProperty('reports');
|
|
@@ -262,10 +274,11 @@ describe(`${worker_adapter_1.WorkerAdapter.name}.emit`, () => {
|
|
|
262
274
|
});
|
|
263
275
|
describe('WorkerAdapter — workersOldest / workersNewest boundary updates', () => {
|
|
264
276
|
let adapter;
|
|
277
|
+
let adapterState;
|
|
265
278
|
let mockPostMessage;
|
|
266
279
|
beforeEach(() => {
|
|
267
280
|
jest.clearAllMocks();
|
|
268
|
-
({ adapter } = makeAdapter());
|
|
281
|
+
({ adapter, adapterState } = makeAdapter());
|
|
269
282
|
const workerThreads = require('node:worker_threads');
|
|
270
283
|
mockPostMessage = jest.fn();
|
|
271
284
|
if (workerThreads.parentPort) {
|
|
@@ -295,75 +308,75 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
|
|
|
295
308
|
describe('initial import with UNBOUNDED start', () => {
|
|
296
309
|
it('should set workersOldest to UNBOUNDED_DATE_TIME_VALUE and workersNewest to extraction end', async () => {
|
|
297
310
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
298
|
-
expect(
|
|
299
|
-
expect(
|
|
311
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
312
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
|
|
300
313
|
});
|
|
301
314
|
});
|
|
302
315
|
describe('reconciliation after UNBOUNDED initial import', () => {
|
|
303
316
|
it('should NOT overwrite workersOldest when reconciliation start is later than sentinel', async () => {
|
|
304
317
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
305
318
|
await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
|
|
306
|
-
expect(
|
|
307
|
-
expect(
|
|
319
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
320
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
|
|
308
321
|
});
|
|
309
322
|
it('should NOT overwrite workersOldest even when reconciliation start is very early', async () => {
|
|
310
323
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
311
324
|
await emitDone(adapter, '1980-01-01T00:00:00.000Z', '1990-01-01T00:00:00.000Z');
|
|
312
|
-
expect(
|
|
313
|
-
expect(
|
|
325
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
326
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-06-01T00:00:00.000Z');
|
|
314
327
|
});
|
|
315
328
|
});
|
|
316
329
|
describe('forward sync after UNBOUNDED initial import', () => {
|
|
317
330
|
it('should expand workersNewest forward while preserving workersOldest', async () => {
|
|
318
331
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
319
332
|
await emitDone(adapter, '2025-06-01T00:00:00.000Z', '2025-07-01T00:00:00.000Z');
|
|
320
|
-
expect(
|
|
321
|
-
expect(
|
|
333
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
334
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-07-01T00:00:00.000Z');
|
|
322
335
|
});
|
|
323
336
|
});
|
|
324
337
|
describe('reconciliation with end beyond current newest', () => {
|
|
325
338
|
it('should expand workersNewest when reconciliation end is later', async () => {
|
|
326
339
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
327
340
|
await emitDone(adapter, '2024-01-01T00:00:00.000Z', '2025-08-01T00:00:00.000Z');
|
|
328
|
-
expect(
|
|
329
|
-
expect(
|
|
341
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
342
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-08-01T00:00:00.000Z');
|
|
330
343
|
});
|
|
331
344
|
});
|
|
332
345
|
describe('first sync with absolute dates (no UNBOUNDED)', () => {
|
|
333
346
|
it('should set both boundaries from the extraction range', async () => {
|
|
334
347
|
await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
|
|
335
|
-
expect(
|
|
336
|
-
expect(
|
|
348
|
+
expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
|
|
349
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
|
|
337
350
|
});
|
|
338
351
|
});
|
|
339
352
|
describe('reconciliation after absolute initial sync', () => {
|
|
340
353
|
it('should expand workersOldest backward when reconciliation start is earlier', async () => {
|
|
341
354
|
await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
|
|
342
355
|
await emitDone(adapter, '2024-06-01T00:00:00.000Z', '2025-02-01T00:00:00.000Z');
|
|
343
|
-
expect(
|
|
344
|
-
expect(
|
|
356
|
+
expect(adapterState.sdkState.workersOldest).toBe('2024-06-01T00:00:00.000Z');
|
|
357
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
|
|
345
358
|
});
|
|
346
359
|
it('should NOT change boundaries when reconciliation is within existing range', async () => {
|
|
347
360
|
await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
|
|
348
361
|
await emitDone(adapter, '2025-01-15T00:00:00.000Z', '2025-02-15T00:00:00.000Z');
|
|
349
|
-
expect(
|
|
350
|
-
expect(
|
|
362
|
+
expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
|
|
363
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
|
|
351
364
|
});
|
|
352
365
|
it('should expand both boundaries when reconciliation exceeds both', async () => {
|
|
353
366
|
await emitDone(adapter, '2025-01-01T00:00:00.000Z', '2025-03-01T00:00:00.000Z');
|
|
354
367
|
await emitDone(adapter, '2024-06-01T00:00:00.000Z', '2025-09-01T00:00:00.000Z');
|
|
355
|
-
expect(
|
|
356
|
-
expect(
|
|
368
|
+
expect(adapterState.sdkState.workersOldest).toBe('2024-06-01T00:00:00.000Z');
|
|
369
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-09-01T00:00:00.000Z');
|
|
357
370
|
});
|
|
358
371
|
});
|
|
359
372
|
describe('multiple forward syncs', () => {
|
|
360
373
|
it('should progressively expand workersNewest while preserving workersOldest', async () => {
|
|
361
374
|
await emitDone(adapter, constants_1.UNBOUNDED_DATE_TIME_VALUE, '2025-06-01T00:00:00.000Z');
|
|
362
375
|
await emitDone(adapter, '2025-06-01T00:00:00.000Z', '2025-07-01T00:00:00.000Z');
|
|
363
|
-
expect(
|
|
376
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-07-01T00:00:00.000Z');
|
|
364
377
|
await emitDone(adapter, '2025-07-01T00:00:00.000Z', '2025-08-01T00:00:00.000Z');
|
|
365
|
-
expect(
|
|
366
|
-
expect(
|
|
378
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-08-01T00:00:00.000Z');
|
|
379
|
+
expect(adapterState.sdkState.workersOldest).toBe(constants_1.UNBOUNDED_DATE_TIME_VALUE);
|
|
367
380
|
});
|
|
368
381
|
});
|
|
369
382
|
describe('non-AttachmentExtractionDone events should NOT update boundaries', () => {
|
|
@@ -373,8 +386,8 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
|
|
|
373
386
|
types_1.ExtractorEventType.MetadataExtractionError,
|
|
374
387
|
types_1.ExtractorEventType.AttachmentExtractionError,
|
|
375
388
|
])('should not update boundaries on %s', async (eventType) => {
|
|
376
|
-
|
|
377
|
-
|
|
389
|
+
adapterState.sdkState.workersOldest = '2025-01-01T00:00:00.000Z';
|
|
390
|
+
adapterState.sdkState.workersNewest = '2025-03-01T00:00:00.000Z';
|
|
378
391
|
adapter.event.payload.event_context.extract_from =
|
|
379
392
|
'2024-01-01T00:00:00.000Z';
|
|
380
393
|
adapter.event.payload.event_context.extract_to =
|
|
@@ -383,8 +396,8 @@ describe('WorkerAdapter — workersOldest / workersNewest boundary updates', ()
|
|
|
383
396
|
reports: [],
|
|
384
397
|
processed_files: [],
|
|
385
398
|
});
|
|
386
|
-
expect(
|
|
387
|
-
expect(
|
|
399
|
+
expect(adapterState.sdkState.workersOldest).toBe('2025-01-01T00:00:00.000Z');
|
|
400
|
+
expect(adapterState.sdkState.workersNewest).toBe('2025-03-01T00:00:00.000Z');
|
|
388
401
|
});
|
|
389
402
|
});
|
|
390
403
|
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseAdapter = void 0;
|
|
4
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
5
|
+
const constants_1 = require("../../common/constants");
|
|
6
|
+
const control_protocol_1 = require("../../common/control-protocol");
|
|
7
|
+
const helpers_1 = require("../../common/helpers");
|
|
8
|
+
const logger_1 = require("../../logger/logger");
|
|
9
|
+
const logger_context_1 = require("../../logger/logger.context");
|
|
10
|
+
const workers_1 = require("../../types/workers");
|
|
11
|
+
const uploader_1 = require("../../uploader/uploader");
|
|
12
|
+
/**
|
|
13
|
+
* BaseAdapter holds the state and behavior shared by both sync modes and owns
|
|
14
|
+
* the `emit` control-protocol flow as a template method. Mode-specific adapters
|
|
15
|
+
* (`ExtractionAdapter`, `LoadingAdapter`) implement the abstract hooks to inject
|
|
16
|
+
* their own pre-emit work and event payload shaping.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam ConnectorState - the connector-owned state shape
|
|
19
|
+
* @typeParam StateClass - the mode's `BaseState` subclass
|
|
20
|
+
*/
|
|
21
|
+
class BaseAdapter {
|
|
22
|
+
constructor({ event, adapterState, options, }) {
|
|
23
|
+
this.event = event;
|
|
24
|
+
this.options = options;
|
|
25
|
+
this.adapterState = adapterState;
|
|
26
|
+
this.hasWorkerEmitted = false;
|
|
27
|
+
this.isTimeout = false;
|
|
28
|
+
this.uploader = new uploader_1.Uploader({
|
|
29
|
+
event,
|
|
30
|
+
options,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
get state() {
|
|
34
|
+
return this.adapterState.state;
|
|
35
|
+
}
|
|
36
|
+
set state(value) {
|
|
37
|
+
this.adapterState.state = value;
|
|
38
|
+
}
|
|
39
|
+
async postState() {
|
|
40
|
+
return (0, logger_context_1.runWithSdkLogContext)(async () => {
|
|
41
|
+
await this.adapterState.postState();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Emits an event to the platform.
|
|
46
|
+
*
|
|
47
|
+
* @param newEventType - The event type to be emitted
|
|
48
|
+
* @param data - The data to be sent with the event
|
|
49
|
+
*/
|
|
50
|
+
async emit(newEventType, data) {
|
|
51
|
+
return (0, logger_context_1.runWithSdkLogContext)(async () => {
|
|
52
|
+
var _a;
|
|
53
|
+
if (this.hasWorkerEmitted) {
|
|
54
|
+
console.warn(`Trying to emit event with event type: ${newEventType}. Ignoring emit request because it has already been emitted.`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
await this.beforeEmit(newEventType);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error('Error while preparing to emit event', error);
|
|
62
|
+
node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
|
|
63
|
+
this.hasWorkerEmitted = true;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// We want to save the state every time we emit an event, except for the start and delete events
|
|
67
|
+
if (!constants_1.STATELESS_EVENT_TYPES.includes(this.event.payload.event_type)) {
|
|
68
|
+
console.log(`Saving state before emitting event with event type: ${newEventType}.`);
|
|
69
|
+
try {
|
|
70
|
+
await this.adapterState.postState();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('Error while posting state', error);
|
|
74
|
+
node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
|
|
75
|
+
this.hasWorkerEmitted = true;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
// Always prune error messages to make them shorter before emit
|
|
81
|
+
if ((_a = data === null || data === void 0 ? void 0 : data.error) === null || _a === void 0 ? void 0 : _a.message) {
|
|
82
|
+
data.error.message = (0, helpers_1.truncateMessage)(data.error.message);
|
|
83
|
+
}
|
|
84
|
+
await (0, control_protocol_1.emit)({
|
|
85
|
+
eventType: newEventType,
|
|
86
|
+
event: this.event,
|
|
87
|
+
data: Object.assign(Object.assign({}, data), this.buildEmitPayload(newEventType)),
|
|
88
|
+
});
|
|
89
|
+
const message = {
|
|
90
|
+
subject: workers_1.WorkerMessageSubject.WorkerMessageEmitted,
|
|
91
|
+
payload: { eventType: newEventType },
|
|
92
|
+
};
|
|
93
|
+
this.afterEmit(newEventType);
|
|
94
|
+
node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(message);
|
|
95
|
+
this.hasWorkerEmitted = true;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error(`Error while emitting event with event type: ${newEventType}.`, (0, logger_1.serializeError)(error));
|
|
99
|
+
node_worker_threads_1.parentPort === null || node_worker_threads_1.parentPort === void 0 ? void 0 : node_worker_threads_1.parentPort.postMessage(workers_1.WorkerMessageSubject.WorkerMessageExit);
|
|
100
|
+
this.hasWorkerEmitted = true;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.BaseAdapter = BaseAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-adapter.artifacts.test.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/extraction-adapter.artifacts.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const constants_1 = require("../../common/constants");
|
|
4
|
-
const
|
|
4
|
+
const extraction_state_1 = require("../../state/extraction-state");
|
|
5
5
|
const jest_setup_1 = require("../../tests/jest.setup");
|
|
6
6
|
const test_helpers_1 = require("../../tests/test-helpers");
|
|
7
7
|
const test_utils_1 = require("../../common/test-utils");
|
|
8
8
|
const types_1 = require("../../types");
|
|
9
|
-
const
|
|
9
|
+
const extraction_adapter_1 = require("./extraction-adapter");
|
|
10
10
|
// 1. Create a mock function for the method you want to override.
|
|
11
11
|
const mockUpload = (itemType, objects) => {
|
|
12
12
|
return {
|
|
@@ -55,11 +55,11 @@ describe('Artifact ordering when artifacts overflow batch sizes in repositories'
|
|
|
55
55
|
const mockEvent = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
|
|
56
56
|
payload: { event_type: types_1.EventType.StartExtractingData },
|
|
57
57
|
});
|
|
58
|
-
const mockAdapterState = new
|
|
58
|
+
const mockAdapterState = new extraction_state_1.ExtractionState({
|
|
59
59
|
event: mockEvent,
|
|
60
60
|
initialState: { attachments: { completed: false } },
|
|
61
61
|
});
|
|
62
|
-
testAdapter = new
|
|
62
|
+
testAdapter = new extraction_adapter_1.ExtractionAdapter({
|
|
63
63
|
event: mockEvent,
|
|
64
64
|
adapterState: mockAdapterState,
|
|
65
65
|
options: {
|
|
@@ -136,11 +136,11 @@ describe('External sync units splitting into artifacts', () => {
|
|
|
136
136
|
const mockEvent = (0, test_utils_1.createMockEvent)(jest_setup_1.mockServer.baseUrl, {
|
|
137
137
|
payload: { event_type: types_1.EventType.StartExtractingExternalSyncUnits },
|
|
138
138
|
});
|
|
139
|
-
const mockAdapterState = new
|
|
139
|
+
const mockAdapterState = new extraction_state_1.ExtractionState({
|
|
140
140
|
event: mockEvent,
|
|
141
141
|
initialState: {},
|
|
142
142
|
});
|
|
143
|
-
testAdapter = new
|
|
143
|
+
testAdapter = new extraction_adapter_1.ExtractionAdapter({
|
|
144
144
|
event: mockEvent,
|
|
145
145
|
adapterState: mockAdapterState,
|
|
146
146
|
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Repo } from '../../repo/repo';
|
|
2
|
+
import { NormalizedAttachment, RepoInterface } from '../../repo/repo.interfaces';
|
|
3
|
+
import { ExtractionState } from '../../state/extraction-state';
|
|
4
|
+
import { AirSyncEvent, ExternalSystemAttachmentProcessors, ExternalSystemAttachmentStreamingFunction, ExtractorEventType, EventData, ProcessAttachmentReturnType, StreamAttachmentsReturnType } from '../../types/extraction';
|
|
5
|
+
import { LoaderEventType } from '../../types/loading';
|
|
6
|
+
import { WorkerAdapterOptions } from '../../types/workers';
|
|
7
|
+
import { Artifact } from '../../uploader/uploader.interfaces';
|
|
8
|
+
import { BaseAdapter } from './base-adapter';
|
|
9
|
+
/**
|
|
10
|
+
* ExtractionAdapter is the adapter passed to extraction tasks. It exposes the
|
|
11
|
+
* extraction surface (repos, artifacts, attachment streaming) and updates the
|
|
12
|
+
* extraction boundaries before emitting.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export declare class ExtractionAdapter<ConnectorState> extends BaseAdapter<ConnectorState, ExtractionState<ConnectorState>> {
|
|
17
|
+
private _artifacts;
|
|
18
|
+
private repos;
|
|
19
|
+
private currentEventDataLength;
|
|
20
|
+
constructor(params: {
|
|
21
|
+
event: AirSyncEvent;
|
|
22
|
+
adapterState: ExtractionState<ConnectorState>;
|
|
23
|
+
options?: WorkerAdapterOptions;
|
|
24
|
+
});
|
|
25
|
+
get extractionScope(): import("../../types/workers").ExtractionScope;
|
|
26
|
+
/**
|
|
27
|
+
* Returns whether the given item type should be extracted.
|
|
28
|
+
* Defaults to true if the scope is empty or the item type is not listed.
|
|
29
|
+
*/
|
|
30
|
+
shouldExtract(itemType: string): boolean;
|
|
31
|
+
initializeRepos(repos: RepoInterface[]): void;
|
|
32
|
+
getRepo(itemType: string): Repo | undefined;
|
|
33
|
+
get artifacts(): Artifact[];
|
|
34
|
+
set artifacts(artifacts: Artifact[]);
|
|
35
|
+
protected beforeEmit(newEventType: ExtractorEventType | LoaderEventType): Promise<void>;
|
|
36
|
+
protected buildEmitPayload(newEventType: ExtractorEventType | LoaderEventType): EventData;
|
|
37
|
+
protected afterEmit(): void;
|
|
38
|
+
uploadAllRepos(): Promise<void>;
|
|
39
|
+
processAttachment(attachment: NormalizedAttachment, stream: ExternalSystemAttachmentStreamingFunction): Promise<ProcessAttachmentReturnType>;
|
|
40
|
+
/**
|
|
41
|
+
* Destroys a stream to prevent memory leaks.
|
|
42
|
+
* @param httpStream - The axios response stream to destroy
|
|
43
|
+
*/
|
|
44
|
+
private destroyHttpStream;
|
|
45
|
+
/**
|
|
46
|
+
* Streams the attachments to the DevRev platform.
|
|
47
|
+
* The attachments are streamed to the platform and the artifact information is returned.
|
|
48
|
+
* @param params - The parameters to stream the attachments
|
|
49
|
+
* @returns The response object containing the ssorAttachment artifact information
|
|
50
|
+
* or error information if there was an error
|
|
51
|
+
*/
|
|
52
|
+
streamAttachments<NewBatch>({ stream, processors, batchSize, }: {
|
|
53
|
+
stream: ExternalSystemAttachmentStreamingFunction;
|
|
54
|
+
processors?: ExternalSystemAttachmentProcessors<ConnectorState, NormalizedAttachment[], NewBatch>;
|
|
55
|
+
batchSize?: number;
|
|
56
|
+
}): Promise<StreamAttachmentsReturnType>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=extraction-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-adapter.d.ts","sourceRoot":"","sources":["../../../src/multithreading/adapters/extraction-adapter.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,oBAAoB,EACpB,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EACL,YAAY,EACZ,kCAAkC,EAClC,yCAAyC,EACzC,kBAAkB,EAClB,SAAS,EACT,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAkB,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;GAMG;AACH,qBAAa,iBAAiB,CAAC,cAAc,CAAE,SAAQ,WAAW,CAChE,cAAc,EACd,eAAe,CAAC,cAAc,CAAC,CAChC;IACC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,sBAAsB,CAAa;gBAE/B,MAAM,EAAE;QAClB,KAAK,EAAE,YAAY,CAAC;QACpB,YAAY,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC;QAC9C,OAAO,CAAC,EAAE,oBAAoB,CAAC;KAChC;IAKD,IAAI,eAAe,kDAElB;IAED;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAOxC,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE;IAuCtC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAa3C,IAAI,SAAS,IAAI,QAAQ,EAAE,CAE1B;IAED,IAAI,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,EAIlC;cAEe,UAAU,CACxB,YAAY,EAAE,kBAAkB,GAAG,eAAe,GACjD,OAAO,CAAC,IAAI,CAAC;IAyChB,SAAS,CAAC,gBAAgB,CACxB,YAAY,EAAE,kBAAkB,GAAG,eAAe,GACjD,SAAS;IAOZ,SAAS,CAAC,SAAS,IAAI,IAAI;IAIrB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAU/B,iBAAiB,CACrB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,yCAAyC,GAChD,OAAO,CAAC,2BAA2B,CAAC;IA+GvC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;OAMG;IACG,iBAAiB,CAAC,QAAQ,EAAE,EAChC,MAAM,EACN,UAAU,EACV,SAAa,GACd,EAAE;QACD,MAAM,EAAE,yCAAyC,CAAC;QAClD,UAAU,CAAC,EAAE,kCAAkC,CAC7C,cAAc,EACd,oBAAoB,EAAE,EACtB,QAAQ,CACT,CAAC;QACF,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,2BAA2B,CAAC;CAyIzC"}
|