-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #894, add perEventContextResolver for subscribe #2485
Fix #894, add perEventContextResolver for subscribe #2485
Conversation
@tgriesser I like this solution and I think it is generic enough to be added into lib. Also please update JSDoc comments for relevant functions. |
Nice! The idea with the name was to take Maybe one of:
Sounds good, will do once we land on the name. |
@tgriesser The fact that we call Spec describes "stream of events" so I think it should be something like |
Ah right, that makes sense.
Sounds great. |
@IvanGoncharov docs should be updated, let me know if you see anything that needs correction. |
…ription * master: TS: remove TS-specific TSource argument for resolveFieldValueOr… (graphql#2491) TS: remove TS-specific TData from ExecutionResult (graphql#2490) TS(definition): remove TS-specific TArgs (graphql#2488)
@tgriesser Thanks for the update, now it looks perfect 👍 |
…ription * master: v15.0.0 Update deps (graphql#2502) Update Flow (graphql#2500) Update prettier (graphql#2499) Move custom ESLint rules into internal package (graphql#2498)
Just ran into the issue at #894 Seems that the milestone was missed. Anything holding this back? |
@IvanGoncharov @tgriesser I have a similar use case while implementing graphql subscriptions with dataloaders. Any particular reason why this isn't merged yet? |
…ription * master: (211 commits) Update deps (graphql#2844) resources: use named groups in RegExp (graphql#2840) TS: exclude integration tests from root tsconfig.json (graphql#2838) Flow: remove support for measuring Flow coverage (graphql#2837) CI: test on node 15 (graphql#2836) Update deps (graphql#2835) build: add support for experimental releases (graphql#2831) 15.4.0 Update deps (graphql#2827) Update deps (graphql#2825) integrationTests: add Flow test (graphql#2819) fix: ensure variance of types matches how values are used (graphql#2786) Cleanup '__fixtures__' leftovers (graphql#2818) Convert fixtures to be JS files (graphql#2816) Update deps (graphql#2815) benchmark: extract benchmarks into separate folder and run them on NPM package Update deps (graphql#2810) Update outdated documentation (graphql#2806) Make print() break arguments over multiple lines (graphql#2797) Added check for specific symbols in polyfills/symbols (graphql#2804) ...
Is there a way to "release" the context? Say, for example, that the context were to contain an authenticated client connected to a datastore. E.g. for normal GraphQL execution you can do: function getContext(...) {
const client = ...;
return {
contextValue: { client },
release: () => client.release(),
};
}
const { contextValue, release } = getContext(...);
try {
return await graphql({schema, source, contextValue})
} finally {
release();
} |
@benjie that's a really good point... the current change wouldn't support that case well. In thinking about it more, and looking through the const iterator = await subscribe({
schema,
document,
variableValues,
contextValue: new DataContext(),
operationName: obj.request.name,
perEventExecute: async (execArgs) => {
const { contextValue, release } = getContext(...);
try {
return await execute({...execArgs, contextValue})
} finally {
release();
}
}
}) @IvanGoncharov thoughts on that? Something like: export type SubscriptionArgs = {|
schema: GraphQLSchema,
document: DocumentNode,
rootValue?: mixed,
contextValue?: mixed,
variableValues?: ?{ +[variable: string]: mixed, ... },
operationName?: ?string,
fieldResolver?: ?GraphQLFieldResolver<any, any>,
subscribeFieldResolver?: ?GraphQLFieldResolver<any, any>,
+ perEventExecute?: (args: ExecutionArgs) => PromiseOrValue<ExecutionResult>
|}; function subscribeImpl(
args: SubscriptionArgs,
): Promise<AsyncGenerator<ExecutionResult, void, void> | ExecutionResult> {
const {
schema,
document,
rootValue,
contextValue,
variableValues,
operationName,
fieldResolver,
subscribeFieldResolver,
+ perEventExecute = execute
} = args; const mapSourceToResponse = (payload) =>
- execute({
+ perEventExecute({
schema, |
@IvanGoncharov Are there any plans to merge this ? If not, then what is the best way to generate a context for each execution currently? |
PR which solves this in another way: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
send it
to safely export buildExecutionContext() as validateExecutionArgs() motivation: this will allow us to: 1. export `executeOperation()` and `executeSubscription()` for those who would like to use directly. 2. add a `perEventExecutor` option to `ExecutionArgs` that allows one to pass a custom context for execution of each execution event, with the opportunity to clean up the context on return, a la #2485 and #3071, addressing #894, which would not require re-coercion of variables. The signature of the `perEventExecutor` option would be: ```ts type SubscriptionEventExecutor = ( validatedExecutionArgs: ValidatedExecutionArgs): PromiseOrValue<ExecutionResult> ``` rather than: ```ts type SubscriptionEventExecutor = ( executionArgs: ExecutionArgs): PromiseOrValue<ExecutionResult> ``` This might be a first step to integrating `subscribe()` completely into `execute()` (see: #3644) but is also a reasonable stopping place.
Fixes #894
Adds
contextValueExecution
perEventContextResolver
, a new option forsubscribe
which allows you to derive a new context value for each independent execution of a subscription.It takes the original
context
value as an argument, so you can derive the new context from the original.