# frozen_string_literal: true module Mozo module Broadcaster # Drop-in replacement for Mozo::Broadcaster::Faye that uses # Rails' built-in ActionCable instead of an external Faye process. # # Benefits over Faye: # - Async by default (ActionCable.server.broadcast is non-blocking) # - No extra gem / process / port to manage # - Integrated with Rails authentication (cookies, sessions) # - WebSocket native (no long-polling fallback needed with modern browsers) # # Channel naming: accepts both Faye format and underscore format: # /user/123 or /user_123 → user_123 # /supplier/456 or /supplier_456 → supplier_456 # # To use: # Set Mozo.broadcaster = Mozo::Broadcaster::ActionCable.new # in config/initializers/mozo_settings.rb # class ActionCable CHANNEL_PREFIX_REMAP = { %r{^/user[/_](.+)$} => 'user_\1', %r{^/supplier[/_](.+)$} => 'supplier_\1' }.freeze def broadcast(message) channel = message[:channel] || message['channel'] data = message[:data] || message['data'] remapped = remap_channel(channel) unless remapped Rails.logger.warn("[ACTION_CABLE] broadcast skipped: unknown channel #{channel}") return end Rails.logger.debug("[ACTION_CABLE] broadcasting to #{remapped}: #{data.inspect}") ::ActionCable.server.broadcast(remapped, data) rescue => e Rails.logger.error("[ACTION_CABLE][ERROR] #{e.message}") end private def remap_channel(channel) CHANNEL_PREFIX_REMAP.each do |pattern, replacement| return channel.sub(pattern, replacement) if channel.match?(pattern) end Rails.logger.warn("[ACTION_CABLE] Unknown channel format: #{channel}") nil end end end end