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

Trigger doesn't fire rspec have_broadcasted_to #12

Open
sjovanelly opened this issue Aug 4, 2020 · 5 comments
Open

Trigger doesn't fire rspec have_broadcasted_to #12

sjovanelly opened this issue Aug 4, 2020 · 5 comments

Comments

@sjovanelly
Copy link

sjovanelly commented Aug 4, 2020

Describe the bug
Switched to anycable from straight up AC. Trying to convert tests and the old tests that used to pass, now fail with 0 broadcasts. The app itself works fine with updates to AnyCable.

rspec test looks like this

it 'does project socket broadcast' do
   expect do
     subject.process(message_hash)  # this calls the trigger listed below in it's process
   end.to have_broadcasted_to("graphql-event::liveProject:projectId:#{project.id}")
end

Trigger is called this way...

MainApiSchema.subscriptions.trigger('liveActivityFeed', { project_id: project.id }, { item: feed })

Versions
ruby: 2.6.3
rails (or other framework): 6.0.3.2
graphql: 1.11
graphql-anycable: 0.4.0
anycable: 1.0.1

GraphQL schema

module Types
  class ActivityFeedItemType < Types::BaseObject
    description 'Events that are associated to a project.'
    field :id, Integer, null: false
    field :category, String, null: false
    field :topic, String, null: false
    field :reference, String, null: false, method: :reference_type
    field :reference_id, Integer, null: false
    field :metadata, Types::Scalars::Json, null: false
    field :created_from_type, String, null: false
    field :created_from_id, Integer, null: false
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false, method: :reference_created_at

    def metadata
      object.metadata['data']
    end
  end
end

class MainApiSchema < GraphQL::Schema
  mutation(Types::MutationType)
  query(Types::QueryType)
  subscription(Types::SubscriptionType)

  # enable batch loading
  use BatchLoader::GraphQL
  use GraphQL::Tracing::NewRelicTracing

  use GraphQL::Subscriptions::AnyCableSubscriptions
  use GraphQL::Execution::Interpreter
  use GraphQL::Analysis::AST
  use GraphQL::Execution::Errors
end

module Subscriptions
  class ActivityFeedSubscription < Subscriptions::BaseSubscription
    description 'An activity feed item was added to the project'
    argument :project_id, ID, required: true

    field :item,
          Types::ActivityFeedItemType,
          null: true,
          description: 'New feed item added for a project'
  end
end

GraphQL query

How do you subscribe to subscriptions?

subscription onActivityFeedCreated($projectId: ID!){
  liveActivityFeed(projectId: $projectId) {
    item {
      ...feedFragment
    }
  }

fragment feedFragment on ActivityFeedItem {
  id
  topic
  category
  reference
  referenceId
  metadata
  createdAt
  createdFromType
  createdFromId
}

Steps to reproduce
Create rspec test and call. You can skip the middleman with my subject.call method and just put trigger in there.

it 'does feed socket broadcast' do
  expect do
     MainApiSchema.subscriptions.trigger('liveActivityFeed', { project_id: project.id }, { item: feedItem })
  end.to have_broadcasted_to("graphql-event::liveActivityFeed:projectId:#{project.id}")
end

Expected behavior
have_broadcasted_to should return true

Actual behavior
Error in rspec log:

ArtifactAssociatedConsumer#process_message when the artifact is present does socket broadcast
 Failure/Error:
   expect do
     subject.process(message_hash)
   end.to have_broadcasted_to("graphql-event::liveActivityFeed:projectId:#{project.id}")
    
  expected to broadcast exactly 1 messages to graphql-event::liveActivityFeed:projectId:13, but broadcast 0
  # ./spec/consumers/artifact_associated_consumer_spec.rb:77:in `block (4 levels) in <top (required)>'

Additional context
Cable yml looks like this...

development:
  adapter: <%= ENV.fetch("ACTION_CABLE_ADAPTER", "any_cable") %>
test:
  adapter: test
production:
  adapter: <%= ENV.fetch("ACTION_CABLE_ADAPTER", "any_cable") %>

and my other config settings are per AnyCable documentation

@Envek
Copy link
Member

Envek commented Aug 5, 2020

Thank you for pointing it out! @palkan, any thoughts?

I have no idea for now and it will require some time to investigate. I hope I will be able to dig into it next week maybe.

@palkan
Copy link
Member

palkan commented Aug 5, 2020

I believe this happens because we broadcast directly via AnyCable, not via ActionCable.server.pubsub:

anycable.broadcast(SUBSCRIPTION_PREFIX + subscription_id, payload.to_json)

The workaround for this could be adding a Rails specific Subscriptions class, which inherits from AnyCableSubscriptions and overrides the #deliver method to use Action Cable.

@sjovanelly
Copy link
Author

sjovanelly commented Aug 5, 2020

Thx for feedback. Since this is in our testing, we changed our tests to make sure the trigger is getting called...

expect_any_instance_of(GraphQL::Subscriptions::AnyCableSubscriptions).to receive(:trigger).with('liveActivityFeed', { project_id: project.id }, { item: be_present })

We also stubbed out the trigger call so our external CI tools didn't require redis_url

@Envek
Copy link
Member

Envek commented Aug 5, 2020

we broadcast directly via AnyCable, not via ActionCable.server.pubsub:

This is because we want it to be also usable without Rails. Not sure how to fix it there at the moment.

@palkan
Copy link
Member

palkan commented Aug 6, 2020

Not sure how to fix it there at the moment.

This

The workaround for this could be adding a Rails specific Subscriptions class, which inherits from AnyCableSubscriptions

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

3 participants