@devrev/ts-adaas 1.1.5 → 1.1.6

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 CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Release Notes
4
4
 
5
+ ### v1.1.6
6
+
7
+ - Add exponential retry and handle rate-limiting towards DevRev.
8
+ - Gracefully handle failure to upload extracted attachments.
9
+
5
10
  ### v1.1.5
6
11
 
7
12
  - Increase `delayFactor` and number of retries for the exponential backoff retry mechanism for HTTP requests.
@@ -4,7 +4,7 @@ export declare const ALLOWED_EXTRACTION_EVENT_TYPES: EventType[];
4
4
  export declare const ALLOWED_LOADING_EVENT_TYPES: EventType[];
5
5
  export declare const ALLOWED_EVENT_TYPES: EventType[];
6
6
  export declare const ARTIFACT_BATCH_SIZE = 2000;
7
- export declare const MAX_DEVREV_ARTIFACT_SIZE = 536870912;
7
+ export declare const MAX_DEVREV_ARTIFACT_SIZE = 262144000;
8
8
  export declare const AIRDROP_DEFAULT_ITEM_TYPES: {
9
9
  EXTERNAL_DOMAIN_METADATA: string;
10
10
  ATTACHMENTS: string;
@@ -31,7 +31,7 @@ exports.ALLOWED_EVENT_TYPES = [
31
31
  ...exports.ALLOWED_LOADING_EVENT_TYPES,
32
32
  ];
33
33
  exports.ARTIFACT_BATCH_SIZE = 2000;
34
- exports.MAX_DEVREV_ARTIFACT_SIZE = 536870912; // 512MB
34
+ exports.MAX_DEVREV_ARTIFACT_SIZE = 262144000; // 250MB
35
35
  exports.AIRDROP_DEFAULT_ITEM_TYPES = {
36
36
  EXTERNAL_DOMAIN_METADATA: 'external_domain_metadata',
37
37
  ATTACHMENTS: 'attachments',
@@ -22,12 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.Uploader = void 0;
30
- const axios_1 = __importDefault(require("axios"));
27
+ const axios_devrev_client_1 = require("../../http/axios-devrev-client");
31
28
  const typescript_sdk_1 = require("@devrev/typescript-sdk");
32
29
  const fs_1 = __importStar(require("fs"));
33
30
  const helpers_1 = require("../common/helpers");
@@ -111,7 +108,7 @@ class Uploader {
111
108
  ) {
112
109
  const formData = (0, helpers_1.createFormData)(preparedArtifact, fetchedObjects);
113
110
  try {
114
- const response = await axios_1.default.post(preparedArtifact.url, formData, {
111
+ const response = await axios_devrev_client_1.axiosDevRevClient.post(preparedArtifact.url, formData, {
115
112
  headers: {
116
113
  'Content-Type': 'multipart/form',
117
114
  },
@@ -0,0 +1,3 @@
1
+ import axios from 'axios';
2
+ declare const axiosDevRevClient: import("axios").AxiosInstance;
3
+ export { axios, axiosDevRevClient };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.axiosDevRevClient = exports.axios = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ exports.axios = axios_1.default;
9
+ const axios_retry_1 = __importDefault(require("axios-retry"));
10
+ const axiosDevRevClient = axios_1.default.create();
11
+ exports.axiosDevRevClient = axiosDevRevClient;
12
+ (0, axios_retry_1.default)(axiosDevRevClient, {
13
+ retries: 5,
14
+ retryDelay: (retryCount, error) => {
15
+ var _a, _b;
16
+ console.warn('Retry attempt: ' + retryCount + 'to url: ' + ((_a = error.config) === null || _a === void 0 ? void 0 : _a.url) + '.');
17
+ if (error.response) {
18
+ const retry_after = (_b = error.response) === null || _b === void 0 ? void 0 : _b.headers['retry-after'];
19
+ if (retry_after) {
20
+ return retry_after;
21
+ }
22
+ }
23
+ // Exponential backoff algorithm: 1 * 2 ^ retryCount * 1000ms
24
+ return axios_retry_1.default.exponentialDelay(retryCount, error, 1000);
25
+ },
26
+ retryCondition: (error) => {
27
+ var _a;
28
+ return (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) ||
29
+ ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 429);
30
+ },
31
+ onMaxRetryTimesExceeded(error, retryCount) {
32
+ var _a;
33
+ console.log(`Max retries attempted: ${retryCount}`);
34
+ (_a = error.config) === null || _a === void 0 ? true : delete _a.headers.Authorization;
35
+ delete error.request._header;
36
+ },
37
+ });
package/dist/repo/repo.js CHANGED
@@ -48,7 +48,7 @@ class Repo {
48
48
  }
49
49
  // Add the new records to the items array
50
50
  this.items.push(...recordsToPush);
51
- console.log(`Extracted ${recordsToPush.length} new items of type ${this.itemType}. Total number of items in repo: ${this.items.length}.`);
51
+ console.info(`Extracted ${recordsToPush.length} new items of type ${this.itemType}. Total number of items in repo: ${this.items.length}.`);
52
52
  // Upload in batches while the number of items exceeds the batch size
53
53
  while (this.items.length >= constants_1.ARTIFACT_BATCH_SIZE) {
54
54
  // Slice out a batch of ARTIFACT_BATCH_SIZE items to upload
@@ -1,7 +1,7 @@
1
- import { AxiosResponse } from 'axios';
2
1
  import { betaSDK } from '@devrev/typescript-sdk';
3
2
  import { NormalizedAttachment } from '../repo/repo.interfaces';
4
3
  import { UploadResponse, UploaderFactoryInterface } from './uploader.interfaces';
4
+ import { AxiosResponse } from 'axios';
5
5
  export declare class Uploader {
6
6
  private event;
7
7
  private betaDevrevSdk;
@@ -28,7 +28,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.Uploader = void 0;
30
30
  const fs_1 = __importStar(require("fs"));
31
- const axios_client_1 = require("../http/axios-client");
31
+ const axios_devrev_client_1 = require("../http/axios-devrev-client");
32
32
  const zlib_1 = __importDefault(require("zlib"));
33
33
  const js_jsonl_1 = require("js-jsonl");
34
34
  const form_data_1 = __importDefault(require("form-data"));
@@ -98,7 +98,7 @@ class Uploader {
98
98
  return response.data;
99
99
  }
100
100
  catch (error) {
101
- if (axios_client_1.axios.isAxiosError(error)) {
101
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
102
102
  console.error('Error while preparing artifact.', (0, logger_1.serializeAxiosError)(error));
103
103
  }
104
104
  else {
@@ -115,13 +115,13 @@ class Uploader {
115
115
  }
116
116
  formData.append('file', file);
117
117
  try {
118
- const response = await axios_client_1.axiosClient.post(preparedArtifact.url, formData, {
118
+ const response = await axios_devrev_client_1.axiosDevRevClient.post(preparedArtifact.url, formData, {
119
119
  headers: Object.assign({}, formData.getHeaders()),
120
120
  });
121
121
  return response;
122
122
  }
123
123
  catch (error) {
124
- if (axios_client_1.axios.isAxiosError(error)) {
124
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
125
125
  console.error('Error while uploading artifact.', (0, logger_1.serializeAxiosError)(error));
126
126
  }
127
127
  else {
@@ -137,8 +137,11 @@ class Uploader {
137
137
  formData.append(field.key, field.value);
138
138
  }
139
139
  formData.append('file', fileStreamResponse.data);
140
+ if (fileStreamResponse.headers['content-length'] > constants_1.MAX_DEVREV_ARTIFACT_SIZE) {
141
+ return;
142
+ }
140
143
  try {
141
- const response = await axios_client_1.axiosClient.post(preparedArtifact.url, formData, {
144
+ const response = await axios_devrev_client_1.axiosDevRevClient.post(preparedArtifact.url, formData, {
142
145
  headers: Object.assign(Object.assign({}, formData.getHeaders()), (!fileStreamResponse.headers['content-length'] && {
143
146
  'Content-Length': constants_1.MAX_DEVREV_ARTIFACT_SIZE,
144
147
  })),
@@ -146,7 +149,7 @@ class Uploader {
146
149
  return response;
147
150
  }
148
151
  catch (error) {
149
- if (axios_client_1.axios.isAxiosError(error)) {
152
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
150
153
  console.error('Error while streaming artifact.', (0, logger_1.serializeAxiosError)(error));
151
154
  }
152
155
  else {
@@ -199,13 +202,13 @@ class Uploader {
199
202
  }
200
203
  async downloadArtifact(artifactUrl) {
201
204
  try {
202
- const response = await axios_client_1.axiosClient.get(artifactUrl, {
205
+ const response = await axios_devrev_client_1.axiosDevRevClient.get(artifactUrl, {
203
206
  responseType: 'arraybuffer',
204
207
  });
205
208
  return response.data;
206
209
  }
207
210
  catch (error) {
208
- if (axios_client_1.axios.isAxiosError(error)) {
211
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
209
212
  console.error('Error while downloading artifact from URL.', (0, logger_1.serializeAxiosError)(error));
210
213
  }
211
214
  else {
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WorkerAdapter = void 0;
4
4
  exports.createWorkerAdapter = createWorkerAdapter;
5
- const axios_client_1 = require("../http/axios-client");
5
+ const axios_devrev_client_1 = require("../http/axios-devrev-client");
6
6
  const extraction_1 = require("../types/extraction");
7
7
  const loading_1 = require("../types/loading");
8
8
  const constants_1 = require("../common/constants");
@@ -340,7 +340,7 @@ class WorkerAdapter {
340
340
  console.log('Updated sync mapper record', JSON.stringify(updateSyncMapperRecordResponse.data));
341
341
  }
342
342
  catch (error) {
343
- if (axios_client_1.axios.isAxiosError(error)) {
343
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
344
344
  console.error('Failed to update sync mapper record', (0, logger_1.serializeAxiosError)(error));
345
345
  return {
346
346
  error: {
@@ -385,7 +385,7 @@ class WorkerAdapter {
385
385
  // Update mapper (optional)
386
386
  }
387
387
  catch (error) {
388
- if (axios_client_1.axios.isAxiosError(error)) {
388
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
389
389
  if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
390
390
  // Create item
391
391
  const { id, delay, error } = await itemTypeToLoad.create({
@@ -411,7 +411,7 @@ class WorkerAdapter {
411
411
  };
412
412
  }
413
413
  catch (error) {
414
- if (axios_client_1.axios.isAxiosError(error)) {
414
+ if (axios_devrev_client_1.axios.isAxiosError(error)) {
415
415
  console.error('Failed to create sync mapper record', (0, logger_1.serializeAxiosError)(error));
416
416
  return {
417
417
  error: {
@@ -469,7 +469,7 @@ class WorkerAdapter {
469
469
  * or error information if there was an error
470
470
  */
471
471
  async streamAttachments({ stream, }) {
472
- var _a, _b, _c, _d, _e, _f, _g;
472
+ var _a, _b, _c, _d, _e, _f;
473
473
  const repos = [
474
474
  {
475
475
  itemType: 'ssor_attachment',
@@ -487,9 +487,8 @@ class WorkerAdapter {
487
487
  if (error) {
488
488
  return { error };
489
489
  }
490
- console.log('this.state.toDevRev?.attachmentsMetadata :>> ', (_c = this.state.toDevRev) === null || _c === void 0 ? void 0 : _c.attachmentsMetadata);
491
490
  if (attachments) {
492
- const attachmentsToProcess = attachments.slice((_e = (_d = this.state.toDevRev) === null || _d === void 0 ? void 0 : _d.attachmentsMetadata) === null || _e === void 0 ? void 0 : _e.lastProcessed, attachments.length);
491
+ const attachmentsToProcess = attachments.slice((_d = (_c = this.state.toDevRev) === null || _c === void 0 ? void 0 : _c.attachmentsMetadata) === null || _d === void 0 ? void 0 : _d.lastProcessed, attachments.length);
493
492
  for (const attachment of attachmentsToProcess) {
494
493
  const { httpStream, delay, error } = await stream({
495
494
  item: attachment,
@@ -503,19 +502,26 @@ class WorkerAdapter {
503
502
  return { delay };
504
503
  }
505
504
  if (httpStream) {
506
- const fileType = ((_f = httpStream.headers) === null || _f === void 0 ? void 0 : _f['content-type']) ||
505
+ const fileType = ((_e = httpStream.headers) === null || _e === void 0 ? void 0 : _e['content-type']) ||
507
506
  'application/octet-stream';
508
507
  const preparedArtifact = await this.uploader.prepareArtifact(attachment.file_name, fileType);
509
508
  if (!preparedArtifact) {
510
- return {
511
- error: { message: 'Error while preparing artifact.' },
512
- };
509
+ console.warn('Error while preparing artifact for attachment ID ' +
510
+ attachment.id +
511
+ '. Skipping attachment');
512
+ if (this.state.toDevRev) {
513
+ this.state.toDevRev.attachmentsMetadata.lastProcessed++;
514
+ }
515
+ continue;
513
516
  }
514
517
  const uploadedArtifact = await this.uploader.streamToArtifact(preparedArtifact, httpStream);
515
518
  if (!uploadedArtifact) {
516
- return {
517
- error: { message: 'Error while streaming artifact.' },
518
- };
519
+ console.warn('Error while preparing artifact for attachment ID ' +
520
+ attachment.id);
521
+ if (this.state.toDevRev) {
522
+ this.state.toDevRev.attachmentsMetadata.lastProcessed++;
523
+ }
524
+ continue;
519
525
  }
520
526
  const ssorAttachment = {
521
527
  id: {
@@ -529,7 +535,7 @@ class WorkerAdapter {
529
535
  external: attachment.author_id,
530
536
  },
531
537
  };
532
- await ((_g = this.getRepo('ssor_attachment')) === null || _g === void 0 ? void 0 : _g.push([ssorAttachment]));
538
+ await ((_f = this.getRepo('ssor_attachment')) === null || _f === void 0 ? void 0 : _f.push([ssorAttachment]));
533
539
  if (this.state.toDevRev) {
534
540
  this.state.toDevRev.attachmentsMetadata.lastProcessed++;
535
541
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devrev/ts-adaas",
3
- "version": "1.1.5",
4
- "description": "Typescript library containing the ADaaS(AirDrop as a Service) control protocol.",
3
+ "version": "1.1.6",
4
+ "description": "DevRev ADaaS (AirDrop-as-a-Service) Typescript SDK.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",
7
7
  "typings": "./dist/index.d.ts",