strawberry-graphql / strawberry

A GraphQL library for Python that leverages type annotations 🍓
https://strawberry.rocks
MIT License
3.94k stars 521 forks source link

strawberry-fastapi integration: context['response'].background = BackgroundTask(calback) not invoked #2103

Closed BakinSergey closed 2 years ago

BakinSergey commented 2 years ago
#### gq types ####

@strawberry.type(description="mutations")
class Mutation:
    task_create = strawberry.mutation(
        resolver=task.create, description="New Task"
    )

#### deco  4 resolver  fns ####

async def user_action_audit(response):
     ...some stuff ...

def with_audit(gql_resolver: Callable[[Any], Awaitable[Any]]):
    @wraps(gql_resolver)
    async def wrapper(*args, **kwargs):
        response = await gql_resolver(*args, **kwargs)

        # https://strawberry.rocks/docs/integrations/asgi#setting-response-headers
        kwargs["info"].context["response"].set_cookie(key="kuka", value='puka')    - this WORK

        # https://strawberry.rocks/docs/integrations/asgi#setting-background-tasks  - NOT WORK(bg task NOT invoked)
        kwargs["info"].context["response"].background = BackgroundTask(user_action_audit, response)  

        # was discovered myself   - WORK(bg task invoked)
        kwargs['info'].context['background_tasks'].tasks.append(BackgroundTask(user_action_audit, response))  

        return response
    return wrapper

#### resolver fn ####

@with_audit
async def create(
    info: Info,
    user_id: Annotated[
        UUID, strawberry.argument(description="user id")
    ],
) -> Task:
    data = crud.task.create_for_user(info.context["db"], user_id=user_id)
    return cast(Task, data)

the problem is that no background task is called in the described here way(see comments in code)

Ubuntu 20.04 python = "~3.8" strawberry-graphql = {extras = ["fastapi"], version = "^0.108.0"} fastapi = "^0.75.2"

tsmith023 commented 2 years ago

I think this is a case of out-of-date documentation as your workaround appears to be the intended functionality.

Looking at this and this, it seems impossible to achieve the functionality as described in the documentation since info.context["response"] has no attribute background. Instead, info.context has background_tasks as a field (if a dictionary) or an attribute (if inheriting from BaseContext).

I will amend the documentation to better describe this situation and so hopefully resolve this issue :D

BakinSergey commented 2 years ago

it seems like it has, but not work(not handle), but in other case(for ex FileResponse) it works image image

BakinSergey commented 2 years ago

i check - this(2) will work, but (1) in case of context['response'].background - will not image image

tsmith023 commented 2 years ago

Ahh okay, interesting. I see what you're driving at! You may be mixing up the different Strawberry integrations.

You initially linked here, which actually applies to the Strawberry-ASGI integration and not the Strawberry-FastAPI integration. If you go here then you will see the correct FastAPI functionality that allows for adding background tasks to the context object, which is the functionality you desire.

Since these are different integrations, it's important that you use the correct functionality for the integration that you choose. You chose FastAPI, so you should follow these docs.

BakinSergey commented 2 years ago

u right! i was only google by "Setting background tasks" ))) Thx for your time!

tsmith023 commented 2 years ago

Great! :D If you feel that this is resolved could you please close the issue, thanks!