@devrev/airsync-sdk 2.0.0-beta.1 → 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/README.md +0 -4
- package/dist/airsync-sdk.d.ts +2059 -0
- 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 +27 -16
- package/dist/attachments-streaming/attachments-streaming-pool.test.js +246 -27
- package/dist/common/constants.d.ts +16 -5
- package/dist/common/constants.d.ts.map +1 -1
- package/dist/common/constants.js +20 -6
- package/dist/common/control-protocol.d.ts +2 -2
- package/dist/common/control-protocol.d.ts.map +1 -1
- package/dist/common/control-protocol.js +1 -5
- package/dist/common/helpers.d.ts +8 -0
- package/dist/common/helpers.d.ts.map +1 -1
- package/dist/common/helpers.js +15 -0
- package/dist/common/install-initial-domain-mapping.d.ts +2 -2
- package/dist/common/install-initial-domain-mapping.test.js +5 -2
- package/dist/common/test-utils.d.ts +19 -0
- package/dist/common/test-utils.d.ts.map +1 -0
- package/dist/common/test-utils.js +101 -0
- package/dist/common/time-value-resolver.d.ts +47 -0
- package/dist/common/time-value-resolver.d.ts.map +1 -0
- package/dist/common/time-value-resolver.js +141 -0
- package/dist/common/time-value-resolver.test.d.ts +2 -0
- package/dist/common/time-value-resolver.test.d.ts.map +1 -0
- package/dist/common/time-value-resolver.test.js +268 -0
- package/dist/http/axios-client-internal.d.ts.map +1 -1
- package/dist/http/axios-client-internal.js +7 -0
- package/dist/http/axios-client-internal.test.js +21 -0
- package/dist/http/axios-client.d.ts.map +1 -1
- package/dist/http/axios-client.js +6 -3
- package/dist/http/index.d.ts +0 -1
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +0 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -13
- package/dist/logger/logger.d.ts +1 -17
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.interfaces.d.ts +2 -2
- package/dist/logger/logger.js +35 -27
- package/dist/logger/logger.test.js +66 -19
- package/dist/mappers/mappers.interface.d.ts +5 -5
- package/dist/mappers/mappers.interface.js +3 -3
- package/dist/mappers/mappers.test.js +8 -10
- package/dist/mock-server/mock-server.d.ts +47 -0
- package/dist/mock-server/mock-server.d.ts.map +1 -0
- package/dist/mock-server/mock-server.interfaces.d.ts +73 -0
- package/dist/mock-server/mock-server.interfaces.d.ts.map +1 -0
- package/dist/mock-server/mock-server.interfaces.js +4 -0
- package/dist/mock-server/mock-server.js +278 -0
- 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/adapters/base-adapter.emit.test.js +403 -0
- 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} +53 -5
- 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/adapters/extraction-adapter.test.js +789 -0
- 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/adapters/loading-adapter.test.js +589 -0
- package/dist/multithreading/adapters/serialization.test.d.ts +2 -0
- package/dist/multithreading/adapters/serialization.test.d.ts.map +1 -0
- package/dist/multithreading/adapters/serialization.test.js +71 -0
- package/dist/multithreading/create-worker.test.js +36 -17
- 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 -82
- package/dist/multithreading/process-task.test.d.ts +2 -0
- package/dist/multithreading/process-task.test.d.ts.map +1 -0
- package/dist/multithreading/process-task.test.js +146 -0
- package/dist/multithreading/spawn/spawn.d.ts +3 -3
- package/dist/multithreading/spawn/spawn.d.ts.map +1 -1
- package/dist/multithreading/spawn/spawn.helpers.d.ts.map +1 -1
- package/dist/multithreading/spawn/spawn.helpers.js +6 -14
- package/dist/multithreading/spawn/spawn.helpers.test.js +8 -8
- package/dist/multithreading/spawn/spawn.js +20 -25
- package/dist/multithreading/spawn/spawn.test.d.ts +2 -0
- package/dist/multithreading/spawn/spawn.test.d.ts.map +1 -0
- package/dist/multithreading/spawn/spawn.test.js +232 -0
- package/dist/repo/repo.d.ts.map +1 -1
- package/dist/repo/repo.interfaces.d.ts +4 -2
- package/dist/repo/repo.interfaces.d.ts.map +1 -1
- package/dist/repo/repo.js +4 -3
- package/dist/repo/repo.test.js +60 -7
- 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.d.ts +2 -0
- package/dist/state/state.extract-window.test.d.ts.map +1 -0
- package/dist/state/state.extract-window.test.js +163 -0
- package/dist/state/state.interfaces.d.ts +44 -27
- package/dist/state/state.interfaces.d.ts.map +1 -1
- package/dist/state/state.interfaces.js +18 -5
- package/dist/state/state.pending-boundaries.test.d.ts +2 -0
- package/dist/state/state.pending-boundaries.test.d.ts.map +1 -0
- package/dist/state/state.pending-boundaries.test.js +189 -0
- package/dist/state/state.post-state.test.d.ts +2 -0
- package/dist/state/state.post-state.test.d.ts.map +1 -0
- package/dist/state/state.post-state.test.js +78 -0
- package/dist/state/state.test.js +135 -88
- package/dist/state/state.time-value-resolution.test.d.ts +2 -0
- package/dist/state/state.time-value-resolution.test.d.ts.map +1 -0
- package/dist/state/state.time-value-resolution.test.js +175 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/types/common.d.ts +0 -25
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/common.js +1 -11
- package/dist/types/external-domain-metadata.d.ts +20 -1
- package/dist/types/external-domain-metadata.d.ts.map +1 -1
- package/dist/types/extraction.d.ts +92 -221
- package/dist/types/extraction.d.ts.map +1 -1
- package/dist/types/extraction.js +56 -124
- package/dist/types/extraction.test.js +69 -43
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +6 -3
- package/dist/types/loading.d.ts +4 -24
- package/dist/types/loading.d.ts.map +1 -1
- package/dist/types/loading.js +1 -22
- package/dist/types/workers.d.ts +47 -29
- package/dist/types/workers.d.ts.map +1 -1
- package/dist/types/workers.js +1 -0
- package/dist/uploader/uploader.d.ts +1 -0
- package/dist/uploader/uploader.d.ts.map +1 -1
- package/dist/uploader/uploader.helpers.test.js +0 -11
- package/dist/uploader/uploader.interfaces.d.ts +3 -3
- package/dist/uploader/uploader.js +53 -20
- package/dist/uploader/uploader.test.js +22 -10
- package/package.json +10 -13
- package/dist/common/event-type-translation.d.ts +0 -24
- package/dist/common/event-type-translation.d.ts.map +0 -1
- package/dist/common/event-type-translation.js +0 -117
- package/dist/deprecated/adapter/index.d.ts +0 -62
- package/dist/deprecated/adapter/index.d.ts.map +0 -1
- package/dist/deprecated/adapter/index.js +0 -151
- package/dist/deprecated/common/helpers.d.ts +0 -7
- package/dist/deprecated/common/helpers.d.ts.map +0 -1
- package/dist/deprecated/common/helpers.js +0 -47
- package/dist/deprecated/demo-extractor/external_domain_metadata.json +0 -38
- package/dist/deprecated/demo-extractor/index.d.ts +0 -18
- package/dist/deprecated/demo-extractor/index.d.ts.map +0 -1
- package/dist/deprecated/demo-extractor/index.js +0 -161
- package/dist/deprecated/http/client.d.ts +0 -22
- package/dist/deprecated/http/client.d.ts.map +0 -1
- package/dist/deprecated/http/client.js +0 -161
- package/dist/deprecated/uploader/index.d.ts +0 -35
- package/dist/deprecated/uploader/index.d.ts.map +0 -1
- package/dist/deprecated/uploader/index.js +0 -161
- package/dist/http/types.d.ts +0 -17
- package/dist/http/types.d.ts.map +0 -1
- package/dist/http/types.js +0 -2
- 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 -91
- package/dist/multithreading/worker-adapter/worker-adapter.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 -745
- package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts +0 -2
- package/dist/multithreading/worker-adapter/worker-adapter.test.d.ts.map +0 -1
- package/dist/multithreading/worker-adapter/worker-adapter.test.js +0 -483
- package/dist/state/state.d.ts +0 -30
- package/dist/state/state.d.ts.map +0 -1
- package/dist/state/state.js +0 -166
- /package/dist/multithreading/{worker-adapter/worker-adapter.helpers.js → adapters/loading-adapter.helpers.js} +0 -0
|
@@ -3,12 +3,13 @@ import { AttachmentsStreamingPoolParams } from './attachments-streaming-pool.int
|
|
|
3
3
|
export declare class AttachmentsStreamingPool<ConnectorState> {
|
|
4
4
|
private adapter;
|
|
5
5
|
private attachments;
|
|
6
|
+
private attachmentsMetadata;
|
|
6
7
|
private batchSize;
|
|
7
8
|
private delay;
|
|
8
9
|
private stream;
|
|
9
10
|
private totalProcessedCount;
|
|
10
11
|
private readonly PROGRESS_REPORT_INTERVAL;
|
|
11
|
-
constructor({ adapter, attachments, batchSize, stream, }: AttachmentsStreamingPoolParams<ConnectorState>);
|
|
12
|
+
constructor({ adapter, attachments, attachmentsMetadata, batchSize, stream, }: AttachmentsStreamingPoolParams<ConnectorState>);
|
|
12
13
|
private updateProgress;
|
|
13
14
|
/**
|
|
14
15
|
* Migrates processed attachments from the legacy string[] format to the new ProcessedAttachment[] format.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachments-streaming-pool.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attachments-streaming-pool.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,2BAA2B,EAC5B,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AAEzF,qBAAa,wBAAwB,CAAC,cAAc;IAClD,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,mBAAmB,CAA8C;IACzE,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,MAAM,CAA4C;IAE1D,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAM;gBAEnC,EACV,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,SAAc,EACd,MAAM,GACP,EAAE,8BAA8B,CAAC,cAAc,CAAC;YASnC,cAAc;IAS5B;;;;;OAKG;IAEH,OAAO,CAAC,2BAA2B;IAsB7B,SAAS,IAAI,OAAO,CAAC,2BAA2B,CAAC;IAyCjD,kBAAkB;CAuFzB"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { ExternalSystemAttachmentStreamingFunction, NormalizedAttachment } from '../types';
|
|
2
|
-
import {
|
|
2
|
+
import { ExtractionAdapter } from '../multithreading/adapters/extraction-adapter';
|
|
3
|
+
import { ToDevRev } from '../state/state.interfaces';
|
|
3
4
|
export interface AttachmentsStreamingPoolParams<ConnectorState> {
|
|
4
|
-
adapter:
|
|
5
|
+
adapter: ExtractionAdapter<ConnectorState>;
|
|
5
6
|
attachments: NormalizedAttachment[];
|
|
7
|
+
/**
|
|
8
|
+
* SDK-owned attachments bookkeeping. Passed in directly so the pool does not
|
|
9
|
+
* reach into the (now-encapsulated) adapter state.
|
|
10
|
+
*/
|
|
11
|
+
attachmentsMetadata: ToDevRev['attachmentsMetadata'] | undefined;
|
|
6
12
|
batchSize?: number;
|
|
7
13
|
stream: ExternalSystemAttachmentStreamingFunction;
|
|
8
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachments-streaming-pool.interfaces.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yCAAyC,EACzC,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"attachments-streaming-pool.interfaces.d.ts","sourceRoot":"","sources":["../../src/attachments-streaming/attachments-streaming-pool.interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yCAAyC,EACzC,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,MAAM,WAAW,8BAA8B,CAAC,cAAc;IAC5D,OAAO,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAC3C,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC;;;OAGG;IACH,mBAAmB,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,SAAS,CAAC;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,yCAAyC,CAAC;CACnD"}
|
|
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AttachmentsStreamingPool = void 0;
|
|
4
4
|
const helpers_1 = require("../common/helpers");
|
|
5
5
|
class AttachmentsStreamingPool {
|
|
6
|
-
constructor({ adapter, attachments, batchSize = 10, stream, }) {
|
|
6
|
+
constructor({ adapter, attachments, attachmentsMetadata, batchSize = 10, stream, }) {
|
|
7
7
|
this.totalProcessedCount = 0;
|
|
8
8
|
this.PROGRESS_REPORT_INTERVAL = 50;
|
|
9
9
|
this.adapter = adapter;
|
|
10
10
|
this.attachments = [...attachments]; // Create a copy we can mutate
|
|
11
|
+
this.attachmentsMetadata = attachmentsMetadata;
|
|
11
12
|
this.batchSize = batchSize;
|
|
12
13
|
this.delay = undefined;
|
|
13
14
|
this.stream = stream;
|
|
@@ -47,22 +48,19 @@ class AttachmentsStreamingPool {
|
|
|
47
48
|
}
|
|
48
49
|
async streamAll() {
|
|
49
50
|
console.log(`Starting download of ${this.attachments.length} attachments, streaming ${this.batchSize} at once.`);
|
|
50
|
-
if (!this.
|
|
51
|
+
if (!this.attachmentsMetadata) {
|
|
51
52
|
const error = new Error('toDevRev state is not initialized');
|
|
52
53
|
console.error(error);
|
|
53
54
|
return { error };
|
|
54
55
|
}
|
|
55
56
|
// Get the list of successfully processed attachments in previous (possibly incomplete) batch extraction.
|
|
56
57
|
// If no such list exists, create an empty one.
|
|
57
|
-
if (!this.
|
|
58
|
-
.lastProcessedAttachmentsIdsList
|
|
59
|
-
this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
60
|
-
[];
|
|
58
|
+
if (!this.attachmentsMetadata.lastProcessedAttachmentsIdsList) {
|
|
59
|
+
this.attachmentsMetadata.lastProcessedAttachmentsIdsList = [];
|
|
61
60
|
}
|
|
62
61
|
// Migrate old processed attachments to the new format.
|
|
63
|
-
this.
|
|
64
|
-
this.migrateProcessedAttachments(this.
|
|
65
|
-
.lastProcessedAttachmentsIdsList);
|
|
62
|
+
this.attachmentsMetadata.lastProcessedAttachmentsIdsList =
|
|
63
|
+
this.migrateProcessedAttachments(this.attachmentsMetadata.lastProcessedAttachmentsIdsList);
|
|
66
64
|
// Start initial batch of promises up to batchSize limit
|
|
67
65
|
const initialBatchSize = Math.min(this.batchSize, this.attachments.length);
|
|
68
66
|
const initialPromises = [];
|
|
@@ -77,7 +75,7 @@ class AttachmentsStreamingPool {
|
|
|
77
75
|
return {};
|
|
78
76
|
}
|
|
79
77
|
async startPoolStreaming() {
|
|
80
|
-
var _a, _b, _c
|
|
78
|
+
var _a, _b, _c;
|
|
81
79
|
// Process attachments until the attachments array is empty
|
|
82
80
|
while (this.attachments.length > 0) {
|
|
83
81
|
// If delay is set, stop streaming
|
|
@@ -94,8 +92,7 @@ class AttachmentsStreamingPool {
|
|
|
94
92
|
if (!attachment) {
|
|
95
93
|
break; // Exit if no more attachments
|
|
96
94
|
}
|
|
97
|
-
if (this.
|
|
98
|
-
((_a = this.adapter.state.toDevRev.attachmentsMetadata.lastProcessedAttachmentsIdsList) === null || _a === void 0 ? void 0 : _a.some((it) => it.id == attachment.id && it.parent_id == attachment.parent_id))) {
|
|
95
|
+
if ((_b = (_a = this.attachmentsMetadata) === null || _a === void 0 ? void 0 : _a.lastProcessedAttachmentsIdsList) === null || _b === void 0 ? void 0 : _b.some((it) => it.id == attachment.id && it.parent_id == attachment.parent_id)) {
|
|
99
96
|
continue; // Skip if the attachment ID is already processed
|
|
100
97
|
}
|
|
101
98
|
try {
|
|
@@ -106,18 +103,32 @@ class AttachmentsStreamingPool {
|
|
|
106
103
|
return;
|
|
107
104
|
}
|
|
108
105
|
if (response === null || response === void 0 ? void 0 : response.error) {
|
|
109
|
-
|
|
106
|
+
const fileExtension = attachment.file_name.split('.').pop() || '';
|
|
107
|
+
const fileSizeInfo = response.error.fileSize
|
|
108
|
+
? `and size ${response.error.fileSize} bytes `
|
|
109
|
+
: '';
|
|
110
|
+
const contentTypeInfo = attachment.content_type
|
|
111
|
+
? `and content_type ${attachment.content_type} `
|
|
112
|
+
: '';
|
|
113
|
+
console.warn(`Skipping attachment with ID ${attachment.id} with extension ${fileExtension} ${fileSizeInfo}${contentTypeInfo}due to error returned by the stream function`, response.error.message);
|
|
110
114
|
await this.updateProgress();
|
|
111
115
|
continue;
|
|
112
116
|
}
|
|
113
117
|
// No rate limiting, process normally
|
|
114
|
-
if ((_c =
|
|
115
|
-
|
|
118
|
+
if ((_c = this.attachmentsMetadata) === null || _c === void 0 ? void 0 : _c.lastProcessedAttachmentsIdsList) {
|
|
119
|
+
this.attachmentsMetadata.lastProcessedAttachmentsIdsList.push({
|
|
120
|
+
id: attachment.id,
|
|
121
|
+
parent_id: attachment.parent_id,
|
|
122
|
+
});
|
|
116
123
|
}
|
|
117
124
|
await this.updateProgress();
|
|
118
125
|
}
|
|
119
126
|
catch (error) {
|
|
120
|
-
|
|
127
|
+
const fileExtension = attachment.file_name.split('.').pop() || '';
|
|
128
|
+
const contentTypeInfo = attachment.content_type
|
|
129
|
+
? ` and content_type ${attachment.content_type}`
|
|
130
|
+
: '';
|
|
131
|
+
console.warn(`Skipping attachment with ID ${attachment.id} with extension ${fileExtension}${contentTypeInfo} due to error in processAttachment function`, error);
|
|
121
132
|
await this.updateProgress();
|
|
122
133
|
}
|
|
123
134
|
}
|
|
@@ -6,16 +6,18 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
6
6
|
let mockAdapter;
|
|
7
7
|
let mockStream;
|
|
8
8
|
let mockAttachments;
|
|
9
|
+
let attachmentsMetadata;
|
|
9
10
|
beforeEach(() => {
|
|
11
|
+
// SDK-owned attachments bookkeeping, passed into the pool directly.
|
|
12
|
+
attachmentsMetadata = {
|
|
13
|
+
artifactIds: [],
|
|
14
|
+
lastProcessed: 0,
|
|
15
|
+
lastProcessedAttachmentsIdsList: [],
|
|
16
|
+
};
|
|
10
17
|
// Create mock adapter
|
|
11
18
|
mockAdapter = {
|
|
12
19
|
state: {
|
|
13
20
|
attachments: { completed: false },
|
|
14
|
-
toDevRev: {
|
|
15
|
-
attachmentsMetadata: {
|
|
16
|
-
lastProcessedAttachmentsIdsList: [],
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
21
|
},
|
|
20
22
|
processAttachment: jest
|
|
21
23
|
.fn()
|
|
@@ -44,10 +46,6 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
44
46
|
parent_id: 'parent-3',
|
|
45
47
|
},
|
|
46
48
|
];
|
|
47
|
-
// Mock console methods
|
|
48
|
-
jest.spyOn(console, 'log').mockImplementation();
|
|
49
|
-
jest.spyOn(console, 'error').mockImplementation();
|
|
50
|
-
jest.spyOn(console, 'warn').mockImplementation();
|
|
51
49
|
});
|
|
52
50
|
afterEach(() => {
|
|
53
51
|
jest.clearAllMocks();
|
|
@@ -57,10 +55,10 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
57
55
|
it('should initialize with default values', () => {
|
|
58
56
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
59
57
|
adapter: mockAdapter,
|
|
58
|
+
attachmentsMetadata,
|
|
60
59
|
attachments: mockAttachments,
|
|
61
60
|
stream: mockStream,
|
|
62
61
|
});
|
|
63
|
-
expect(pool).toBeDefined();
|
|
64
62
|
expect(pool['adapter']).toBe(mockAdapter);
|
|
65
63
|
expect(pool['attachments']).toEqual(mockAttachments);
|
|
66
64
|
expect(pool['batchSize']).toBe(10);
|
|
@@ -69,6 +67,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
69
67
|
it('should initialize with custom batch size', () => {
|
|
70
68
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
71
69
|
adapter: mockAdapter,
|
|
70
|
+
attachmentsMetadata,
|
|
72
71
|
attachments: mockAttachments,
|
|
73
72
|
batchSize: 5,
|
|
74
73
|
stream: mockStream,
|
|
@@ -78,6 +77,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
78
77
|
it('should create a copy of attachments array', () => {
|
|
79
78
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
80
79
|
adapter: mockAdapter,
|
|
80
|
+
attachmentsMetadata,
|
|
81
81
|
attachments: mockAttachments,
|
|
82
82
|
stream: mockStream,
|
|
83
83
|
});
|
|
@@ -87,11 +87,11 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
87
87
|
});
|
|
88
88
|
describe(attachments_streaming_pool_1.AttachmentsStreamingPool.prototype.streamAll.name, () => {
|
|
89
89
|
it('should initialize lastProcessedAttachmentsIdsList if it does not exist', async () => {
|
|
90
|
-
|
|
91
|
-
undefined;
|
|
90
|
+
attachmentsMetadata.lastProcessedAttachmentsIdsList = undefined;
|
|
92
91
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
93
92
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
94
93
|
adapter: mockAdapter,
|
|
94
|
+
attachmentsMetadata,
|
|
95
95
|
attachments: mockAttachments,
|
|
96
96
|
stream: mockStream,
|
|
97
97
|
});
|
|
@@ -100,13 +100,13 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
100
100
|
.spyOn(pool, 'startPoolStreaming')
|
|
101
101
|
.mockResolvedValue(undefined);
|
|
102
102
|
await pool.streamAll();
|
|
103
|
-
expect(
|
|
104
|
-
.lastProcessedAttachmentsIdsList).toEqual([]);
|
|
103
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([]);
|
|
105
104
|
});
|
|
106
105
|
it('should process all attachments successfully', async () => {
|
|
107
106
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
108
107
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
109
108
|
adapter: mockAdapter,
|
|
109
|
+
attachmentsMetadata,
|
|
110
110
|
attachments: mockAttachments,
|
|
111
111
|
stream: mockStream,
|
|
112
112
|
});
|
|
@@ -117,6 +117,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
117
117
|
it('should handle empty attachments array', async () => {
|
|
118
118
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
119
119
|
adapter: mockAdapter,
|
|
120
|
+
attachmentsMetadata,
|
|
120
121
|
attachments: [],
|
|
121
122
|
stream: mockStream,
|
|
122
123
|
});
|
|
@@ -129,6 +130,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
129
130
|
mockAdapter.processAttachment.mockResolvedValue(delayResponse);
|
|
130
131
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
131
132
|
adapter: mockAdapter,
|
|
133
|
+
attachmentsMetadata,
|
|
132
134
|
attachments: mockAttachments,
|
|
133
135
|
stream: mockStream,
|
|
134
136
|
});
|
|
@@ -136,18 +138,20 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
136
138
|
expect(result).toEqual({ delay: 5000 });
|
|
137
139
|
});
|
|
138
140
|
it('should resume attachment extraction if it encounters old ids', async () => {
|
|
139
|
-
var _a;
|
|
140
141
|
// Test migration from old string[] format to new ProcessedAttachment[] format
|
|
141
142
|
// Using 'as any' because we're intentionally testing legacy data format
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
attachmentsMetadata.lastProcessedAttachmentsIdsList = [
|
|
144
|
+
'attachment-1',
|
|
145
|
+
'attachment-2',
|
|
146
|
+
];
|
|
144
147
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
145
148
|
adapter: mockAdapter,
|
|
149
|
+
attachmentsMetadata,
|
|
146
150
|
attachments: mockAttachments,
|
|
147
151
|
stream: mockStream,
|
|
148
152
|
});
|
|
149
153
|
const result = await pool.streamAll();
|
|
150
|
-
expect(
|
|
154
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([
|
|
151
155
|
{ id: 'attachment-1', parent_id: '' },
|
|
152
156
|
{ id: 'attachment-2', parent_id: '' },
|
|
153
157
|
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
@@ -156,14 +160,57 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
156
160
|
]);
|
|
157
161
|
expect(result).toEqual({});
|
|
158
162
|
});
|
|
163
|
+
it('should handle all attachments failing with different file types and sizes', async () => {
|
|
164
|
+
const largeAttachments = [
|
|
165
|
+
{
|
|
166
|
+
id: 'attachment-image',
|
|
167
|
+
url: 'https://example.com/photo.jpg',
|
|
168
|
+
file_name: 'photo.jpg',
|
|
169
|
+
parent_id: 'parent-1',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'attachment-pdf',
|
|
173
|
+
url: 'https://example.com/document.pdf',
|
|
174
|
+
file_name: 'document.pdf',
|
|
175
|
+
parent_id: 'parent-2',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'attachment-video',
|
|
179
|
+
url: 'https://example.com/video.mp4',
|
|
180
|
+
file_name: 'video.mp4',
|
|
181
|
+
parent_id: 'parent-3',
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
const imageError = new Error('Image upload failed: File too large');
|
|
185
|
+
const pdfError = new Error('PDF upload failed: Unsupported format');
|
|
186
|
+
const videoError = new Error('Video upload failed: Network error');
|
|
187
|
+
mockAdapter.processAttachment
|
|
188
|
+
.mockRejectedValueOnce(imageError)
|
|
189
|
+
.mockRejectedValueOnce(pdfError)
|
|
190
|
+
.mockRejectedValueOnce(videoError);
|
|
191
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
192
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
193
|
+
adapter: mockAdapter,
|
|
194
|
+
attachmentsMetadata,
|
|
195
|
+
attachments: largeAttachments,
|
|
196
|
+
stream: mockStream,
|
|
197
|
+
});
|
|
198
|
+
await pool.streamAll();
|
|
199
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
200
|
+
// Since there are 3 parallel workers (one per attachment), each logs its own failed attachment
|
|
201
|
+
expect(warnSpy).toHaveBeenCalledTimes(3);
|
|
202
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([]);
|
|
203
|
+
});
|
|
159
204
|
});
|
|
160
205
|
describe(attachments_streaming_pool_1.AttachmentsStreamingPool.prototype.startPoolStreaming.name, () => {
|
|
161
206
|
it('should skip already processed attachments', async () => {
|
|
162
|
-
|
|
163
|
-
|
|
207
|
+
attachmentsMetadata.lastProcessedAttachmentsIdsList = [
|
|
208
|
+
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
209
|
+
];
|
|
164
210
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
165
211
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
166
212
|
adapter: mockAdapter,
|
|
213
|
+
attachmentsMetadata,
|
|
167
214
|
attachments: mockAttachments,
|
|
168
215
|
stream: mockStream,
|
|
169
216
|
});
|
|
@@ -174,18 +221,19 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
174
221
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
175
222
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
176
223
|
adapter: mockAdapter,
|
|
224
|
+
attachmentsMetadata,
|
|
177
225
|
attachments: mockAttachments,
|
|
178
226
|
stream: mockStream,
|
|
179
227
|
});
|
|
180
228
|
await pool.streamAll();
|
|
181
|
-
expect(
|
|
182
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
229
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([
|
|
183
230
|
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
184
231
|
{ id: 'attachment-2', parent_id: 'parent-2' },
|
|
185
232
|
{ id: 'attachment-3', parent_id: 'parent-3' },
|
|
186
233
|
]);
|
|
187
234
|
});
|
|
188
235
|
it('should handle processing errors gracefully', async () => {
|
|
236
|
+
const warnSpy = jest.spyOn(console, 'warn').mockImplementation();
|
|
189
237
|
const error = new Error('Processing failed');
|
|
190
238
|
mockAdapter.processAttachment
|
|
191
239
|
.mockResolvedValueOnce({}) // First attachment succeeds
|
|
@@ -193,13 +241,13 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
193
241
|
.mockResolvedValueOnce({}); // Third attachment succeeds
|
|
194
242
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
195
243
|
adapter: mockAdapter,
|
|
244
|
+
attachmentsMetadata,
|
|
196
245
|
attachments: mockAttachments,
|
|
197
246
|
stream: mockStream,
|
|
198
247
|
});
|
|
199
248
|
await pool.streamAll();
|
|
200
|
-
expect(
|
|
201
|
-
expect(
|
|
202
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
249
|
+
expect(warnSpy).toHaveBeenCalledWith('Skipping attachment with ID attachment-2 with extension jpg due to error in processAttachment function', error);
|
|
250
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([
|
|
203
251
|
{
|
|
204
252
|
id: 'attachment-1',
|
|
205
253
|
parent_id: 'parent-1',
|
|
@@ -217,13 +265,13 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
217
265
|
.mockResolvedValueOnce({}); // Third attachment succeeds
|
|
218
266
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
219
267
|
adapter: mockAdapter,
|
|
268
|
+
attachmentsMetadata,
|
|
220
269
|
attachments: mockAttachments,
|
|
221
270
|
stream: mockStream,
|
|
222
271
|
});
|
|
223
272
|
await pool.streamAll();
|
|
224
273
|
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
225
|
-
expect(
|
|
226
|
-
.lastProcessedAttachmentsIdsList).toEqual([
|
|
274
|
+
expect(attachmentsMetadata.lastProcessedAttachmentsIdsList).toEqual([
|
|
227
275
|
{ id: 'attachment-1', parent_id: 'parent-1' },
|
|
228
276
|
{ id: 'attachment-3', parent_id: 'parent-3' },
|
|
229
277
|
]);
|
|
@@ -232,6 +280,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
232
280
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
233
281
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
234
282
|
adapter: mockAdapter,
|
|
283
|
+
attachmentsMetadata,
|
|
235
284
|
attachments: [mockAttachments[0]],
|
|
236
285
|
stream: mockStream,
|
|
237
286
|
});
|
|
@@ -243,6 +292,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
243
292
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
244
293
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
245
294
|
adapter: mockAdapter,
|
|
295
|
+
attachmentsMetadata,
|
|
246
296
|
attachments: [mockAttachments[0]],
|
|
247
297
|
stream: mockStream,
|
|
248
298
|
});
|
|
@@ -254,6 +304,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
254
304
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
255
305
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
256
306
|
adapter: mockAdapter,
|
|
307
|
+
attachmentsMetadata,
|
|
257
308
|
attachments: mockAttachments,
|
|
258
309
|
batchSize: 100,
|
|
259
310
|
stream: mockStream,
|
|
@@ -271,6 +322,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
271
322
|
});
|
|
272
323
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
273
324
|
adapter: mockAdapter,
|
|
325
|
+
attachmentsMetadata,
|
|
274
326
|
attachments: mockAttachments,
|
|
275
327
|
batchSize: 1,
|
|
276
328
|
stream: mockStream,
|
|
@@ -282,6 +334,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
282
334
|
mockAdapter.processAttachment.mockResolvedValue({});
|
|
283
335
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
284
336
|
adapter: mockAdapter,
|
|
337
|
+
attachmentsMetadata,
|
|
285
338
|
attachments: mockAttachments,
|
|
286
339
|
batchSize: 1,
|
|
287
340
|
stream: mockStream,
|
|
@@ -289,6 +342,122 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
289
342
|
await pool.streamAll();
|
|
290
343
|
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
291
344
|
});
|
|
345
|
+
describe('content_type handling', () => {
|
|
346
|
+
it('should pass attachment with content_type to processAttachment', async () => {
|
|
347
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
348
|
+
const attachmentWithContentType = {
|
|
349
|
+
id: 'attachment-ct',
|
|
350
|
+
url: 'https://example.com/report.pdf',
|
|
351
|
+
file_name: 'report.pdf',
|
|
352
|
+
parent_id: 'parent-ct',
|
|
353
|
+
content_type: 'application/pdf',
|
|
354
|
+
};
|
|
355
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
356
|
+
adapter: mockAdapter,
|
|
357
|
+
attachmentsMetadata,
|
|
358
|
+
attachments: [attachmentWithContentType],
|
|
359
|
+
stream: mockStream,
|
|
360
|
+
});
|
|
361
|
+
await pool.streamAll();
|
|
362
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledWith(attachmentWithContentType, mockStream);
|
|
363
|
+
expect(mockAdapter.processAttachment.mock.calls[0][0].content_type).toBe('application/pdf');
|
|
364
|
+
});
|
|
365
|
+
it('should handle mixed attachments with and without content_type', async () => {
|
|
366
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
367
|
+
const mixedAttachments = [
|
|
368
|
+
{
|
|
369
|
+
id: 'att-with-ct',
|
|
370
|
+
url: 'https://example.com/image.png',
|
|
371
|
+
file_name: 'image.png',
|
|
372
|
+
parent_id: 'parent-1',
|
|
373
|
+
content_type: 'image/png',
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
id: 'att-without-ct',
|
|
377
|
+
url: 'https://example.com/file.bin',
|
|
378
|
+
file_name: 'file.bin',
|
|
379
|
+
parent_id: 'parent-2',
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
id: 'att-with-ct-2',
|
|
383
|
+
url: 'https://example.com/doc.pdf',
|
|
384
|
+
file_name: 'doc.pdf',
|
|
385
|
+
parent_id: 'parent-3',
|
|
386
|
+
content_type: 'application/pdf',
|
|
387
|
+
},
|
|
388
|
+
];
|
|
389
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
390
|
+
adapter: mockAdapter,
|
|
391
|
+
attachmentsMetadata,
|
|
392
|
+
attachments: mixedAttachments,
|
|
393
|
+
batchSize: 1,
|
|
394
|
+
stream: mockStream,
|
|
395
|
+
});
|
|
396
|
+
await pool.streamAll();
|
|
397
|
+
expect(mockAdapter.processAttachment).toHaveBeenCalledTimes(3);
|
|
398
|
+
expect(mockAdapter.processAttachment.mock.calls[0][0].content_type).toBe('image/png');
|
|
399
|
+
expect(mockAdapter.processAttachment.mock.calls[1][0].content_type).toBeUndefined();
|
|
400
|
+
expect(mockAdapter.processAttachment.mock.calls[2][0].content_type).toBe('application/pdf');
|
|
401
|
+
});
|
|
402
|
+
it('should include content_type in error log when processAttachment returns error', async () => {
|
|
403
|
+
mockAdapter.processAttachment.mockResolvedValue({
|
|
404
|
+
error: { message: 'Upload failed' },
|
|
405
|
+
});
|
|
406
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
407
|
+
const attachmentWithContentType = {
|
|
408
|
+
id: 'att-error-ct',
|
|
409
|
+
url: 'https://example.com/file.pdf',
|
|
410
|
+
file_name: 'file.pdf',
|
|
411
|
+
parent_id: 'parent-err',
|
|
412
|
+
content_type: 'application/pdf',
|
|
413
|
+
};
|
|
414
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
415
|
+
adapter: mockAdapter,
|
|
416
|
+
attachmentsMetadata,
|
|
417
|
+
attachments: [attachmentWithContentType],
|
|
418
|
+
batchSize: 1,
|
|
419
|
+
stream: mockStream,
|
|
420
|
+
});
|
|
421
|
+
await pool.streamAll();
|
|
422
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('content_type application/pdf'), expect.any(String));
|
|
423
|
+
});
|
|
424
|
+
it('should include content_type in error log when processAttachment throws', async () => {
|
|
425
|
+
const error = new Error('Processing crashed');
|
|
426
|
+
mockAdapter.processAttachment.mockRejectedValue(error);
|
|
427
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
428
|
+
const attachmentWithContentType = {
|
|
429
|
+
id: 'att-throw-ct',
|
|
430
|
+
url: 'https://example.com/file.png',
|
|
431
|
+
file_name: 'file.png',
|
|
432
|
+
parent_id: 'parent-throw',
|
|
433
|
+
content_type: 'image/png',
|
|
434
|
+
};
|
|
435
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
436
|
+
adapter: mockAdapter,
|
|
437
|
+
attachmentsMetadata,
|
|
438
|
+
attachments: [attachmentWithContentType],
|
|
439
|
+
batchSize: 1,
|
|
440
|
+
stream: mockStream,
|
|
441
|
+
});
|
|
442
|
+
await pool.streamAll();
|
|
443
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('content_type image/png'), error);
|
|
444
|
+
});
|
|
445
|
+
it('should not include content_type in error log when content_type is not set', async () => {
|
|
446
|
+
mockAdapter.processAttachment.mockResolvedValue({
|
|
447
|
+
error: { message: 'Upload failed' },
|
|
448
|
+
});
|
|
449
|
+
const warnSpy = jest.spyOn(console, 'warn');
|
|
450
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
451
|
+
adapter: mockAdapter,
|
|
452
|
+
attachmentsMetadata,
|
|
453
|
+
attachments: [mockAttachments[0]],
|
|
454
|
+
batchSize: 1,
|
|
455
|
+
stream: mockStream,
|
|
456
|
+
});
|
|
457
|
+
await pool.streamAll();
|
|
458
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.not.stringContaining('content_type'), expect.any(String));
|
|
459
|
+
});
|
|
460
|
+
});
|
|
292
461
|
describe('concurrency behavior', () => {
|
|
293
462
|
it('should process attachments concurrently within batch size', async () => {
|
|
294
463
|
let processCallCount = 0;
|
|
@@ -305,6 +474,7 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
305
474
|
});
|
|
306
475
|
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
307
476
|
adapter: mockAdapter,
|
|
477
|
+
attachmentsMetadata,
|
|
308
478
|
attachments: mockAttachments,
|
|
309
479
|
batchSize: 2,
|
|
310
480
|
stream: mockStream,
|
|
@@ -318,4 +488,53 @@ describe(attachments_streaming_pool_1.AttachmentsStreamingPool.name, () => {
|
|
|
318
488
|
expect(endTime - startTime).toBeLessThan(250);
|
|
319
489
|
});
|
|
320
490
|
});
|
|
491
|
+
describe('log context attribution', () => {
|
|
492
|
+
it('should emit SDK-generated logs from pool (Starting download message)', async () => {
|
|
493
|
+
const logSpy = jest.spyOn(console, 'log');
|
|
494
|
+
mockAdapter.processAttachment.mockResolvedValue({});
|
|
495
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
496
|
+
adapter: mockAdapter,
|
|
497
|
+
attachmentsMetadata,
|
|
498
|
+
attachments: mockAttachments.slice(0, 1),
|
|
499
|
+
stream: mockStream,
|
|
500
|
+
});
|
|
501
|
+
// Call streamAll - it should log "Starting download of N attachments..."
|
|
502
|
+
await pool.streamAll();
|
|
503
|
+
// Verify the SDK-generated "Starting download" message was logged
|
|
504
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('Starting download of 1 attachments'));
|
|
505
|
+
});
|
|
506
|
+
it('should process user stream callback correctly while maintaining context isolation', async () => {
|
|
507
|
+
let userCallbackExecuted = false;
|
|
508
|
+
// Mock stream to capture context info
|
|
509
|
+
const mockStreamFn = jest
|
|
510
|
+
.fn()
|
|
511
|
+
.mockImplementation(async () => {
|
|
512
|
+
await Promise.resolve();
|
|
513
|
+
userCallbackExecuted = true;
|
|
514
|
+
// Record that the callback executed
|
|
515
|
+
return Promise.resolve({
|
|
516
|
+
httpStream: undefined,
|
|
517
|
+
error: undefined,
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
mockAdapter.processAttachment.mockImplementation(async (attachment, stream) => {
|
|
521
|
+
// processAttachment should be called with the user's stream function
|
|
522
|
+
const result = await stream({
|
|
523
|
+
item: attachment,
|
|
524
|
+
event: {},
|
|
525
|
+
});
|
|
526
|
+
return result;
|
|
527
|
+
});
|
|
528
|
+
const pool = new attachments_streaming_pool_1.AttachmentsStreamingPool({
|
|
529
|
+
adapter: mockAdapter,
|
|
530
|
+
attachmentsMetadata,
|
|
531
|
+
attachments: mockAttachments.slice(0, 1),
|
|
532
|
+
stream: mockStreamFn,
|
|
533
|
+
});
|
|
534
|
+
await pool.streamAll();
|
|
535
|
+
// Verify the user callback was executed
|
|
536
|
+
expect(userCallbackExecuted).toBe(true);
|
|
537
|
+
expect(mockStreamFn).toHaveBeenCalled();
|
|
538
|
+
});
|
|
539
|
+
});
|
|
321
540
|
});
|
|
@@ -12,14 +12,25 @@ export declare const ARTIFACT_BATCH_SIZE = 2000;
|
|
|
12
12
|
export declare const MAX_DEVREV_ARTIFACT_SIZE: number;
|
|
13
13
|
export declare const MAX_DEVREV_FILENAME_LENGTH = 256;
|
|
14
14
|
export declare const MAX_DEVREV_FILENAME_EXTENSION_LENGTH = 20;
|
|
15
|
-
export declare const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
export declare const MAX_EVENT_SIZE_BYTES = 200000;
|
|
16
|
+
export declare const EVENT_SIZE_THRESHOLD_BYTES: number;
|
|
17
|
+
export declare const SSOR_ATTACHMENT: string;
|
|
18
|
+
export declare enum AirSyncDefaultItemTypes {
|
|
19
|
+
EXTERNAL_DOMAIN_METADATA = "external_domain_metadata",
|
|
20
|
+
ATTACHMENTS = "attachments",
|
|
21
|
+
EXTERNAL_SYNC_UNITS = "external_sync_units"
|
|
22
|
+
}
|
|
20
23
|
export declare const LIBRARY_VERSION: any;
|
|
21
24
|
export declare const DEFAULT_LAMBDA_TIMEOUT: number;
|
|
22
25
|
export declare const HARD_TIMEOUT_MULTIPLIER = 1.3;
|
|
23
26
|
export declare const MEMORY_LOG_INTERVAL: number;
|
|
24
27
|
export declare const DEFAULT_SLEEP_DELAY_MS: number;
|
|
28
|
+
/**
|
|
29
|
+
* Sentinel value representing an unbounded (no limit) extraction timestamp.
|
|
30
|
+
* Used as the resolved value for TimeValueType.UNBOUNDED, stored as workersOldest
|
|
31
|
+
* when the initial import has no lower time bound. The Unix epoch ensures that
|
|
32
|
+
* no real extraction timestamp can be earlier, preventing accidental overwrites
|
|
33
|
+
* of the boundary by subsequent syncs (e.g. reconciliation with absolute dates).
|
|
34
|
+
*/
|
|
35
|
+
export declare const UNBOUNDED_DATE_TIME_VALUE = "1970-01-01T00:00:00.000Z";
|
|
25
36
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,eAAO,MAAM,8BAA8B,aAS1C,CAAC;AAEF,eAAO,MAAM,2BAA2B,aAKvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAG/B,CAAC;AAEF,eAAO,MAAM,gCAAgC,aAI5C,CAAC;AAEF,eAAO,MAAM,6BAA6B,aAGzC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAGjC,CAAC;AAEF,eAAO,MAAM,+BAA+B,aAGzC,CAAC;AAEJ,eAAO,MAAM,4BAA4B,aAExC,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAGhC,CAAC;AAEF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,wBAAwB,QAAyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,oCAAoC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,eAAO,MAAM,8BAA8B,aAS1C,CAAC;AAEF,eAAO,MAAM,2BAA2B,aAKvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,aAG/B,CAAC;AAEF,eAAO,MAAM,gCAAgC,aAI5C,CAAC;AAEF,eAAO,MAAM,6BAA6B,aAGzC,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAGjC,CAAC;AAEF,eAAO,MAAM,+BAA+B,aAGzC,CAAC;AAEJ,eAAO,MAAM,4BAA4B,aAExC,CAAC;AAEF,eAAO,MAAM,oBAAoB,aAGhC,CAAC;AAEF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,wBAAwB,QAAyB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAGvD,eAAO,MAAM,oBAAoB,SAAU,CAAC;AAE5C,eAAO,MAAM,0BAA0B,QAEtC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAA0B,CAAC;AAEzD,oBAAY,uBAAuB;IACjC,wBAAwB,6BAA6B;IACrD,WAAW,gBAAgB;IAC3B,mBAAmB,wBAAwB;CAC5C;AAED,eAAO,MAAM,eAAe,KAAsB,CAAC;AAEnD,eAAO,MAAM,sBAAsB,QAAiB,CAAC;AACrD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,mBAAmB,QAAY,CAAC;AAE7C,eAAO,MAAM,sBAAsB,QAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,6BAA6B,CAAC"}
|