@pager/minion-army 2.0.0 → 2.2.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/.eslintrc.js +1 -1
- package/.github/workflows/release.yml +6 -4
- package/CHANGELOG.md +7 -0
- package/cloudbuild.yaml +39 -0
- package/lib/index.js +10 -3
- package/lib/loggingUtils.js +112 -0
- package/lib/schema.js +6 -2
- package/package.json +7 -4
- package/test/index.js +79 -0
- package/test/loggingUtils.js +178 -0
- package/.circleci/config.yml +0 -61
package/.eslintrc.js
CHANGED
|
@@ -9,13 +9,15 @@ jobs:
|
|
|
9
9
|
runs-on: ubuntu-latest
|
|
10
10
|
steps:
|
|
11
11
|
- name: Checkout
|
|
12
|
-
uses: actions/checkout@
|
|
12
|
+
uses: actions/checkout@v2
|
|
13
|
+
with:
|
|
14
|
+
persist-credentials: false
|
|
13
15
|
- name: Setup Node.js
|
|
14
|
-
uses: actions/setup-node@
|
|
16
|
+
uses: actions/setup-node@v2
|
|
15
17
|
with:
|
|
16
|
-
node-version:
|
|
18
|
+
node-version: 18
|
|
17
19
|
- name: Cache
|
|
18
|
-
uses: actions/cache@
|
|
20
|
+
uses: actions/cache@v2
|
|
19
21
|
with:
|
|
20
22
|
path: ~/.npm
|
|
21
23
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package.json') }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [2.1.0](https://github.com/pagerinc/minion-army/compare/v2.0.0...v2.1.0) (2023-05-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add requeue to the schema ([#453](https://github.com/pagerinc/minion-army/issues/453)) ([74a5c41](https://github.com/pagerinc/minion-army/commit/74a5c4127aee8513500edfe04760bf03ffee057f))
|
|
7
|
+
|
|
1
8
|
# [2.0.0](https://github.com/pagerinc/minion-army/compare/v1.3.0...v2.0.0) (2020-08-19)
|
|
2
9
|
|
|
3
10
|
|
package/cloudbuild.yaml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
steps:
|
|
2
|
+
- id: npm-install
|
|
3
|
+
name: node:18
|
|
4
|
+
secretEnv: ['NPM_TOKEN']
|
|
5
|
+
entrypoint: npm
|
|
6
|
+
args: ['i', '--quiet', '--package-lock-only']
|
|
7
|
+
|
|
8
|
+
- id: npm-ci
|
|
9
|
+
name: node:18
|
|
10
|
+
secretEnv: ['NPM_TOKEN']
|
|
11
|
+
entrypoint: npm
|
|
12
|
+
args: ['ci', '--quiet']
|
|
13
|
+
|
|
14
|
+
- id: test-unit
|
|
15
|
+
name: node:18
|
|
16
|
+
secretEnv: ['NPM_TOKEN']
|
|
17
|
+
entrypoint: npm
|
|
18
|
+
args: ['test']
|
|
19
|
+
|
|
20
|
+
- id: npm-publish
|
|
21
|
+
name: 'gcr.io/$PROJECT_ID/cloudbuilders/npm:6.13.4'
|
|
22
|
+
secretEnv: ['NPM_TOKEN']
|
|
23
|
+
env:
|
|
24
|
+
- 'TAG_NAME=$TAG_NAME'
|
|
25
|
+
- '_PR_NUMBER=$_PR_NUMBER'
|
|
26
|
+
|
|
27
|
+
timeout: 10m
|
|
28
|
+
|
|
29
|
+
logsBucket: 'gs://$PROJECT_ID-primary-cloudbuild-logs'
|
|
30
|
+
|
|
31
|
+
tags:
|
|
32
|
+
- 'backend'
|
|
33
|
+
- 'npm'
|
|
34
|
+
- 'nodejs'
|
|
35
|
+
|
|
36
|
+
secrets:
|
|
37
|
+
- kmsKeyName: projects/production-197117/locations/global/keyRings/gcb/cryptoKeys/main
|
|
38
|
+
secretEnv:
|
|
39
|
+
NPM_TOKEN: 'CiUA/4lqmXwRPPaGHe+X7TS7mwqARNCw5QFq7yfq7ESHaJrf+tzeElEADvOwrLQvnxCLG2wy+H2vD+DWHMosEgIfzpKNBJAVHX1u4FSwIF5utaN6tMIrLuZB18HnK2SKpsXTPvB/+0Eoz1acnj6WO+slz+GUGUnxefU='
|
package/lib/index.js
CHANGED
|
@@ -5,8 +5,9 @@ const { EventEmitter } = require('events');
|
|
|
5
5
|
const Jackrabbit = require('@pager/jackrabbit');
|
|
6
6
|
const Joi = require('joi');
|
|
7
7
|
const Schema = require('./schema');
|
|
8
|
+
const { createLoggerContext } = require('./loggingUtils');
|
|
8
9
|
|
|
9
|
-
const validatorFactory = (handler, schema) => (payload,
|
|
10
|
+
const validatorFactory = (handler, schema) => (payload, ...rest) => { // eslint-disable-line
|
|
10
11
|
|
|
11
12
|
const { error, value } = schema.validate(payload, { stripUnknown: true });
|
|
12
13
|
|
|
@@ -14,7 +15,7 @@ const validatorFactory = (handler, schema) => (payload, metadata) => { // eslint
|
|
|
14
15
|
throw error;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
return handler(value,
|
|
18
|
+
return handler(value, ...rest);
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const createExchange = (connection, workerConfig, exchangeMap) => {
|
|
@@ -83,9 +84,15 @@ module.exports = (_manifest) => {
|
|
|
83
84
|
...manifest.defaults,
|
|
84
85
|
...worker.config
|
|
85
86
|
};
|
|
87
|
+
|
|
88
|
+
let handlerWithLoggerContext = handlerWithValidation;
|
|
89
|
+
if (manifest.logger) {
|
|
90
|
+
handlerWithLoggerContext = createLoggerContext(manifest.logger, worker.config.name, handlerWithValidation);
|
|
91
|
+
}
|
|
92
|
+
|
|
86
93
|
const exchange = createExchange(manifest.connection, workerConfig, exchangeMap);
|
|
87
94
|
|
|
88
|
-
const minion = Minion(
|
|
95
|
+
const minion = Minion(handlerWithLoggerContext, { ...workerConfig, exchange });
|
|
89
96
|
|
|
90
97
|
minion.on('ready', checkReady);
|
|
91
98
|
minion.on('message', (m, meta) => eventEmitter.emit('message', worker.config.name, m, meta));
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { v4: Uuid } = require('uuid');
|
|
4
|
+
|
|
5
|
+
const Lodash = require('lodash');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This is a wrapper around the handler that creates a pino style logger and
|
|
9
|
+
* adds it to a context object as a third argument of the handler
|
|
10
|
+
*
|
|
11
|
+
* @param {*} logger a Pino style logger
|
|
12
|
+
* @param {*} minionWorkerName the name of the minion army worker
|
|
13
|
+
* @param {*} handler the handler to be wrapped
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
exports.createLoggerContext = (logger, minionWorkerName, handler) => {
|
|
17
|
+
|
|
18
|
+
return (value, metadata, context = {}) => {
|
|
19
|
+
|
|
20
|
+
let eventId;
|
|
21
|
+
try {
|
|
22
|
+
eventId = metadata?.properties?.headers?.eventId || Uuid();
|
|
23
|
+
const routingKey = metadata?.fields?.routingKey;
|
|
24
|
+
|
|
25
|
+
context.logger = (context.logger || logger).child({ eventId, routingKey, minionWorkerName });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
// eslint-disable-next-line no-console
|
|
29
|
+
console.log('There was an error while creating a child logger in %s for eventId(%s): %o', minionWorkerName, eventId, error);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return handler(value, metadata, context);
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* This utility crteates a wrapper that adds a field from the event into the logger.
|
|
38
|
+
*
|
|
39
|
+
* Usage:
|
|
40
|
+
*
|
|
41
|
+
* const Logger = require('@pager/logger');
|
|
42
|
+
* const Army = require('@pager/minion-army');
|
|
43
|
+
*
|
|
44
|
+
* const injectEncounterIdFromEvent = injectFieldFromEventAs(Logger, 'encounterId', 'triageId');
|
|
45
|
+
*
|
|
46
|
+
* const handler = (message, metadata, context) {
|
|
47
|
+
* context.logger.info('handling message');
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* const army = Army({
|
|
51
|
+
* workers: [
|
|
52
|
+
* {
|
|
53
|
+
* handler: injectEncounterIdFromEvent(handler),
|
|
54
|
+
* config: {
|
|
55
|
+
* name: `events.foo.encounter.state.updated`,
|
|
56
|
+
* key: '#.encounter.state.updated'
|
|
57
|
+
* },
|
|
58
|
+
* validate: Schemas.states
|
|
59
|
+
* },
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* @param {*} logger a Pino style logger
|
|
63
|
+
* @param {*} loggedFieldName what is the name of the field in the log line
|
|
64
|
+
* @param {*} eventFieldName what is the name of the field in the event payload
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
exports.injectFieldFromEventAs = (logger, loggedFieldName, eventFieldName) => (handler) => { // eslint-disable-line @hapi/hapi/scope-start, @hapi/hapi/no-arrowception
|
|
68
|
+
|
|
69
|
+
return (value, metadata, context = {}) => {
|
|
70
|
+
|
|
71
|
+
context.logger = (context.logger || logger).child({ [loggedFieldName]: value[eventFieldName] });
|
|
72
|
+
|
|
73
|
+
return handler(value, metadata, context);
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* This utility function sets up default event handlers that log
|
|
79
|
+
*
|
|
80
|
+
* Usage:
|
|
81
|
+
*
|
|
82
|
+
* const Logger = require('@pager/logger');
|
|
83
|
+
* const Army = require('@pager/minion-army');
|
|
84
|
+
*
|
|
85
|
+
* const army = Army({ ... });
|
|
86
|
+
* addDefaultLoggingEventHandlers(army, 'UpdatedUserArmy', Logger);
|
|
87
|
+
*
|
|
88
|
+
* @param {*} army: the Army instance
|
|
89
|
+
* @param {*} armyName: a unique identifier for this instance of Army
|
|
90
|
+
* @param {*} parentLogger: a Pino style logger
|
|
91
|
+
*/
|
|
92
|
+
exports.addDefaultLoggingEventHandlers = (parentLogger, army, armyName) => {
|
|
93
|
+
|
|
94
|
+
const logger = parentLogger.child({ armyName });
|
|
95
|
+
|
|
96
|
+
army.on('error', (error) => {
|
|
97
|
+
|
|
98
|
+
logger.error({ error }, 'Handler error in %s', armyName);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
army.on('message', (queue, event, metadata) => {
|
|
102
|
+
|
|
103
|
+
const pickedMetadata = Lodash.pick(metadata, ['properties', 'fields']);
|
|
104
|
+
|
|
105
|
+
logger.info({ queue, event, metadata: pickedMetadata }, 'Got event in %s', armyName);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
army.on('ready', (queue) => {
|
|
109
|
+
|
|
110
|
+
logger.info({ queue }, 'Ready to consume on %s by %s', queue.name, armyName);
|
|
111
|
+
});
|
|
112
|
+
};
|
package/lib/schema.js
CHANGED
|
@@ -19,7 +19,8 @@ const config = Joi.object({
|
|
|
19
19
|
rabbit,
|
|
20
20
|
rabbitUrl: Joi.string(),
|
|
21
21
|
prefetch: Joi.number(),
|
|
22
|
-
queueMode: Joi.string()
|
|
22
|
+
queueMode: Joi.string(),
|
|
23
|
+
requeue: Joi.boolean()
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
const worker = {
|
|
@@ -35,5 +36,8 @@ module.exports = Joi.object({
|
|
|
35
36
|
rabbitUrl: Joi.string()
|
|
36
37
|
}),
|
|
37
38
|
defaults: config,
|
|
38
|
-
workers: Joi.array().items(worker)
|
|
39
|
+
workers: Joi.array().items(worker),
|
|
40
|
+
logger: Joi.object({
|
|
41
|
+
child: Joi.func().required()
|
|
42
|
+
}).unknown(true)
|
|
39
43
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pager/minion-army",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Microservice Framework for RabbitMQ Workers",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,17 +25,20 @@
|
|
|
25
25
|
"homepage": "https://github.com/pagerinc/minion#readme",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@pager/jackrabbit": "5.x",
|
|
28
|
-
"@pager/minion": "3.x"
|
|
28
|
+
"@pager/minion": "3.x",
|
|
29
|
+
"lodash": "^4.17.21"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
32
|
+
"@faker-js/faker": "^8.0.1",
|
|
31
33
|
"@hapi/eslint-config-hapi": "13.x",
|
|
32
34
|
"@hapi/eslint-plugin-hapi": "4.x",
|
|
33
|
-
"@pager/semantic-release-config": "
|
|
35
|
+
"@pager/semantic-release-config": "2.x",
|
|
34
36
|
"ava": "3.x",
|
|
35
37
|
"eslint": "7.x",
|
|
36
38
|
"joi": "^17.2.1",
|
|
37
39
|
"nyc": "15.x",
|
|
38
|
-
"semantic-release": "
|
|
40
|
+
"semantic-release": "21.x",
|
|
41
|
+
"sinon": "^15.0.4"
|
|
39
42
|
},
|
|
40
43
|
"peerDependencies": {
|
|
41
44
|
"joi": "^17.2.0"
|
package/test/index.js
CHANGED
|
@@ -4,8 +4,41 @@ const { EventEmitter } = require('events');
|
|
|
4
4
|
const Test = require('ava');
|
|
5
5
|
const Joi = require('joi');
|
|
6
6
|
|
|
7
|
+
const Sinon = require('sinon');
|
|
8
|
+
const { faker } = require('@faker-js/faker');
|
|
9
|
+
|
|
7
10
|
const Army = require('../lib/index');
|
|
8
11
|
|
|
12
|
+
const sandbox = Sinon.createSandbox();
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Test.beforeEach((t) => {
|
|
16
|
+
|
|
17
|
+
t.context.logger = {
|
|
18
|
+
child: sandbox.stub(),
|
|
19
|
+
info: sandbox.stub()
|
|
20
|
+
};
|
|
21
|
+
t.context.rabbit = {
|
|
22
|
+
topic: () => ({
|
|
23
|
+
publish: sandbox.spy()
|
|
24
|
+
}),
|
|
25
|
+
direct: () => ({
|
|
26
|
+
publish: sandbox.spy()
|
|
27
|
+
})
|
|
28
|
+
};
|
|
29
|
+
t.context.metadata = {
|
|
30
|
+
properties: {
|
|
31
|
+
headers: {
|
|
32
|
+
eventId: faker.string.uuid()
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
fields: {
|
|
36
|
+
routingKey: faker.string.uuid()
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
});
|
|
41
|
+
|
|
9
42
|
Test('Creates army from manifest and workers work', async (t) => {
|
|
10
43
|
|
|
11
44
|
const manifest = {
|
|
@@ -399,3 +432,49 @@ Test('Army uses worker exchange overrides', (t) => {
|
|
|
399
432
|
const army = Army(manifest);
|
|
400
433
|
t.deepEqual(Object.keys(army.exchangeMap), ['direct.events.something.happened', 'topic.my-other-exchange']);
|
|
401
434
|
});
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
Test('Army starts with logger context', async (t) => {
|
|
438
|
+
|
|
439
|
+
const { context: { rabbit, logger, metadata } } = t;
|
|
440
|
+
|
|
441
|
+
const minionWorkerName = faker.word.sample();
|
|
442
|
+
|
|
443
|
+
const handler = sandbox.spy();
|
|
444
|
+
|
|
445
|
+
const manifest = {
|
|
446
|
+
connection: {
|
|
447
|
+
rabbit
|
|
448
|
+
},
|
|
449
|
+
defaults: {
|
|
450
|
+
exchangeName: faker.word.sample()
|
|
451
|
+
},
|
|
452
|
+
workers: [
|
|
453
|
+
{
|
|
454
|
+
handler,
|
|
455
|
+
config: {
|
|
456
|
+
name: minionWorkerName,
|
|
457
|
+
key: faker.word.sample()
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
],
|
|
461
|
+
logger
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
const army = Army(manifest);
|
|
465
|
+
t.truthy(army);
|
|
466
|
+
|
|
467
|
+
const event = {
|
|
468
|
+
data: faker.word.sample()
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
const childLogger = sandbox.spy();
|
|
472
|
+
|
|
473
|
+
t.context.logger.child.returns(childLogger);
|
|
474
|
+
|
|
475
|
+
await army.minions[minionWorkerName].handle(event, metadata);
|
|
476
|
+
|
|
477
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { eventId: metadata.properties.headers.eventId, routingKey: metadata.fields.routingKey, minionWorkerName });
|
|
478
|
+
|
|
479
|
+
Sinon.assert.calledOnceWithExactly(handler, event, metadata, { logger: childLogger });
|
|
480
|
+
});
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Test = require('ava');
|
|
4
|
+
|
|
5
|
+
const Sinon = require('sinon');
|
|
6
|
+
const { faker } = require('@faker-js/faker');
|
|
7
|
+
|
|
8
|
+
const Army = require('../lib/index');
|
|
9
|
+
const { createLoggerContext, injectFieldFromEventAs, addDefaultLoggingEventHandlers } = require('../lib/loggingUtils');
|
|
10
|
+
|
|
11
|
+
const sandbox = Sinon.createSandbox();
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Test.beforeEach((t) => {
|
|
15
|
+
|
|
16
|
+
t.context.logger = {
|
|
17
|
+
child: sandbox.stub()
|
|
18
|
+
};
|
|
19
|
+
t.context.metadata = {
|
|
20
|
+
properties: {
|
|
21
|
+
headers: {
|
|
22
|
+
eventId: faker.string.uuid()
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
fields: {
|
|
26
|
+
routingKey: faker.string.uuid()
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
t.context.event = sandbox.spy();
|
|
30
|
+
t.context.minionWorkerName = faker.word.sample();
|
|
31
|
+
t.context.handler = sandbox.spy();
|
|
32
|
+
t.context.rabbit = {
|
|
33
|
+
topic: () => ({
|
|
34
|
+
publish: sandbox.spy()
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
Test.afterEach((t) => {
|
|
40
|
+
|
|
41
|
+
sandbox.restore();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
Test('createLoggerContext wraps a handler', (t) => {
|
|
45
|
+
|
|
46
|
+
const { context: { logger, event, metadata, minionWorkerName, handler } } = t;
|
|
47
|
+
|
|
48
|
+
const wrappedHandler = createLoggerContext(logger, minionWorkerName, handler);
|
|
49
|
+
|
|
50
|
+
const childLogger = sandbox.spy();
|
|
51
|
+
|
|
52
|
+
t.context.logger.child.returns(childLogger);
|
|
53
|
+
|
|
54
|
+
wrappedHandler(event, metadata);
|
|
55
|
+
|
|
56
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { eventId: metadata.properties.headers.eventId, routingKey: metadata.fields.routingKey, minionWorkerName });
|
|
57
|
+
|
|
58
|
+
Sinon.assert.calledOnceWithExactly(handler, event, metadata, { logger: childLogger });
|
|
59
|
+
|
|
60
|
+
t.pass();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
Test('createLoggerContext does not fail if the logger fails', (t) => {
|
|
64
|
+
|
|
65
|
+
const { context: { logger, event, metadata, minionWorkerName, handler } } = t;
|
|
66
|
+
|
|
67
|
+
const wrappedHandler = createLoggerContext(logger, minionWorkerName, handler);
|
|
68
|
+
|
|
69
|
+
t.context.logger.child.throws(new Error('failed to create logger'));
|
|
70
|
+
|
|
71
|
+
wrappedHandler(event, metadata);
|
|
72
|
+
|
|
73
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { eventId: metadata.properties.headers.eventId, routingKey: metadata.fields.routingKey, minionWorkerName });
|
|
74
|
+
|
|
75
|
+
Sinon.assert.calledOnceWithExactly(handler, event, metadata, {});
|
|
76
|
+
|
|
77
|
+
t.pass();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
Test('injectFieldFromEventAs adds field to the logger', (t) => {
|
|
81
|
+
|
|
82
|
+
const { context: { logger, metadata, handler } } = t;
|
|
83
|
+
|
|
84
|
+
const wrappedHandler = injectFieldFromEventAs(logger, 'encounterId', 'triageId')(handler);
|
|
85
|
+
|
|
86
|
+
const childLogger = sandbox.spy();
|
|
87
|
+
|
|
88
|
+
t.context.logger.child.returns(childLogger);
|
|
89
|
+
|
|
90
|
+
const event = {
|
|
91
|
+
triageId: faker.database.mongodbObjectId()
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
wrappedHandler(event, metadata);
|
|
95
|
+
|
|
96
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { encounterId: event.triageId });
|
|
97
|
+
|
|
98
|
+
Sinon.assert.calledOnceWithExactly(handler, event, metadata, { logger: childLogger });
|
|
99
|
+
|
|
100
|
+
t.pass();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
Test('injectFieldFromEventAs does not add the field to the logger if it is missing', (t) => {
|
|
104
|
+
|
|
105
|
+
const { context: { logger, metadata, handler } } = t;
|
|
106
|
+
|
|
107
|
+
const wrappedHandler = injectFieldFromEventAs(logger, 'encounterId', 'triageId')(handler);
|
|
108
|
+
|
|
109
|
+
const childLogger = sandbox.spy();
|
|
110
|
+
|
|
111
|
+
t.context.logger.child.returns(childLogger);
|
|
112
|
+
|
|
113
|
+
const event = {};
|
|
114
|
+
|
|
115
|
+
wrappedHandler(event, metadata);
|
|
116
|
+
|
|
117
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { encounterId: undefined });
|
|
118
|
+
|
|
119
|
+
Sinon.assert.calledOnceWithExactly(handler, event, metadata, { logger: childLogger });
|
|
120
|
+
|
|
121
|
+
t.pass();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
Test('addDefaultLoggingEventHandlers adds the handlers', (t) => {
|
|
126
|
+
|
|
127
|
+
const { context: { logger, rabbit, metadata } } = t;
|
|
128
|
+
|
|
129
|
+
const workerName = faker.word.sample();
|
|
130
|
+
const queueName = faker.word.sample();
|
|
131
|
+
|
|
132
|
+
const manifest = {
|
|
133
|
+
connection: {
|
|
134
|
+
rabbit
|
|
135
|
+
},
|
|
136
|
+
defaults: {
|
|
137
|
+
exchangeName: faker.word.sample()
|
|
138
|
+
},
|
|
139
|
+
workers: [
|
|
140
|
+
{
|
|
141
|
+
handler: sandbox.spy(),
|
|
142
|
+
config: {
|
|
143
|
+
name: workerName,
|
|
144
|
+
key: queueName
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const army = Army(manifest);
|
|
151
|
+
|
|
152
|
+
t.truthy(army);
|
|
153
|
+
|
|
154
|
+
const childLogger = {
|
|
155
|
+
info: sandbox.spy()
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
t.context.logger.child.returns(childLogger);
|
|
159
|
+
|
|
160
|
+
const armyName = faker.word.sample();
|
|
161
|
+
|
|
162
|
+
addDefaultLoggingEventHandlers(logger, army, armyName);
|
|
163
|
+
|
|
164
|
+
Sinon.assert.calledOnceWithExactly(logger.child, { armyName });
|
|
165
|
+
|
|
166
|
+
const event = {
|
|
167
|
+
data: faker.word.sample()
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
army.minions[workerName].handle(event, metadata);
|
|
171
|
+
|
|
172
|
+
const expectedMetadata = {
|
|
173
|
+
properties: metadata.properties,
|
|
174
|
+
fields: metadata.fields
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
Sinon.assert.calledOnceWithExactly(childLogger.info, { queue: workerName, event, metadata: expectedMetadata }, 'Got event in %s', armyName);
|
|
178
|
+
});
|
package/.circleci/config.yml
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
|
|
3
|
-
defaults: &defaults
|
|
4
|
-
working_directory: ~/repo
|
|
5
|
-
docker:
|
|
6
|
-
- image: circleci/node:12.18@sha256:cc3bed34d3606a476fcb4ef0f2c03890e7a8f2114c2d81055a7695ddbf2eefc9
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
test:
|
|
10
|
-
<<: *defaults
|
|
11
|
-
steps:
|
|
12
|
-
- checkout
|
|
13
|
-
|
|
14
|
-
- restore_cache:
|
|
15
|
-
keys:
|
|
16
|
-
- dependency-cache-{{ checksum "package.json" }}
|
|
17
|
-
- dependency-cache-
|
|
18
|
-
|
|
19
|
-
- run: npm install
|
|
20
|
-
|
|
21
|
-
- save_cache:
|
|
22
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
23
|
-
paths:
|
|
24
|
-
- ./node_modules
|
|
25
|
-
|
|
26
|
-
- run:
|
|
27
|
-
name: Run tests
|
|
28
|
-
command: npm test
|
|
29
|
-
|
|
30
|
-
- persist_to_workspace:
|
|
31
|
-
root: ~/repo
|
|
32
|
-
paths: .
|
|
33
|
-
|
|
34
|
-
deploy:
|
|
35
|
-
<<: *defaults
|
|
36
|
-
steps:
|
|
37
|
-
- attach_workspace:
|
|
38
|
-
at: ~/repo
|
|
39
|
-
- run:
|
|
40
|
-
name: Authenticate with registry
|
|
41
|
-
command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/repo/.npmrc
|
|
42
|
-
- run:
|
|
43
|
-
name: Publish package
|
|
44
|
-
command: npm publish
|
|
45
|
-
|
|
46
|
-
workflows:
|
|
47
|
-
version: 2
|
|
48
|
-
test-deploy:
|
|
49
|
-
jobs:
|
|
50
|
-
- test:
|
|
51
|
-
filters:
|
|
52
|
-
tags:
|
|
53
|
-
only: /^v.*/
|
|
54
|
-
- deploy:
|
|
55
|
-
requires:
|
|
56
|
-
- test
|
|
57
|
-
filters:
|
|
58
|
-
tags:
|
|
59
|
-
only: /^v.*/
|
|
60
|
-
branches:
|
|
61
|
-
ignore: /.*/
|