feat(broadcasting): add ActionCable adapter + fix model broadcast anti-pattern
- Add Mozo::Broadcaster::ActionCable as drop-in Faye replacement - Fix model_broadcast.rb: delegate to Mozo directly instead of ApplicationController.new (memory-unsafe anti-pattern) - Add Broadcastable concern for clean model-side broadcasting - ActionCable config: async adapter, cable.yml, WebSocket endpoint - MozoChannel with per-entity authorization (user/supplier/employee) - Connection auth via auth_token (matches existing auth pattern) - Mount /cable WebSocket in routes - Add broadcasting-migration.md with Faye→ActionCable guide
This commit is contained in:
@@ -2,5 +2,6 @@ module Mozo
|
||||
module Broadcaster
|
||||
extend ActiveSupport::Autoload
|
||||
autoload :Faye
|
||||
autoload :ActionCable
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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 is kept compatible with the existing Faye convention:
|
||||
# /user/:uid → user_<uid>
|
||||
# /supplier/:sid → supplier_<sid>
|
||||
#
|
||||
# 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)
|
||||
return unless remapped
|
||||
|
||||
::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
|
||||
Reference in New Issue
Block a user