@quatrain/worker 1.2.11 → 1.2.14-pr25.8334

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.
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.FileSystem = void 0;
40
- const node_fs_1 = __importStar(require("node:fs"));
40
+ const node_fs_1 = __importDefault(require("node:fs"));
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const axios_1 = __importDefault(require("axios"));
43
43
  const Worker_1 = require("./Worker");
@@ -137,80 +137,66 @@ class FileSystem {
137
137
  */
138
138
  static async uploadFile(filename, meta, mime = 'video/mp4') {
139
139
  // try to get more file metadata
140
- const info = await FileSystem.getInfo(filename);
140
+ let info = {};
141
+ try {
142
+ info = await FileSystem.getInfo(filename);
143
+ }
144
+ catch (err) {
145
+ Worker_1.Worker.warn(`Could not probe media info for ${filename}: ${err?.message || err}`);
146
+ }
141
147
  meta = { ...meta, ...info };
142
148
  Worker_1.Worker.info(`Uploading file ${filename} to ${meta.uploadUrl}`);
143
149
  const { size } = node_fs_1.default.statSync(filename);
144
- if (size < 32 * 1024) {
145
- return new Promise((resolve, reject) => {
146
- (0, node_fetch_native_1.default)(meta.uploadUrl, {
147
- method: 'PUT',
148
- mode: 'cors',
149
- duplex: 'half',
150
- body: (0, node_fs_1.readFileSync)(filename),
151
- headers: {
152
- 'Content-Type': meta.contentType || mime,
153
- 'Content-length': String(size),
154
- },
155
- })
156
- .then(() => resolve({ ...meta, size, uploadUrl: undefined }))
157
- .catch((err) => {
158
- Worker_1.Worker.error(`An error occured while uploading ${filename}: ${err.message}`);
159
- reject(err);
160
- });
150
+ try {
151
+ Worker_1.Worker.info(`Uploading file ${filename} with size ${size} bytes`);
152
+ const fileBuffer = node_fs_1.default.readFileSync(filename);
153
+ const res = await (0, node_fetch_native_1.default)(meta.uploadUrl, {
154
+ method: 'PUT',
155
+ body: fileBuffer,
156
+ headers: {
157
+ 'Content-Type': meta.contentType || mime,
158
+ },
161
159
  });
162
- }
163
- return new Promise((resolve, reject) => {
164
- try {
165
- let done = 0; // total bytes uploaded
166
- let prev = 0; // latest value of done stored when % done was displayed
167
- const { size } = node_fs_1.default.statSync(filename);
168
- const readStream = node_fs_1.default.createReadStream(filename);
169
- const sizeMB = (size / (1024 * 1024)).toFixed(2);
170
- readStream.on('data', (data) => {
171
- done += data.length;
172
- if (done - prev >= size / 20) {
173
- // only display message when 5% more has been uploaded
174
- Worker_1.Worker.info(`${((done / size) * 100).toFixed(2)}% - ${(done /
175
- (1024 * 1024)).toFixed(2)}MB / ${sizeMB}MB`);
176
- prev = done;
177
- }
178
- });
179
- Worker_1.Worker.info(`Uploading file ${filename} with size ${size} bytes`);
180
- (0, node_fetch_native_1.default)(meta.uploadUrl, {
181
- method: 'PUT',
182
- mode: 'cors',
183
- duplex: 'half',
184
- body: readStream,
185
- headers: {
186
- 'Content-Type': meta.contentType || mime,
187
- 'Content-length': String(size),
188
- },
189
- })
190
- .then(() => resolve({ ...meta, size, uploadUrl: undefined }))
191
- .catch((err) => {
192
- Worker_1.Worker.error(`An error occured while uploading ${filename}: ${err.message}`);
193
- reject(err);
194
- });
160
+ if (res && res.ok === false) {
161
+ const errorText = typeof res.text === 'function' ? await res.text().catch(() => '') : '';
162
+ throw new Error(`HTTP upload failed with status ${res.status || 'unknown'}: ${errorText}`);
195
163
  }
196
- catch (err) {
197
- Worker_1.Worker.error(err);
198
- reject(err);
199
- }
200
- });
164
+ return { ...meta, size, uploadUrl: undefined };
165
+ }
166
+ catch (err) {
167
+ Worker_1.Worker.error(`An error occured while uploading ${filename}: ${err.message}`);
168
+ throw err;
169
+ }
201
170
  }
202
171
  /**
203
172
  * Return meta data on given file
204
173
  */
205
174
  static getInfo = (file) => {
206
175
  if (file.endsWith('.mp4') || file.endsWith('.insv')) {
176
+ try {
177
+ const ffprobeStatic = require('ffprobe-static');
178
+ if (ffprobeStatic && ffprobeStatic.path) {
179
+ ffmpeg.setFfprobePath(ffprobeStatic.path);
180
+ }
181
+ }
182
+ catch {
183
+ // ffprobe-static not present, fallback to system PATH
184
+ }
207
185
  return new Promise((resolve, reject) => ffmpeg.ffprobe(file, (err, metadata) => {
208
186
  if (err) {
209
187
  Worker_1.Worker.error(err);
210
- reject(err);
188
+ return reject(err);
189
+ }
190
+ if (!metadata || !metadata.streams || !metadata.streams.length) {
191
+ Worker_1.Worker.warn(`No streams found in ffprobe metadata for ${file}`);
192
+ return resolve({});
193
+ }
194
+ const videoStream = metadata.streams.find((s) => s.codec_type === 'video') ||
195
+ metadata.streams[0];
196
+ if (!videoStream) {
197
+ return resolve({});
211
198
  }
212
- // Worker.debug(`ffprobe getInfo: ${JSON.stringify(metadata)}`)
213
- const { width, height, duration, bit_rate: bitrate, nb_frames: nbFramees, } = metadata.streams[0];
199
+ const { width, height, duration, bit_rate: bitrate, nb_frames: nbFramees, } = videoStream;
214
200
  const nb_frames = Number.parseFloat(nbFramees);
215
201
  const framerate = nb_frames / Number.parseFloat(duration);
216
202
  resolve({
@@ -94,6 +94,12 @@ describe('FileSystem Utilities (Worker)', () => {
94
94
  jest.spyOn(node_fs_1.default, 'createReadStream').mockImplementation(() => {
95
95
  return node_stream_1.Readable.from(Buffer.alloc(35 * 1024));
96
96
  });
97
+ jest.spyOn(node_fs_1.default, 'readFileSync').mockImplementation((p) => {
98
+ if (typeof p === 'string' && (p.endsWith('test.txt') || p.endsWith('small.mp4') || p.endsWith('large.mp4') || p.endsWith('large-fail.mp4') || p.endsWith('small-fail.mp4') || p.endsWith('large-sync-fail.mp4'))) {
99
+ return Buffer.alloc(35 * 1024);
100
+ }
101
+ return (jest.requireActual('node:fs').readFileSync)(p);
102
+ });
97
103
  jest.spyOn(node_fs_1.default, 'existsSync').mockImplementation((p) => {
98
104
  if (typeof p === 'string' && (p.endsWith('test.txt') || p.endsWith('small.mp4') || p.endsWith('large.mp4') || p.endsWith('large-fail.mp4') || p.endsWith('small-fail.mp4') || p.endsWith('large-sync-fail.mp4'))) {
99
105
  return true;
@@ -330,8 +336,8 @@ describe('FileSystem Utilities (Worker)', () => {
330
336
  ffmpeg.ffprobe.mockImplementation((file, callback) => {
331
337
  callback(null, mockMetadata);
332
338
  });
333
- // Make createReadStream throw a synchronous error
334
- jest.spyOn(node_fs_1.default, 'createReadStream').mockImplementationOnce(() => {
339
+ // Make readFileSync throw a synchronous error
340
+ jest.spyOn(node_fs_1.default, 'readFileSync').mockImplementationOnce(() => {
335
341
  throw new Error('Sync stream error');
336
342
  });
337
343
  const meta = {
package/dist/Worker.d.ts CHANGED
@@ -25,7 +25,7 @@ export declare class Worker extends Core {
25
25
  * @param ts timestamp
26
26
  * @returns boolean
27
27
  */
28
- static pushEvent(event: string, data?: {}, ts?: number): false | undefined;
28
+ static pushEvent(event: string, data?: {}, ts?: number): void;
29
29
  /**
30
30
  * Async Push an event to the backend endpoint, if available
31
31
  * @param event string
@@ -33,7 +33,7 @@ export declare class Worker extends Core {
33
33
  * @param ts timestamp
34
34
  * @returns boolean
35
35
  */
36
- static pushEventAsync(event: string, data?: {}, ts?: number): Promise<boolean | undefined>;
36
+ static pushEventAsync(event: string, data?: {}, ts?: number): Promise<true | undefined>;
37
37
  /**
38
38
  * Global handling function to process received messages
39
39
  * @param messageHandler function
package/dist/Worker.js CHANGED
@@ -59,8 +59,8 @@ class Worker extends core_1.Core {
59
59
  */
60
60
  static pushEvent(event, data = {}, ts = 0) {
61
61
  if (!this.endpoint) {
62
- Worker.warn(`Events endpoint is not set, can't send update!`);
63
- return false;
62
+ Worker.error(`Events endpoint is mandatory but missing! Cannot report job status to source.`);
63
+ throw new Error(`Events endpoint is mandatory but missing`);
64
64
  }
65
65
  ts = ts === Date.now() ? Date.now() + 1 : Date.now();
66
66
  const payload = {
@@ -79,8 +79,7 @@ class Worker extends core_1.Core {
79
79
  return true;
80
80
  })
81
81
  .catch((err) => {
82
- Worker.error(`Failed to push event to backend: ${err}`);
83
- return false;
82
+ Worker.error(`Failed to push event to backend: ${err.message}`);
84
83
  });
85
84
  }
86
85
  /**
@@ -92,8 +91,8 @@ class Worker extends core_1.Core {
92
91
  */
93
92
  static async pushEventAsync(event, data = {}, ts = 0) {
94
93
  if (!this.endpoint) {
95
- Worker.warn(`Events endpoint is not set, can't send update!`);
96
- return false;
94
+ Worker.error(`Events endpoint is mandatory but missing! Cannot report job status to source.`);
95
+ throw new Error(`Events endpoint is mandatory but missing`);
97
96
  }
98
97
  try {
99
98
  ts = ts === Date.now() ? Date.now() + 1 : Date.now();
@@ -105,14 +104,14 @@ class Worker extends core_1.Core {
105
104
  ts,
106
105
  };
107
106
  const res = await axios_1.default.patch(Worker.endpoint, payload);
108
- if (res.statusText === 'OK') {
107
+ if (res.statusText === 'OK' || res.status === 200) {
109
108
  Worker.info(`Event pushed to backend: ${res.statusText}`);
110
109
  return true;
111
110
  }
112
111
  }
113
112
  catch (err) {
114
- Worker.error(`Failed to push event to backend: ${err}`);
115
- return false;
113
+ Worker.error(`Failed to push event to backend: ${err.message}`);
114
+ throw new Error(`Failed to push event to backend: ${err.message}`);
116
115
  }
117
116
  }
118
117
  /**
@@ -40,9 +40,8 @@ describe('Worker', () => {
40
40
  });
41
41
  });
42
42
  describe('pushEvent', () => {
43
- it('should return false when endpoint is not set', () => {
44
- const result = Worker_1.Worker.pushEvent('test-event');
45
- expect(result).toBe(false);
43
+ it('should throw error when endpoint is not set', () => {
44
+ expect(() => Worker_1.Worker.pushEvent('test-event')).toThrow('Events endpoint is mandatory but missing');
46
45
  expect(mockedAxios.patch).not.toHaveBeenCalled();
47
46
  });
48
47
  it('should send event when endpoint is set', () => {
@@ -110,9 +109,8 @@ describe('Worker', () => {
110
109
  });
111
110
  });
112
111
  describe('pushEventAsync', () => {
113
- it('should return false when endpoint is not set', async () => {
114
- const result = await Worker_1.Worker.pushEventAsync('test-event');
115
- expect(result).toBe(false);
112
+ it('should throw error when endpoint is not set', async () => {
113
+ await expect(Worker_1.Worker.pushEventAsync('test-event')).rejects.toThrow('Events endpoint is mandatory but missing');
116
114
  expect(mockedAxios.patch).not.toHaveBeenCalled();
117
115
  });
118
116
  it('should send event and return true on success', async () => {
@@ -130,11 +128,10 @@ describe('Worker', () => {
130
128
  foo: 'bar',
131
129
  }));
132
130
  });
133
- it('should return false on axios error', async () => {
131
+ it('should throw error on axios error', async () => {
134
132
  Worker_1.Worker.endpoint = 'https://api.example.com/events';
135
133
  mockedAxios.patch.mockRejectedValue(new Error('Network error'));
136
- const result = await Worker_1.Worker.pushEventAsync('test-event');
137
- expect(result).toBe(false);
134
+ await expect(Worker_1.Worker.pushEventAsync('test-event')).rejects.toThrow('Failed to push event to backend: Network error');
138
135
  });
139
136
  it('should handle non-OK status response', async () => {
140
137
  Worker_1.Worker.endpoint = 'https://api.example.com/events';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quatrain/worker",
3
- "version": "1.2.11",
3
+ "version": "1.2.14-pr25.8334",
4
4
  "description": "Container Worker helpers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "typescript": "^5.1.5"
35
35
  },
36
36
  "dependencies": {
37
- "@quatrain/core": "^1.2.17",
37
+ "@quatrain/core": "^1.2.18",
38
38
  "@quatrain/queue": "^1.2.3",
39
39
  "@quatrain/storage": "^1.2.13",
40
40
  "axios": "^1.7.7",
@@ -63,6 +63,13 @@ describe('FileSystem Utilities (Worker)', () => {
63
63
  return Readable.from(Buffer.alloc(35 * 1024)) as any
64
64
  })
65
65
 
66
+ jest.spyOn(fs, 'readFileSync').mockImplementation((p) => {
67
+ if (typeof p === 'string' && (p.endsWith('test.txt') || p.endsWith('small.mp4') || p.endsWith('large.mp4') || p.endsWith('large-fail.mp4') || p.endsWith('small-fail.mp4') || p.endsWith('large-sync-fail.mp4'))) {
68
+ return Buffer.alloc(35 * 1024)
69
+ }
70
+ return (jest.requireActual('node:fs').readFileSync)(p)
71
+ })
72
+
66
73
  jest.spyOn(fs, 'existsSync').mockImplementation((p) => {
67
74
  if (typeof p === 'string' && (p.endsWith('test.txt') || p.endsWith('small.mp4') || p.endsWith('large.mp4') || p.endsWith('large-fail.mp4') || p.endsWith('small-fail.mp4') || p.endsWith('large-sync-fail.mp4'))) {
68
75
  return true
@@ -346,8 +353,8 @@ describe('FileSystem Utilities (Worker)', () => {
346
353
  callback(null, mockMetadata)
347
354
  });
348
355
 
349
- // Make createReadStream throw a synchronous error
350
- jest.spyOn(fs, 'createReadStream').mockImplementationOnce(() => {
356
+ // Make readFileSync throw a synchronous error
357
+ jest.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
351
358
  throw new Error('Sync stream error')
352
359
  })
353
360
 
package/src/FileSystem.ts CHANGED
@@ -111,79 +111,38 @@ export class FileSystem {
111
111
  mime = 'video/mp4'
112
112
  ): Promise<FileType> {
113
113
  // try to get more file metadata
114
- const info = await FileSystem.getInfo(filename)
114
+ let info = {}
115
+ try {
116
+ info = await FileSystem.getInfo(filename)
117
+ } catch (err: any) {
118
+ Worker.warn(`Could not probe media info for ${filename}: ${(err as Error)?.message || err}`)
119
+ }
115
120
  meta = { ...meta, ...info }
116
121
  Worker.info(`Uploading file ${filename} to ${meta.uploadUrl}`)
117
122
  const { size } = fs.statSync(filename)
118
123
 
119
- if (size < 32 * 1024) {
120
- return new Promise((resolve, reject) => {
121
- fetch(meta.uploadUrl, {
122
- method: 'PUT',
123
- mode: 'cors',
124
- duplex: 'half',
125
- body: readFileSync(filename),
126
- headers: {
127
- 'Content-Type': meta.contentType || mime,
128
- 'Content-length': String(size),
129
- },
130
- } as any)
131
- .then(() => resolve({ ...meta, size, uploadUrl: undefined }))
132
- .catch((err) => {
133
- Worker.error(
134
- `An error occured while uploading ${filename}: ${err.message}`
135
- )
136
- reject(err)
137
- })
124
+ try {
125
+ Worker.info(`Uploading file ${filename} with size ${size} bytes`)
126
+ const fileBuffer = fs.readFileSync(filename)
127
+
128
+ const res = await fetch(meta.uploadUrl, {
129
+ method: 'PUT',
130
+ body: fileBuffer,
131
+ headers: {
132
+ 'Content-Type': meta.contentType || mime,
133
+ },
138
134
  })
139
- }
140
135
 
141
- return new Promise((resolve, reject) => {
142
- try {
143
- let done = 0 // total bytes uploaded
144
- let prev = 0 // latest value of done stored when % done was displayed
145
- const { size } = fs.statSync(filename)
146
- const readStream = fs.createReadStream(filename)
147
-
148
- const sizeMB = (size / (1024 * 1024)).toFixed(2)
149
-
150
- readStream.on('data', (data) => {
151
- done += data.length
152
- if (done - prev >= size / 20) {
153
- // only display message when 5% more has been uploaded
154
- Worker.info(
155
- `${((done / size) * 100).toFixed(2)}% - ${(
156
- done /
157
- (1024 * 1024)
158
- ).toFixed(2)}MB / ${sizeMB}MB`
159
- )
160
- prev = done
161
- }
162
- })
163
-
164
- Worker.info(`Uploading file ${filename} with size ${size} bytes`)
165
- fetch(meta.uploadUrl, {
166
- method: 'PUT',
167
- mode: 'cors',
168
- duplex: 'half',
169
- body: readStream,
170
- headers: {
171
- 'Content-Type': meta.contentType || mime,
172
- 'Content-length': String(size),
173
- },
174
- } as any)
175
- .then(() => resolve({ ...meta, size, uploadUrl: undefined }))
176
- .catch((err) => {
177
- Worker.error(
178
- `An error occured while uploading ${filename}: ${err.message}`
179
- )
180
- reject(err)
181
- })
182
- } catch (err) {
183
- Worker.error(err)
184
- reject(err)
136
+ if (res && res.ok === false) {
137
+ const errorText = typeof res.text === 'function' ? await res.text().catch(() => '') : ''
138
+ throw new Error(`HTTP upload failed with status ${res.status || 'unknown'}: ${errorText}`)
185
139
  }
186
- })
140
+
141
+ return { ...meta, size, uploadUrl: undefined }
142
+ } catch (err: any) {
143
+ Worker.error(`An error occured while uploading ${filename}: ${err.message}`)
144
+ throw err
145
+ }
187
146
  }
188
147
 
189
148
  /**
@@ -191,22 +150,46 @@ export class FileSystem {
191
150
  */
192
151
  static getInfo = (file: string): Promise<any> => {
193
152
  if (file.endsWith('.mp4') || file.endsWith('.insv')) {
153
+ try {
154
+ const ffprobeStatic = require('ffprobe-static')
155
+ if (ffprobeStatic && ffprobeStatic.path) {
156
+ ffmpeg.setFfprobePath(ffprobeStatic.path)
157
+ }
158
+ } catch {
159
+ // ffprobe-static not present, fallback to system PATH
160
+ }
161
+
194
162
  return new Promise((resolve, reject) =>
195
163
  ffmpeg.ffprobe(file, (err: any, metadata: any) => {
196
164
  if (err) {
197
165
  Worker.error(err)
198
- reject(err)
166
+ return reject(err)
167
+ }
168
+
169
+ if (!metadata || !metadata.streams || !metadata.streams.length) {
170
+ Worker.warn(`No streams found in ffprobe metadata for ${file}`)
171
+ return resolve({})
199
172
  }
200
- // Worker.debug(`ffprobe getInfo: ${JSON.stringify(metadata)}`)
173
+
174
+ const videoStream =
175
+ metadata.streams.find((s: any) => s.codec_type === 'video') ||
176
+ metadata.streams[0]
177
+
178
+ if (!videoStream) {
179
+ return resolve({})
180
+ }
181
+
201
182
  const {
202
183
  width,
203
184
  height,
204
185
  duration,
205
186
  bit_rate: bitrate,
206
187
  nb_frames: nbFramees,
207
- } = metadata.streams[0]
188
+ } = videoStream
189
+
208
190
  const nb_frames: number = Number.parseFloat(nbFramees as string)
209
191
  const framerate = nb_frames / Number.parseFloat(duration as string)
192
+
210
193
  resolve({
211
194
  width,
212
195
  height,
@@ -42,9 +42,8 @@ describe('Worker', () => {
42
42
  })
43
43
 
44
44
  describe('pushEvent', () => {
45
- it('should return false when endpoint is not set', () => {
46
- const result = Worker.pushEvent('test-event')
47
- expect(result).toBe(false)
45
+ it('should throw error when endpoint is not set', () => {
46
+ expect(() => Worker.pushEvent('test-event')).toThrow('Events endpoint is mandatory but missing')
48
47
  expect(mockedAxios.patch).not.toHaveBeenCalled()
49
48
  })
50
49
 
@@ -145,9 +144,8 @@ describe('Worker', () => {
145
144
  })
146
145
 
147
146
  describe('pushEventAsync', () => {
148
- it('should return false when endpoint is not set', async () => {
149
- const result = await Worker.pushEventAsync('test-event')
150
- expect(result).toBe(false)
147
+ it('should throw error when endpoint is not set', async () => {
148
+ await expect(Worker.pushEventAsync('test-event')).rejects.toThrow('Events endpoint is mandatory but missing')
151
149
  expect(mockedAxios.patch).not.toHaveBeenCalled()
152
150
  })
153
151
 
@@ -173,14 +171,12 @@ describe('Worker', () => {
173
171
  )
174
172
  })
175
173
 
176
- it('should return false on axios error', async () => {
174
+ it('should throw error on axios error', async () => {
177
175
  Worker.endpoint = 'https://api.example.com/events'
178
176
 
179
177
  mockedAxios.patch.mockRejectedValue(new Error('Network error'))
180
178
 
181
- const result = await Worker.pushEventAsync('test-event')
182
-
183
- expect(result).toBe(false)
179
+ await expect(Worker.pushEventAsync('test-event')).rejects.toThrow('Failed to push event to backend: Network error')
184
180
  })
185
181
 
186
182
  it('should handle non-OK status response', async () => {
package/src/Worker.ts CHANGED
@@ -66,8 +66,8 @@ export class Worker extends Core {
66
66
  */
67
67
  static pushEvent(event: string, data = {}, ts = 0) {
68
68
  if (!this.endpoint) {
69
- Worker.warn(`Events endpoint is not set, can't send update!`)
70
- return false
69
+ Worker.error(`Events endpoint is mandatory but missing! Cannot report job status to source.`)
70
+ throw new Error(`Events endpoint is mandatory but missing`)
71
71
  }
72
72
 
73
73
  ts = ts === Date.now() ? Date.now() + 1 : Date.now()
@@ -89,8 +89,7 @@ export class Worker extends Core {
89
89
  return true
90
90
  })
91
91
  .catch((err) => {
92
- Worker.error(`Failed to push event to backend: ${err}`)
93
- return false
92
+ Worker.error(`Failed to push event to backend: ${err.message}`)
94
93
  })
95
94
  }
96
95
 
@@ -103,8 +102,8 @@ export class Worker extends Core {
103
102
  */
104
103
  static async pushEventAsync(event: string, data = {}, ts = 0) {
105
104
  if (!this.endpoint) {
106
- Worker.warn(`Events endpoint is not set, can't send update!`)
107
- return false
105
+ Worker.error(`Events endpoint is mandatory but missing! Cannot report job status to source.`)
106
+ throw new Error(`Events endpoint is mandatory but missing`)
108
107
  }
109
108
 
110
109
  try {
@@ -119,13 +118,13 @@ export class Worker extends Core {
119
118
 
120
119
  const res = await axios.patch(Worker.endpoint, payload)
121
120
 
122
- if (res.statusText === 'OK') {
121
+ if (res.statusText === 'OK' || res.status === 200) {
123
122
  Worker.info(`Event pushed to backend: ${res.statusText}`)
124
123
  return true
125
124
  }
126
- } catch (err) {
127
- Worker.error(`Failed to push event to backend: ${err}`)
128
- return false
125
+ } catch (err: any) {
126
+ Worker.error(`Failed to push event to backend: ${err.message}`)
127
+ throw new Error(`Failed to push event to backend: ${err.message}`)
129
128
  }
130
129
  }
131
130