Skip to content
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

Notify subscriptions on closed socket #62

Open
jordanmarkov opened this issue Jan 19, 2021 · 5 comments
Open

Notify subscriptions on closed socket #62

jordanmarkov opened this issue Jan 19, 2021 · 5 comments

Comments

@jordanmarkov
Copy link

Hello,

I need to run some cleanup code when a clent unsubscribes or disconnects. Function similar to unsubscribed(root, info, *args, **kwds) for the case when a client disconnects would be perfect. Is this possible?

@prokher
Copy link
Member

prokher commented Feb 11, 2021

Dear @jordanmarkov,

GraphqlWsConsumer has on_connect method to handle the connection event. Probably we should add on_disconnect there to handle disconnect, e.g. to cleanup something. What do you think? Will this address your need?

@jordanmarkov
Copy link
Author

Hello @prokher ,

Not really. I would need the arguments for the subscription. I came up with some not really good solution, but it works for my use case. The problem is it uses private members:

class GraphQLWsConsumer(channels_graphql_ws.GraphqlWsConsumer):
    # ...

    async def disconnect(self, code):
        self._assert_thread()
        for sid in self._subscriptions:
            subinf = self._subscriptions[sid]
            await self._run_in_worker(subinf.unsubscribed_callback)
        await super().disconnect(code)

    # ...

class MySubscription(channels_graphql_ws.Subscription):
    class Arguments:
        arg1 = graphene.String(required=True)

    @staticmethod
    async def subscribe(_root, _info, arg1):
        # setup

    @staticmethod
    async def unsubscribed(_root, _info, arg1):
        # cleanup

Something along these lines would be perfect, possibly with another callback, but I don't really care in this case if the client has disconnected or unsubscribed.

@matclayton
Copy link

We really need this as well, we have some tidy up to do when a client disconnected on a per subscription based, right now we're trying to hack it together using the functions above, but it would be much nicer to be baked into the library.

@btribouillet
Copy link

btribouillet commented Nov 30, 2021

So it is not possible at the moment?

My use case is that I need to set the user as offline for a specific chatroom, therefore accessing the arguments of the subscription.

It would be good to have the on_disconnect in the consumer as well. But for this specific use case, it won't work unless I have access to the subscription payload.

Meanwhile, I implemented the solution from above.

@matclayton
Copy link

This is effectively what we've done, incase it helps someone

class GraphQLWsConsumer(channels_graphql_ws.GraphqlWsConsumer):
    async def disconnect(self, code: int) -> None:
        """
        This handles firing off the unsubscribe functions on subscriptions
        when a client is disconnected, e.g. when they close the browser
        See https://github.com/datadvance/DjangoChannelsGraphqlWs/issues/62
        """
        self._assert_thread()

        # Fire of a GQL Stop (and therefore unsubscribe) for any active subscriptions
        # This is necessary as the library doesnt do this by default.
        for sid in self._subscriptions.copy():
            await self._on_gql_stop(sid)

        await super().disconnect(code)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants