@opentermsarchive/engine 1.0.0 → 1.1.0
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/package.json +1 -1
- package/src/archivist/index.js +8 -5
- package/src/archivist/index.test.js +74 -0
- package/src/index.js +12 -4
- package/src/logger/index.js +4 -0
package/package.json
CHANGED
package/src/archivist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export const EVENTS = [
|
|
|
29
29
|
'trackingCompleted',
|
|
30
30
|
'inaccessibleContent',
|
|
31
31
|
'error',
|
|
32
|
+
'pluginError',
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
export default class Archivist extends events.EventEmitter {
|
|
@@ -72,10 +73,6 @@ export default class Archivist extends events.EventEmitter {
|
|
|
72
73
|
initQueue() {
|
|
73
74
|
this.trackingQueue = async.queue(this.trackTermsChanges.bind(this), MAX_PARALLEL_TRACKING);
|
|
74
75
|
this.trackingQueue.error(async (error, { terms }) => {
|
|
75
|
-
if (error.toString().includes('HttpError: API rate limit exceeded for user ID')) {
|
|
76
|
-
return; // This is an error due to SendInBlue quota, bypass
|
|
77
|
-
}
|
|
78
|
-
|
|
79
76
|
if (error instanceof InaccessibleContentError) {
|
|
80
77
|
this.emit('inaccessibleContent', error, terms);
|
|
81
78
|
|
|
@@ -91,7 +88,13 @@ export default class Archivist extends events.EventEmitter {
|
|
|
91
88
|
const handlerName = `on${event[0].toUpperCase()}${event.substring(1)}`;
|
|
92
89
|
|
|
93
90
|
if (listener[handlerName]) {
|
|
94
|
-
this.on(event,
|
|
91
|
+
this.on(event, async (...params) => {
|
|
92
|
+
try {
|
|
93
|
+
await listener[handlerName](...params); // Prefer try...catch over .catch() for handling errors to account for both synchronous and asynchronous functions, as .catch() cannot be applied to synchronous functions
|
|
94
|
+
} catch (error) {
|
|
95
|
+
this.emit('pluginError', error, listener.constructor.name);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
95
98
|
}
|
|
96
99
|
});
|
|
97
100
|
}
|
|
@@ -245,6 +245,80 @@ describe('Archivist', function () {
|
|
|
245
245
|
});
|
|
246
246
|
});
|
|
247
247
|
|
|
248
|
+
describe('Plugin system', () => {
|
|
249
|
+
const plugin = {};
|
|
250
|
+
|
|
251
|
+
describe('#attach', () => {
|
|
252
|
+
before(async () => {
|
|
253
|
+
app = new Archivist({
|
|
254
|
+
recorderConfig: config.get('recorder'),
|
|
255
|
+
fetcherConfig: config.get('fetcher'),
|
|
256
|
+
});
|
|
257
|
+
await app.initialize();
|
|
258
|
+
|
|
259
|
+
EVENTS.forEach(event => {
|
|
260
|
+
const handlerName = `on${event[0].toUpperCase()}${event.substring(1)}`;
|
|
261
|
+
|
|
262
|
+
plugin[handlerName] = sinon.spy();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
app.removeAllListeners('error');
|
|
266
|
+
expect(app.eventNames()).to.be.empty;
|
|
267
|
+
app.attach(plugin);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
EVENTS.forEach(event => {
|
|
271
|
+
const handlerName = `on${event[0].toUpperCase()}${event.substring(1)}`;
|
|
272
|
+
|
|
273
|
+
it(`attaches plugin "${event}" handler`, () => {
|
|
274
|
+
app.emit(event);
|
|
275
|
+
expect(plugin[handlerName].calledOnce).to.be.true;
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
context('when errors occur within a plugin', () => {
|
|
281
|
+
let error;
|
|
282
|
+
let listeners;
|
|
283
|
+
let plugin;
|
|
284
|
+
|
|
285
|
+
before(async () => {
|
|
286
|
+
nock.cleanAll();
|
|
287
|
+
nock('https://www.servicea.example').get('/tos').reply(200, serviceASnapshotExpectedContent, { 'Content-Type': 'text/html' });
|
|
288
|
+
|
|
289
|
+
app = new Archivist({
|
|
290
|
+
recorderConfig: config.get('recorder'),
|
|
291
|
+
fetcherConfig: config.get('fetcher'),
|
|
292
|
+
});
|
|
293
|
+
await app.initialize();
|
|
294
|
+
|
|
295
|
+
plugin = { onFirstVersionRecorded: () => { throw new Error('Plugin error'); } };
|
|
296
|
+
|
|
297
|
+
listeners = process.listeners('unhandledRejection'); // back up listeners
|
|
298
|
+
process.removeAllListeners('unhandledRejection'); // remove all listeners to avoid exit the process
|
|
299
|
+
|
|
300
|
+
process.on('unhandledRejection', reason => { error = reason; });
|
|
301
|
+
|
|
302
|
+
app.attach(plugin);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
after(async () => {
|
|
306
|
+
process.removeAllListeners('unhandledRejection');
|
|
307
|
+
listeners.forEach(listener => process.on('unhandledRejection', listener));
|
|
308
|
+
await resetGitRepositories();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('does not crash the tracking process', done => {
|
|
312
|
+
app.track({ services: [services[0]] }).then(() => {
|
|
313
|
+
if (error) {
|
|
314
|
+
return done(error);
|
|
315
|
+
}
|
|
316
|
+
done();
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
248
322
|
describe('events', () => {
|
|
249
323
|
const spies = {};
|
|
250
324
|
|
package/src/index.js
CHANGED
|
@@ -39,17 +39,25 @@ export default async function track({ services, types, extractOnly, schedule })
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (process.env.SENDINBLUE_API_KEY) {
|
|
42
|
-
|
|
42
|
+
try {
|
|
43
|
+
archivist.attach(new Notifier(archivist.services));
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.error('Cannot instantiate the Notifier module; it will be ignored:', error);
|
|
46
|
+
}
|
|
43
47
|
} else {
|
|
44
48
|
logger.warn('Environment variable "SENDINBLUE_API_KEY" was not found; the Notifier module will be ignored');
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
if (process.env.GITHUB_TOKEN) {
|
|
48
52
|
if (config.has('reporter.githubIssues.repositories.declarations')) {
|
|
49
|
-
|
|
53
|
+
try {
|
|
54
|
+
const reporter = new Reporter(config.get('reporter'));
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
await reporter.initialize();
|
|
57
|
+
archivist.attach(reporter);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
logger.error('Cannot instantiate the Reporter module; it will be ignored:', error);
|
|
60
|
+
}
|
|
53
61
|
} else {
|
|
54
62
|
logger.warn('Configuration key "reporter.githubIssues.repositories.declarations" was not found; issues on the declarations repository cannot be created');
|
|
55
63
|
}
|
package/src/logger/index.js
CHANGED
|
@@ -136,4 +136,8 @@ logger.onError = (error, terms) => {
|
|
|
136
136
|
logger.error({ message: error.stack, serviceId: terms.serviceId, termsType: terms.type });
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
+
logger.onPluginError = (error, pluginName) => {
|
|
140
|
+
logger.error({ message: `Error in "${pluginName}" plugin: ${error.stack}` });
|
|
141
|
+
};
|
|
142
|
+
|
|
139
143
|
export default logger;
|