Skip to content

Commit

Permalink
Execution context getters using closures (#2461)
Browse files Browse the repository at this point in the history
* no async hooks lol

* changeset

* Update docs #2461

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
  • Loading branch information
enisdenjo and kamilkisiela committed Nov 2, 2023
1 parent c6bc090 commit 472733b
Show file tree
Hide file tree
Showing 10 changed files with 9 additions and 174 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-otters-march.md
@@ -0,0 +1,5 @@
---
'graphql-modules': patch
---

Execution context getters using closures
22 changes: 4 additions & 18 deletions packages/graphql-modules/src/application/context.ts
Expand Up @@ -5,7 +5,6 @@ import { once, merge } from '../shared/utils';
import type { InternalAppContext, ModulesMap } from './application';
import { attachGlobalProvidersMap } from './di';
import { CONTEXT } from './tokens';
import { executionContext, ExecutionContextPicker } from './execution-context';

export type ExecutionContextBuilder<
TContext extends {
Expand Down Expand Up @@ -67,13 +66,13 @@ export function createContextBuilder({
},
});

appInjector.setExecutionContextGetter(
executionContext.getApplicationContext as any
);
appInjector.setExecutionContextGetter(function executionContextGetter() {
return appContext;
} as any);

function createModuleExecutionContextGetter(moduleId: string) {
return function moduleExecutionContextGetter() {
return executionContext.getModuleContext(moduleId);
return getModuleContext(moduleId, context);
};
}

Expand All @@ -83,18 +82,6 @@ export function createContextBuilder({
);
});

const executionContextPicker: ExecutionContextPicker = {
getApplicationContext() {
return appContext;
},
getModuleContext(moduleId) {
return getModuleContext(moduleId, context);
},
};
const destroyExecutionContext = executionContext.create(
executionContextPicker
);

// As the name of the Injector says, it's an Operation scoped Injector
// Application level
// Operation scoped - means it's created and destroyed on every GraphQL Operation
Expand Down Expand Up @@ -186,7 +173,6 @@ export function createContextBuilder({
injector._getObjByKeyId(keyId).onDestroy();
}
});
destroyExecutionContext();
contextCache = {};
}),
ɵinjector: operationAppInjector,
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

19 changes: 0 additions & 19 deletions packages/graphql-modules/src/application/execution-context.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/graphql-modules/src/di/decorators.ts
Expand Up @@ -6,7 +6,6 @@ import {
ensureInjectableMetadata,
} from './metadata';
import { Injector } from './injector';
import { enableExecutionContext } from '../application/execution-context';

function ensureReflect() {
if (!(Reflect && Reflect.getOwnMetadata)) {
Expand All @@ -17,7 +16,6 @@ function ensureReflect() {
export function Injectable(options?: ProviderOptions): ClassDecorator {
return (target) => {
ensureReflect();
enableExecutionContext();

const params: Type<any>[] = (
Reflect.getMetadata('design:paramtypes', target) || []
Expand Down
12 changes: 0 additions & 12 deletions packages/graphql-modules/tests/execution-context.spec.ts
Expand Up @@ -12,20 +12,8 @@ import {
Inject,
} from '../src';

import {
getExecutionContextDependencyStore,
getExecutionContextStore,
} from '../src/application/execution-context-hooks';

const posts = ['Foo', 'Bar'];

afterEach(() => {
// There should be no execution context left after each test
expect(
getExecutionContextDependencyStore().size + getExecutionContextStore().size
).toBe(0);
});

test('ExecutionContext on module level provider', async () => {
const spies = {
posts: jest.fn(),
Expand Down
9 changes: 0 additions & 9 deletions website/src/pages/docs/advanced/execution-context.mdx
Expand Up @@ -38,12 +38,3 @@ The next lines show the usage of `@ExecutionContext` decorator. It's a property
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.

It also means you gain a lot in terms of performance because the `Data` class is instantiated only once and used in many operations.

<Callout>
`@ExecutionContext` impacts the performance, depending on your Node version
(execution context uses `async_hooks` module).

GraphQL Modules is smart enough to enable `async_hooks` only when
`@ExecutionContext` is used.

</Callout>
2 changes: 0 additions & 2 deletions website/src/pages/docs/recipes/migration.mdx
Expand Up @@ -317,8 +317,6 @@ export class MyProvider {

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.

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.

## Context

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`.
Expand Down

0 comments on commit 472733b

Please sign in to comment.