skip to Main Content

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:

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


  1. Chosen as BEST ANSWER

    I finally got it working, but couldn't pinpoint why this wasn't working:

    MySchema.subscriptions.trigger(:server_info, {}, { date_time: DateTime.now })
    

    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:

    module Subscriptions
      class EventReceivedSubscription < Subscriptions::BaseSubscription
        argument :event_name, String, required: true
    
        field :event_name, String, null: false
        field :payload, String, null: true
      end
    end
    
    MySchema.subscriptions.trigger(
      :event_received,
      { event_name: 'greeting' },
      { payload: 'Hello' }
    )
    

    The Redis channel I can now see is:

    $ redis-cli -h 192.168.64.210 -p 6379 pubsub channels
    1) "test-app_development:graphql-event::eventReceived:eventName:greeting"
    

  2. It’s because the method which you are trying to overwrite is expecting parameters, if you look at the GraphQL::Schema::Subscription

    def subscribe( attrs = {})
    ...
    end
    
    def update( attrs = {} )
    ...
    end
    

    You can safely remove the :argument and define your update method with parameter which will solve the issue.

    def update( _attrs = {} )
      # your logic here
    end
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search