I have a barebones setup for update broadcasts with graphql-ruby over Action Cable.
- The client receives the initial payload on subscription fine.
- The client isn’t receiving any updates and the
update
method of the subscription type isn’t being called. No errors on the backend. The trigger call seems to be silently ignored. This is what I’m trying to troubleshoot / properly understand how it’s supposed to work.
The docs I’m looking at:
- https://graphql-ruby.org/subscriptions/subscription_classes.html
- https://graphql-ruby.org/subscriptions/triggers
The subscription type:
module Types
class SubscriptionType < Types::BaseObject
field :server_info, subscription: Subscriptions::ServerInfoSubscription, null: false
end
end
module Subscriptions
class ServerInfoSubscription < Subscriptions::BaseSubscription
field :date_time, GraphQL::Types::ISO8601DateTime, null: false
def subscribe
{ date_time: DateTime.now }
end
def update
puts 'UPDATE CALLED' # Nope, it's not being called
super
end
end
end
The way I’m attempting to trigger an update:
MySchema.subscriptions.trigger(:server_info, {}, { date_time: DateTime.now })
The schema is defined as:
class MySchema < GraphQL::Schema
use GraphQL::Execution::Interpreter
use GraphQL::Subscriptions::ActionCableSubscriptions
subscription(Types::SubscriptionType)
end
I am using the redis adapter for the development environment in config/cable.yml:
development:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: test-app_development
What am I missing? Any troubleshooting tips?
Update:
Some diagnostics:
Rails logs for the initial (and successful) subscription call:
GraphqlChannel#execute({"query"=>"subscription ServerInfoSubscription {n serverInfo {n dateTimen __typenamen }n}n", "variables"=>{}, "operationName"=>"ServerInfoSubscription"})
GraphqlChannel transmitting {"data"=>{"serverInfo"=>{"dateTime"=>"2020-10-08T10:47:08-04:00", "__typename"=>"ServerInfoSubscriptionPayload"}}}
GraphqlChannel is streaming from graphql-subscription:9087735b-9b99-4d66-8b77-ff3622c8efe7
GraphqlChannel is streaming from graphql-event::dateTime:
Started POST "/graphql" for 192.168.64.210 at 2020-10-08 10:47:08 -0400
Checking active Redis PubSub channels:
$ redis-cli -h 192.168.64.210 -p 6379 pubsub channels
1) "test-app_development:graphql-subscription:9087735b-9b99-4d66-8b77-ff3622c8efe7"
2) "test-app_development:graphql-event::dateTime:"
3) "_action_cable_internal"
Outcome of running the trigger call in the Rails console:
irb(main):001:0> MySchema.subscriptions.trigger(:server_info, {}, { date_time: DateTime.now })
[ActionCable] Broadcasting to graphql-event::serverInfo:: "{"date_time":"2020-10-08T10:54:18-04:00","__sym_keys__":["date_time"]}"
The thing that stands out as obvious is that the Redis PubSub channel is called "graphql-event::dateTime:" while the trigger call broadcasts over the nonexistent "graphql-event::serverInfo:" channel. I do not understand why the actual Redis channel is called "graphql-event::dateTime" while the subscription query is on the top-level "ServerInfo" type.
2
Answers
I finally got it working, but couldn't pinpoint why this wasn't working:
Note that I had been passing an empty hash (
{}
) as the second argument.The way I got it working is to add an
argument
to my query and use a matching argument (matching to the original subscription query). Something like this:The Redis channel I can now see is:
It’s because the method which you are trying to overwrite is expecting parameters, if you look at the
GraphQL::Schema::Subscription
You can safely remove the
:argument
and define your update method with parameter which will solve the issue.