@contentstack/datasync-manager 2.1.1 → 2.1.2

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/api.js CHANGED
@@ -17,11 +17,13 @@ const sanitize_url_1 = require("@braintree/sanitize-url");
17
17
  const fs_1 = require("./util/fs");
18
18
  const debug = (0, debug_1.default)('api');
19
19
  let MAX_RETRY_LIMIT;
20
+ let RETRY_DELAY_BASE = 200; // Default base delay in milliseconds
21
+ let TIMEOUT = 30000; // Default timeout in milliseconds
20
22
  let Contentstack;
21
23
  /**
22
24
  * @description Initialize sync utilities API requests
23
25
  * @param {Object} contentstack - Contentstack configuration details
24
- */
26
+ */
25
27
  const init = (contentstack) => {
26
28
  const packageInfo = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..', 'package.json')));
27
29
  Contentstack = contentstack;
@@ -36,6 +38,12 @@ const init = (contentstack) => {
36
38
  if (Contentstack.MAX_RETRY_LIMIT) {
37
39
  MAX_RETRY_LIMIT = Contentstack.MAX_RETRY_LIMIT;
38
40
  }
41
+ if (Contentstack.RETRY_DELAY_BASE) {
42
+ RETRY_DELAY_BASE = Contentstack.RETRY_DELAY_BASE;
43
+ }
44
+ if (Contentstack.TIMEOUT) {
45
+ TIMEOUT = Contentstack.TIMEOUT;
46
+ }
39
47
  };
40
48
  exports.init = init;
41
49
  /**
@@ -60,12 +68,13 @@ const get = (req, RETRY = 1) => {
60
68
  path: (0, sanitize_url_1.sanitizeUrl)(encodeURI(req.path)),
61
69
  port: Contentstack.port,
62
70
  protocol: Contentstack.protocol,
71
+ timeout: TIMEOUT, // Configurable timeout to prevent socket hang ups
63
72
  };
64
73
  try {
65
74
  debug(`${options.method.toUpperCase()}: ${options.path}`);
66
75
  let timeDelay;
67
76
  let body = '';
68
- (0, https_1.request)(options, (response) => {
77
+ const httpRequest = (0, https_1.request)(options, (response) => {
69
78
  response
70
79
  .setEncoding('utf-8')
71
80
  .on('data', (chunk) => body += chunk)
@@ -75,8 +84,8 @@ const get = (req, RETRY = 1) => {
75
84
  return resolve(JSON.parse(body));
76
85
  }
77
86
  else if (response.statusCode === 429) {
78
- timeDelay = Math.pow(Math.SQRT2, RETRY) * 200;
79
- debug(`API rate limit exceeded. Retrying ${options.path} with ${timeDelay} sec delay`);
87
+ timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
88
+ debug(`API rate limit exceeded. Retrying ${options.path} with ${timeDelay} ms delay`);
80
89
  return setTimeout(() => {
81
90
  return (0, exports.get)(req, RETRY)
82
91
  .then(resolve)
@@ -85,8 +94,8 @@ const get = (req, RETRY = 1) => {
85
94
  }
86
95
  else if (response.statusCode >= 500) {
87
96
  // retry, with delay
88
- timeDelay = Math.pow(Math.SQRT2, RETRY) * 200;
89
- debug(`Retrying ${options.path} with ${timeDelay} sec delay`);
97
+ timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
98
+ debug(`Retrying ${options.path} with ${timeDelay} ms delay`);
90
99
  RETRY++;
91
100
  return setTimeout(() => {
92
101
  return (0, exports.get)(req, RETRY)
@@ -99,9 +108,31 @@ const get = (req, RETRY = 1) => {
99
108
  return reject(body);
100
109
  }
101
110
  });
102
- })
103
- .on('error', reject)
104
- .end();
111
+ });
112
+ // Set socket timeout to handle socket hang ups
113
+ httpRequest.setTimeout(options.timeout, () => {
114
+ debug(`Request timeout for ${options.path || 'unknown'}`);
115
+ httpRequest.destroy();
116
+ reject(new Error('Request timeout'));
117
+ });
118
+ // Enhanced error handling for socket hang ups and connection resets
119
+ httpRequest.on('error', (error) => {
120
+ var _a;
121
+ debug(`Request error for ${options.path || 'unknown'}: ${(error === null || error === void 0 ? void 0 : error.message) || 'Unknown error'} (${(error === null || error === void 0 ? void 0 : error.code) || 'NO_CODE'})`);
122
+ // Handle socket hang up and connection reset errors with retry
123
+ if (((error === null || error === void 0 ? void 0 : error.code) === 'ECONNRESET' || ((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('socket hang up'))) && RETRY <= MAX_RETRY_LIMIT) {
124
+ timeDelay = Math.pow(Math.SQRT2, RETRY) * RETRY_DELAY_BASE;
125
+ debug(`Socket hang up detected. Retrying ${options.path || 'unknown'} with ${timeDelay} ms delay (attempt ${RETRY}/${MAX_RETRY_LIMIT})`);
126
+ RETRY++;
127
+ return setTimeout(() => {
128
+ return (0, exports.get)(req, RETRY)
129
+ .then(resolve)
130
+ .catch(reject);
131
+ }, timeDelay);
132
+ }
133
+ return reject(error);
134
+ });
135
+ httpRequest.end();
105
136
  }
106
137
  catch (error) {
107
138
  return reject(error);
package/dist/config.js CHANGED
@@ -35,6 +35,8 @@ exports.config = {
35
35
  },
36
36
  contentstack: {
37
37
  MAX_RETRY_LIMIT: 6,
38
+ TIMEOUT: 30000,
39
+ RETRY_DELAY_BASE: 200,
38
40
  actions: {
39
41
  delete: 'delete',
40
42
  publish: 'publish',
package/dist/core/inet.js CHANGED
@@ -68,7 +68,10 @@ const checkNetConnectivity = () => {
68
68
  };
69
69
  exports.checkNetConnectivity = checkNetConnectivity;
70
70
  const netConnectivityIssues = (error) => {
71
- if (error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT') {
71
+ var _a;
72
+ // Include socket hang up and connection reset errors as network connectivity issues
73
+ const networkErrorCodes = ['ENOTFOUND', 'ETIMEDOUT', 'ECONNRESET', 'EPIPE', 'EHOSTUNREACH'];
74
+ if (networkErrorCodes.includes(error.code) || ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('socket hang up'))) {
72
75
  return true;
73
76
  }
74
77
  return false;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contentstack/datasync-manager",
3
3
  "author": "Contentstack LLC <support@contentstack.com>",
4
- "version": "2.1.1",
4
+ "version": "2.1.2",
5
5
  "description": "The primary module of Contentstack DataSync. Syncs Contentstack data with your server using Contentstack Sync API",
6
6
  "main": "dist/index.js",
7
7
  "dependencies": {