strawberry-graphql/strawberry

Extensions execution context can easily overlap between parallel executions.

Opened this issue · 2 comments

Describe the Bug

RN extensions can be singleton instances meaning that the execution context can change during
lifepsan hook execution (if you have parallel operaitons running) :

async def test_execution_context_distinct_on_parallel_execution():

    class EnsureDistinctExtension(SchemaExtension):
        def __init__(self) -> None:
            ...
        async def on_operation(self) -> AsyncIterator[None]:
            query = self.execution_context.query
            yield
            assert self.execution_context.query == query

    @strawberry.type
    class Query:
        @strawberry.field
        async def foo(self) -> str:
            await asyncio.sleep(0.01)
            return "pong"

        @strawberry.field
        async def bar(self) -> str:
            await asyncio.sleep(0.02)
            return "pong"

    schema = strawberry.Schema(query=Query, extensions=[EnsureDistinctExtension()])
    query_foo = "query foo { foo }"
    query_bar = "query bar { bar }"
    for _ in range(10):
        results = await asyncio.gather(*[schema.execute(query_foo), schema.execute(query_bar)])

    for res in results:
        assert not res.errors

I want to remove the execution_context from the extension instance and provide it as an argument to each hook
what do you guys think?
original discussion on discord

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

We've seen this in the wild, with an async schema extensions seem to run multiple times since a recent update.

@nburns I think #3640 should fix this :)