How to get the `operationName` inside `subscriptionExchange`?
See original GitHub issueI’m running a GraphQL API with graphql-ruby
and needed to get subscriptions work with Action Cable
, so I’ve created this SubscriptionForwarder
, based on the official ActionCableLink
implementation:
import * as ActionCable from '@rails/actioncable'
import { SubscriptionOperation } from '@urql/core/dist/types/exchanges/subscription'
import Observable from 'zen-observable-ts'
class ActionCableExchange {
cable: ActionCable.Cable
channelName: string
actionName: string
connectionParams: object
constructor(options: { cable: ActionCable.Cable; channelName?: string; actionName?: string; connectionParams?: object }) {
this.cable = options.cable
this.channelName = options.channelName || 'GraphqlChannel'
this.actionName = options.actionName || 'execute'
this.connectionParams = options.connectionParams || {}
}
request(operation: SubscriptionOperation) {
return new Observable(observer => {
var channelId = Math.round(Date.now() + Math.random() * 100000).toString(16)
var actionName = this.actionName
var subscription = this.cable.subscriptions.create(
Object.assign(
{},
{
channel: this.channelName,
channelId: channelId,
},
this.connectionParams,
),
{
connected: function() {
this.perform(actionName, {
query: operation.query ? operation.query : null,
variables: operation.variables,
// TODO: add this to support persisted queries. But we need to get the operationName at first
// operationId: (operation as { operationId?: string }).operationId,
// operationName: operation.operationName,
})
},
received: function(payload) {
if (payload.result.data || payload.result.errors) {
observer.next(payload.result)
}
if (!payload.more) {
observer.complete()
}
},
},
)
// Make the ActionCable subscription behave like an Apollo subscription
return Object.assign(subscription, { closed: false })
})
}
}
const cable = ActionCable.createConsumer('ws://localhost:3000/cable')
const actionCableClient = new ActionCableExchange({ cable })
const defaultExchanges = [
dedupExchange,
cacheExchange,
errorExchange,
fetchExchange,
subscriptionExchange({
forwardSubscription: operation => {
return actionCableClient.request(operation)
},
}),
]
I’d like to add this to the graphql-ruby
repository and then add some documentation about the usage with ActionCable to urql
. But I need to figure out how to get the operationName
of the query in my actionCableClient
at first, since graphql-ruby
needs this to support persisted operations. I took a look at the source of the subscriptionExchange
, but I think that it’s not possible to get the operationName
at the moment, isn’t it?
Also I was thinking about the possibility to use the operationName
to invalidate the cache (little bit off topic, but I don’t want to open a second issue). Sometimes it would be helpful to invalidate certain queries, since I don’t want to invalidate all of my viewer
queries if I just could invalidate GetViewerIssues
for example. Any thoughts about this? 😊
Last but not least: thank you so much for urql
. I’ve switched from Apollo and everything feels way more “under control” now 😄
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (2 by maintainers)
More or less, I’ve omitted the
operationId
for now and don’t use persisted queries, but the subscription works:Hi @gopeter, were you able to figure this out? It’s possible to share it please? I have no idea how to make subscriptions work with rubys action cable. Thanks