I created a background job that sends a signal to client on completion:BuildingConstructionChannel.broadcast_to(user, { message: 'Building construction completed' })
.
When signal is received, connected client need to reload page.
Problem is that client dont receive signal.
In browser console I see successful connection log.However, there are no logs indicating that data has been received.
In Rails Server console I see that data has been sent.
What I did wrong and unable to receive data?
Connection
module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end private def find_verified_user if verified_user = env['warden'].user verified_user else reject_unauthorized_connection end end endend
Channel
class BuildingConstructionChannel < ApplicationCable::Channel def subscribed Rails.logger.debug("Subscribing to BuildingConstructionChannel for user #{current_user.id}") stream_for current_user end def unsubscribed Rails.logger.debug("Unsubscribed from BuildingConstructionChannel for user #{current_user.id}") endend
Consumer
import consumer from "channels/consumer"consumer.subscriptions.create("BuildingConstructionChannel", { connected() { // Called when the subscription is ready for use on the server console.log('Connected to BuildingConstructionChannel'); }, disconnected() { // Called when the subscription has been terminated by the server console.log('Disconnected from BuildingConstructionChannel'); }, received(data) { // Called when there's incoming data on the websocket for this channel console.log('Received data:', data); // window.location.reload(); }});
Controller
class BuildingsController < ApplicationController def build @building.update(is_under_construction: true, build_time: @building.time_requirement) BuildingConstructionJob.perform_async(@building.id, current_user.id) redirect_to castle_path(@building.castle), notice: 'Construction of the building has begun' end # other codeend
Background job
class BuildingConstructionJob include Sidekiq::Worker def perform(building_id, user_id) begin user = User.find(user_id) building = Building.find(building_id) until building.build_time.zero? building.build_time -= 10 building.save sleep(10) end building.update(is_under_construction: false, build_time: 0) BuildingConstructionChannel.broadcast_to(user, { message: 'Building construction completed' }) rescue StandardError => e Rails.logger.error("Error in BuildingConstructionJob: #{e.message}") end endend
Logs in /log/development.log shows, that connections success, user is valid, controller works, background job is started and data is sent:
Started GET "/cable" for ::1 at 2023-12-14 08:36:28 +0000Started GET "/cable" [WebSocket] for ::1 at 2023-12-14 08:36:28 +0000Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket) User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 6], ["LIMIT", 1]]↳ app/channels/application_cable/connection.rb:12:in find_verified_user'Registered connection (Z2lkOi8vZmNzL1VzZXIvNg)Subscribing to BuildingConstructionChannel for user 6BuildingConstructionChannel is transmitting the subscription confirmationBuildingConstructionChannel is streaming from building_construction:Z2lkOi8vZmNzL1VzZXIvNg...[ActionCable] Broadcasting to building_construction:Z2lkOi8vZmNzL1VzZXIvNg: {:message=>"Building construction completed"}
Sidekiq logs dont have errors, started and completed task:
2023-12-14T08:36:17.104Z pid=92135 tid=1lmj class=BuildingConstructionJob jid=07b8000b35785ffb1bbfac00 INFO: start2023-12-14T08:37:17.343Z pid=92135 tid=1lmj class=BuildingConstructionJob jid=07b8000b35785ffb1bbfac00 elapsed=60.239 INFO: done