Skip to content

Commit 472733b

Browse files
Execution context getters using closures (#2461)
* no async hooks lol * changeset * Update docs #2461 --------- Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
1 parent c6bc090 commit 472733b

File tree

10 files changed

+9
-174
lines changed

10 files changed

+9
-174
lines changed

Diff for: .changeset/stupid-otters-march.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'graphql-modules': patch
3+
---
4+
5+
Execution context getters using closures

Diff for: packages/graphql-modules/src/application/context.ts

+4-18
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { once, merge } from '../shared/utils';
55
import type { InternalAppContext, ModulesMap } from './application';
66
import { attachGlobalProvidersMap } from './di';
77
import { CONTEXT } from './tokens';
8-
import { executionContext, ExecutionContextPicker } from './execution-context';
98

109
export type ExecutionContextBuilder<
1110
TContext extends {
@@ -67,13 +66,13 @@ export function createContextBuilder({
6766
},
6867
});
6968

70-
appInjector.setExecutionContextGetter(
71-
executionContext.getApplicationContext as any
72-
);
69+
appInjector.setExecutionContextGetter(function executionContextGetter() {
70+
return appContext;
71+
} as any);
7372

7473
function createModuleExecutionContextGetter(moduleId: string) {
7574
return function moduleExecutionContextGetter() {
76-
return executionContext.getModuleContext(moduleId);
75+
return getModuleContext(moduleId, context);
7776
};
7877
}
7978

@@ -83,18 +82,6 @@ export function createContextBuilder({
8382
);
8483
});
8584

86-
const executionContextPicker: ExecutionContextPicker = {
87-
getApplicationContext() {
88-
return appContext;
89-
},
90-
getModuleContext(moduleId) {
91-
return getModuleContext(moduleId, context);
92-
},
93-
};
94-
const destroyExecutionContext = executionContext.create(
95-
executionContextPicker
96-
);
97-
9885
// As the name of the Injector says, it's an Operation scoped Injector
9986
// Application level
10087
// Operation scoped - means it's created and destroyed on every GraphQL Operation
@@ -186,7 +173,6 @@ export function createContextBuilder({
186173
injector._getObjByKeyId(keyId).onDestroy();
187174
}
188175
});
189-
destroyExecutionContext();
190176
contextCache = {};
191177
}),
192178
ɵinjector: operationAppInjector,

Diff for: packages/graphql-modules/src/application/execution-context-async-local-storage.ts

-29
This file was deleted.

Diff for: packages/graphql-modules/src/application/execution-context-hooks.ts

-79
This file was deleted.

Diff for: packages/graphql-modules/src/application/execution-context.interface.ts

-4
This file was deleted.

Diff for: packages/graphql-modules/src/application/execution-context.ts

-19
This file was deleted.

Diff for: packages/graphql-modules/src/di/decorators.ts

-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
ensureInjectableMetadata,
77
} from './metadata';
88
import { Injector } from './injector';
9-
import { enableExecutionContext } from '../application/execution-context';
109

1110
function ensureReflect() {
1211
if (!(Reflect && Reflect.getOwnMetadata)) {
@@ -17,7 +16,6 @@ function ensureReflect() {
1716
export function Injectable(options?: ProviderOptions): ClassDecorator {
1817
return (target) => {
1918
ensureReflect();
20-
enableExecutionContext();
2119

2220
const params: Type<any>[] = (
2321
Reflect.getMetadata('design:paramtypes', target) || []

Diff for: packages/graphql-modules/tests/execution-context.spec.ts

-12
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,8 @@ import {
1212
Inject,
1313
} from '../src';
1414

15-
import {
16-
getExecutionContextDependencyStore,
17-
getExecutionContextStore,
18-
} from '../src/application/execution-context-hooks';
19-
2015
const posts = ['Foo', 'Bar'];
2116

22-
afterEach(() => {
23-
// There should be no execution context left after each test
24-
expect(
25-
getExecutionContextDependencyStore().size + getExecutionContextStore().size
26-
).toBe(0);
27-
});
28-
2917
test('ExecutionContext on module level provider', async () => {
3018
const spies = {
3119
posts: jest.fn(),

Diff for: website/src/pages/docs/advanced/execution-context.mdx

-9
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,3 @@ The next lines show the usage of `@ExecutionContext` decorator. It's a property
3838
This way the Singleton `Data` service runs within the execution context of a GraphQL Operation and can access Operation scoped Injector and the GraphQL Context object.
3939

4040
It also means you gain a lot in terms of performance because the `Data` class is instantiated only once and used in many operations.
41-
42-
<Callout>
43-
`@ExecutionContext` impacts the performance, depending on your Node version
44-
(execution context uses `async_hooks` module).
45-
46-
GraphQL Modules is smart enough to enable `async_hooks` only when
47-
`@ExecutionContext` is used.
48-
49-
</Callout>

Diff for: website/src/pages/docs/recipes/migration.mdx

-2
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,6 @@ export class MyProvider {
317317

318318
In v0, we had a concept of Session to manage the execution of each operation. In v1, we dropped it, in favor of a simpler solution.
319319

320-
Internally, we are using Node's `async_hooks` to manage a context of an execution, which allow us to share Injectables between Singleton and Operation scope.
321-
322320
## Context
323321

324322
In v0, you could create a `context` per each module. In v1, `context` is external for GraphQL-Modules and it's not directly in use. You can do whatever you want with that, and just access it in GraphQL-Modules if you need, but we no longer require you to do specific things with your `context`.

0 commit comments

Comments
 (0)