11const asyncHooks = require ( 'async_hooks' ) ;
2+ const ExecutionContextResource = require ( './lib/ExecutionContextResource' )
23const { isProduction } = require ( './lib' ) ;
34const { create : createHooks } = require ( './hooks' ) ;
45const { ExecutionContextErrors } = require ( './constants' ) ;
56
6- /**
7- * The global service context execution map
8- * @type ExecutionContextMap
9- */
10- const executionContextMap = new Map ( ) ;
11-
12- // Sets node async hooks setup
13- asyncHooks . createHook (
14- createHooks ( executionContextMap )
15- ) . enable ( ) ;
16-
177/**
188 * Handles execution context error, throws when none production
199 * @param code
@@ -28,65 +18,100 @@ const handleError = (code) => {
2818
2919/**
3020 * The Execution Context API
21+ * @return {ExecutionContextAPI }
3122 */
32- const Context = {
23+ const createExecutionContext = ( ) => {
3324
3425 /**
35- * Creates an execution context for the current asyncId process.
36- * This will expose Context get / update at any point after.
37- * @param {Object } initialContext - The initial context to be used
38- * @returns void
26+ * The global service context execution map
27+ * @type ExecutionContextMap
3928 */
40- create : ( initialContext = { } ) => {
41- const asyncId = asyncHooks . executionAsyncId ( ) ;
42-
43- // Creation is allowed once per execution context
44- if ( executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_ALREADY_DECLARED ) ;
45-
46- executionContextMap . set ( asyncId , {
47- context : { ...initialContext , executionId : asyncId } ,
48- children : [ ]
49- } ) ;
50- } ,
51-
52- /**
53- * Updates the current async process context
54- * @param {Object } update - The update to apply on the current process context
55- * @returns void
56- */
57- update : ( update = { } ) => {
58- const asyncId = asyncHooks . executionAsyncId ( ) ;
59-
60- if ( ! executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_DOES_NOT_EXISTS ) ;
61-
62- const contextData = executionContextMap . get ( asyncId ) ;
63-
64- // Update target is always the root context, ref updates will need to be channeled
65- const targetContextData = contextData . ref
66- ? executionContextMap . get ( contextData . ref )
67- : contextData ;
68-
69- targetContextData . context = { ...targetContextData . context , ...update } ;
70- } ,
71-
72- /**
73- * Gets the current async process execution context
74- * @returns {Object }
75- */
76- get : ( ) => {
77- const asyncId = asyncHooks . executionAsyncId ( ) ;
78- if ( ! executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_DOES_NOT_EXISTS ) ;
79-
80- const { context = { } , ref } = executionContextMap . get ( asyncId ) ;
81- if ( ref ) {
82-
83- // Ref will be used to point out on the root context
84- return executionContextMap . get ( ref ) . context ;
29+ const executionContextMap = new Map ( ) ;
30+
31+ // Sets node async hooks setup
32+ asyncHooks . createHook (
33+ createHooks ( executionContextMap )
34+ ) . enable ( ) ;
35+
36+ const Context = {
37+
38+ /**
39+ * Creates an execution context for the current asyncId process.
40+ * This will expose Context get / update at any point after.
41+ * @param {Object } initialContext - The initial context to be used
42+ * @returns void
43+ */
44+ create : ( initialContext = { } ) => {
45+ console . log ( 'Ceating: ' , executionContextMap ) ;
46+ const asyncId = asyncHooks . executionAsyncId ( ) ;
47+
48+ // Creation is allowed once per execution context
49+ if ( executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_ALREADY_DECLARED ) ;
50+
51+ executionContextMap . set ( asyncId , {
52+ context : { ...initialContext , executionId : asyncId } ,
53+ children : [ ]
54+ } ) ;
55+ } ,
56+
57+ /**
58+ * Updates the current async process context.
59+ * @param {Object } update - The update to apply on the current process context.
60+ * @returns void
61+ */
62+ update : ( update = { } ) => {
63+ const asyncId = asyncHooks . executionAsyncId ( ) ;
64+
65+ if ( ! executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_DOES_NOT_EXISTS ) ;
66+
67+ const contextData = executionContextMap . get ( asyncId ) ;
68+
69+ // Update target is always the root context, ref updates will need to be channeled
70+ const targetContextData = contextData . ref
71+ ? executionContextMap . get ( contextData . ref )
72+ : contextData ;
73+
74+ targetContextData . context = { ...targetContextData . context , ...update } ;
75+ } ,
76+
77+ /**
78+ * Gets the current async process execution context.
79+ * @returns {Object }
80+ */
81+ get : ( ) => {
82+ const asyncId = asyncHooks . executionAsyncId ( ) ;
83+ if ( ! executionContextMap . has ( asyncId ) ) handleError ( ExecutionContextErrors . CONTEXT_DOES_NOT_EXISTS ) ;
84+
85+ const { context = { } , ref } = executionContextMap . get ( asyncId ) ;
86+ if ( ref ) {
87+
88+ // Ref will be used to point out on the root context
89+ return executionContextMap . get ( ref ) . context ;
90+ }
91+
92+ // Root context
93+ return context ;
94+ } ,
95+
96+ /**
97+ * Runs a given function within "AsyncResource" context, this will ensure the function executed within a uniq execution context.
98+ * @param {Function } fn - The function to run.
99+ * @param {Object } initialContext - The initial context to expose to the function execution
100+ */
101+ run : ( fn , initialContext ) => {
102+ const resource = new ExecutionContextResource ( ) ;
103+
104+ resource . runInAsyncScope ( ( ) => {
105+ Context . create ( initialContext ) ;
106+
107+ fn ( ) ;
108+ } ) ;
85109 }
110+ } ;
86111
87- // Root context
88- return context ;
89- }
90- } ;
112+ return Context ;
113+ }
114+
115+ global . ExecutionContext = global . ExecutionContext || createExecutionContext ( ) ;
91116
92- module . exports = Context ;
117+ module . exports = global . ExecutionContext ;
0 commit comments