Class: RailsErrorDashboard::Services::ErrorBroadcaster

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_error_dashboard/services/error_broadcaster.rb

Overview

Infrastructure service: Turbo Stream broadcasting for real-time UI updates

Handles broadcasting new errors, error updates, and stats refreshes via Turbo Streams. Safely no-ops when Turbo/ActionCable is unavailable.

IMPORTANT: Broadcasting failures MUST NOT block error logging. All public methods rescue exceptions and log them.

Class Method Summary collapse

Class Method Details

.available?Boolean

Check if broadcasting infrastructure is available

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rails_error_dashboard/services/error_broadcaster.rb', line 75

def self.available?
  return false unless defined?(Turbo)
  return false unless defined?(ActionCable)

  Rails.cache.write("rails_error_dashboard_broadcast_test", true, expires_in: 1.second)
  Rails.cache.delete("rails_error_dashboard_broadcast_test")
  true
rescue => e
  Rails.logger.debug("[RailsErrorDashboard] Broadcast not available: #{e.message}")
  false
end

.broadcast_new(error_log) ⇒ Object

Broadcast a new error (prepend to error list + refresh stats)

Parameters:

  • error_log (ErrorLog)

    The newly created error



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rails_error_dashboard/services/error_broadcaster.rb', line 15

def self.broadcast_new(error_log)
  return unless error_log
  return unless available?

  platforms = ErrorLog.distinct.pluck(:platform).compact
  show_platform = platforms.size > 1

  Turbo::StreamsChannel.broadcast_prepend_to(
    "error_list",
    target: "error_list",
    partial: "rails_error_dashboard/errors/error_row",
    locals: { error: error_log, show_platform: show_platform }
  )
  broadcast_stats
rescue => e
  Rails.logger.error("[RailsErrorDashboard] Failed to broadcast new error: #{e.class} - #{e.message}")
  Rails.logger.debug("[RailsErrorDashboard] Backtrace: #{e.backtrace&.first(3)&.join("\n")}")
end

.broadcast_statsObject

Broadcast stats refresh



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rails_error_dashboard/services/error_broadcaster.rb', line 56

def self.broadcast_stats
  return unless available?

  stats = Queries::DashboardStats.call
  return unless stats.is_a?(Hash) && stats.present?

  Turbo::StreamsChannel.broadcast_replace_to(
    "error_list",
    target: "dashboard_stats",
    partial: "rails_error_dashboard/errors/stats",
    locals: { stats: stats }
  )
rescue => e
  Rails.logger.error("[RailsErrorDashboard] Failed to broadcast stats update: #{e.class} - #{e.message}")
  Rails.logger.debug("[RailsErrorDashboard] Backtrace: #{e.backtrace&.first(3)&.join("\n")}")
end

.broadcast_update(error_log) ⇒ Object

Broadcast an error update (replace in error list + refresh stats)

Parameters:

  • error_log (ErrorLog)

    The updated error



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rails_error_dashboard/services/error_broadcaster.rb', line 36

def self.broadcast_update(error_log)
  return unless error_log
  return unless available?

  platforms = ErrorLog.distinct.pluck(:platform).compact
  show_platform = platforms.size > 1

  Turbo::StreamsChannel.broadcast_replace_to(
    "error_list",
    target: "error_#{error_log.id}",
    partial: "rails_error_dashboard/errors/error_row",
    locals: { error: error_log, show_platform: show_platform }
  )
  broadcast_stats
rescue => e
  Rails.logger.error("[RailsErrorDashboard] Failed to broadcast error update: #{e.class} - #{e.message}")
  Rails.logger.debug("[RailsErrorDashboard] Backtrace: #{e.backtrace&.first(3)&.join("\n")}")
end