Skip to content

Commit daa960b

Browse files
authored
[Feature] Update API. (#23)
1 parent df69e89 commit daa960b

File tree

12 files changed

+103
-7
lines changed

12 files changed

+103
-7
lines changed

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
node-version: [8.x, 10.x, 12.x, 14.x]
19+
node-version: [8.x, 10.x, 12.x, 14.x, 16.x]
2020

2121
steps:
2222
- uses: actions/checkout@v2

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 3.0.2 (February 12, 2021)
4+
5+
- Add `update` API for ease usage in case context is a plain `object`.
6+
37
## 3.0.1 (February 12, 2021)
48

59
- Better `types.d`.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-execution-context",
3-
"version": "3.0.1",
3+
"version": "3.0.2",
44
"description": "Provides execution context wrapper for node JS, can be used to create execution wrapper for handling requests and more",
55
"author": "Oded Goldglas <odedglas@gmail.com>",
66
"license": "ISC",

src/ExecutionContext/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
exports.ExecutionContextErrors = {
66
CONTEXT_DOES_NOT_EXIST: 'Execution context does not exists, please ensure to call create/run before.',
7+
UPDATE_BLOCKED: 'Calling "update" API is allowed only when provided context is a plain `object`.',
78
MONITOR_MISS_CONFIGURATION: 'Monitoring option is off by default, please call `configure` with the proper options.'
89
};
910

src/ExecutionContext/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ class ExecutionContext {
3131
this.manager.set(context);
3232
}
3333

34+
/**
35+
* Updates the current asynchronous execution context with a given value.
36+
* @param {*} context - The new context to expose current asynchronous execution.
37+
* @returns void
38+
*/
39+
update(context) {
40+
this.manager.update(context);
41+
}
42+
3443
/**
3544
* Gets the current asynchronous execution context.
3645
* @return {*}

src/ExecutionContext/spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,35 @@ describe('Context', () => {
5252
});
5353
});
5454

55+
describe('Update', () => {
56+
it('Throws an error when context is not created', () => {
57+
expect(() => Context.get())
58+
.toThrow(ExecutionContextErrors.CONTEXT_DOES_NOT_EXIST);
59+
});
60+
61+
it('Throws an error when context is a pain `object`', () => {
62+
Context.create({ my: 'thing' });
63+
64+
expect(() => Context.update('Hey'))
65+
.toThrow(ExecutionContextErrors.UPDATE_BLOCKED);
66+
});
67+
68+
describe('When context is created', () => {
69+
it('Update context', () => {
70+
Context.create({ val: 'value', other: 'o' });
71+
const context = Context.get();
72+
73+
expect(context.val).toEqual('value');
74+
75+
Context.update({ val: false });
76+
expect(Context.get()).toMatchObject({
77+
val: false,
78+
other: 'o'
79+
});
80+
});
81+
});
82+
});
83+
5584
describe('Run', () => {
5685
let spies;
5786
let execute;

src/ExecutionContext/types.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { ExecutionMapUsage } from '../lib/types';
2-
31
interface ExecutionContextNode {
42
asyncId: number;
53
monitor: boolean;

src/lib/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ module.exports = {
5858
*/
5959
supportAsyncLocalStorage: (version = process.version) => semver.gte(version, '12.17.0'),
6060

61+
/**
62+
* Returns true if a given thing is an object
63+
* @param value - The thing to check.
64+
*/
65+
isObject: (value) => !!value &&
66+
!Array.isArray(value) &&
67+
typeof value === 'object',
68+
6169
/**
6270
* Returns a monitoring report over the "executionContext" memory usage.
6371
* @param {ExecutionContextMap} executionContextMap The execution map to monitor.

src/lib/spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ describe('Lib', () => {
3535
});
3636
});
3737

38+
describe('isObject', () => {
39+
it.each([
40+
[false, false],
41+
[1, false],
42+
['', false],
43+
[undefined, false],
44+
[[], false],
45+
[() => {}, false],
46+
[class Test {}, false],
47+
[{}, true],
48+
])('Returns true when given value is object (%p)', (value, expected) => {
49+
expect(lib.isObject(value)).toEqual(expected);
50+
});
51+
});
52+
3853
describe('supportAsyncLocalStorage', () => {
3954
describe('When node version is lower than 12.17.0', () => {
4055
it.each([

src/managers/asyncHooks/index.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const asyncHooks = require('async_hooks');
2-
const { monitorMap, handleError, ExecutionContextResource } = require('../../lib');
2+
const { monitorMap, handleError, isObject, ExecutionContextResource } = require('../../lib');
33
const { create: createHooks, onChildProcessDestroy } = require('./hooks');
44
const { ExecutionContextErrors } = require('../../ExecutionContext/constants');
55
const { DEFAULT_CONFIG } = require('./constants');
@@ -103,6 +103,18 @@ class AsyncHooksContext {
103103
rootContext.context = context;
104104
}
105105

106+
update(context) {
107+
const asyncId = asyncHooks.executionAsyncId();
108+
109+
if (!executionContextMap.has(asyncId)) return handleError(ExecutionContextErrors.CONTEXT_DOES_NOT_EXIST);
110+
if (!isObject(context)) return handleError(ExecutionContextErrors.UPDATE_BLOCKED);
111+
112+
// Update target is always the root context, ref updates will need to be channeled
113+
const rootContext = this._getRootContext(asyncId);
114+
115+
Object.assign(rootContext.context, context);
116+
}
117+
106118
configure(config) {
107119
this.config = config;
108120
}

0 commit comments

Comments
 (0)