DjangoChannelsGraphqlWs
DjangoChannelsGraphqlWs copied to clipboard
It is not possible to access the `operation_id` from the `subscribe` or `unsubscribed` methods (or it very seriously lacks documentation).
It is not possible to access the operation_id
from the subscribe
or unsubscribed
methods (or it very seriously lacks documentation).
If you create a service which you send you some logs, and test it like this with the wscat shell :
wscat --slash -s graphql-ws -c ws://localhost:8000/graphql -H "Authorization:Bearer some_token"
{"type": "connection_init", "payload": {}}
You then subscribe to a subscription like this like this (example):
{"id": "1", "type": "start", "payload": {"query": "subscription { logs(build_id: 97770) { logs { timestamp message } } }", "variables": null}}
And to another like this:
{"id": "2", "type": "start", "payload": {"query": "subscription { logs(build_id: 97769) { logs { timestamp message } } }", "variables": null}}
These subscriptions launch threads which will be referenced via the id.
Each thread send there responses in a specific group created specifically in the subscribe
method.
To unsubscribe to the first subscription you would send:
{"id": "1", "type": "stop"}
and.or tho the second one via
{"id": "2", "type": "stop"}
however, I found strictly no way to access this "id": "1"
in the info
parameter of the subscribe
and unsubscribed
methods. And therefore to terminate the desired thread and subscription instead of all.
Currently I subclassed channels_graphql_ws.GraphqlWsConsumer
with these methods:
async def _on_gql_start(self, operation_id, payload):
self.scope['on_gql_start_operation_id'] = operation_id
self.scope['on_gql_start_payload'] = payload
return await super()._on_gql_start(operation_id, payload)
async def _on_gql_stop(self, operation_id):
self.scope['on_gql_stop_operation_id'] = operation_id
return await super()._on_gql_stop(operation_id)
And I can find the operation_id
in my channels_graphql_ws.Subscription.subscribe
method via info.context.on_gql_start_operation_id
and in the channels_graphql_ws.Subscription.unsubscribed
method via info.context.on_gql_stop_operation_id
.
The payload
is also interesting because I hash it, and if someone else subscribes to the same thing I reuse the existing thread (and join the existing subscription group).
is there a a proper way to access this operation_id
? because it's in my opinion compulsory to be able to access it. Otherwise you need to unsubscribe all threads and not only one.
It is to note that the angular apollo graphql client launches multiple subscriptions in a unique websocket (channels_graphql_ws.GraphqlWsConsumer.on_connect
). The Apollo client forges this operaion_id
itself. And when you create a web app with angular which subscribes to multiple subscriptions in the same page, without the hack I did it was not possible to select multiple subscriptions on the same page and to start stop only the desired one on demand.
Let me know if anything was unclear.
Regards,
The major issue with the workaround described above is that it only works with channels_graphql_ws.GraphqlWsConsumer.strict_ordering = True
Without this, the information is totally mixed up
The version 1.0.0rc1 is available in PyPI, it has info.context.graphql_operation_id
field to address this issue. Closing this, feel free to reopen or file a new one in case of problems.