Class: RubyAsterisk::ARI::WebSocket

Inherits:
Object
  • Object
show all
Includes:
Connection, EventHandlers, Heartbeat, Reconnect
Defined in:
lib/ruby-asterisk/ari/websocket.rb,
lib/ruby-asterisk/ari/websocket/heartbeat.rb,
lib/ruby-asterisk/ari/websocket/reconnect.rb,
lib/ruby-asterisk/ari/websocket/connection.rb,
lib/ruby-asterisk/ari/websocket/event_handlers.rb,
lib/ruby-asterisk/ari/websocket/socket_adapter.rb

Overview

WebSocket client for ARI events Connects to the Asterisk ARI WebSocket endpoint to receive real-time events

I/O model (no EventMachine): the WebSocket protocol is handled by the pure Ruby websocket-driver gem over a plain TCPSocket (SSLSocket for wss).

connection_thread — owns the socket lifecycle: connects, runs the read
                  loop (readpartial -> driver.parse -> callbacks), and
                  re-connects after a drop while auto-reconnect is on.

ping_thread       — started when the connection opens; wakes every
                  ping_interval seconds and sends a WebSocket ping.

Event callbacks execute in the connection thread. All driver calls are serialized through a reentrant Monitor so send_message? is safe from any thread.

Defined Under Namespace

Modules: Connection, EventHandlers, Heartbeat, Reconnect Classes: SocketAdapter

Constant Summary collapse

PING_INTERVAL =

Ping interval in seconds to keep connection alive

30
RECONNECT_DELAY =

Reconnect delay in seconds (base for exponential backoff)

5
MAX_RECONNECT_DELAY =

Upper bound for the exponential reconnect backoff, in seconds

60
MAX_RECONNECT_ATTEMPTS =

Maximum reconnection attempts (nil for infinite)

nil

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_url, api_key, app_name, options = {}) ⇒ WebSocket

Initialize a new WebSocket client

Parameters:

  • base_url (String)

    Base URL of the Asterisk server (e.g., 'http://localhost:8088')

  • api_key (String)

    API key for authentication

  • app_name (String)

    Stasis application name

  • options (Hash) (defaults to: {})

    Additional options

Options Hash (options):

  • :logger (Logger)

    Logger instance for debugging

  • :ping_interval (Integer)

    Ping interval in seconds (default: 30)

  • :auto_reconnect (Boolean)

    Enable auto-reconnect (default: true)

  • :reconnect_delay (Integer)

    Delay between reconnection attempts (default: 5)



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ruby-asterisk/ari/websocket.rb', line 64

def initialize(base_url, api_key, app_name, options = {})
  @base_url = base_url
  @api_key = api_key
  @app_name = app_name
  @callbacks = {}
  @connected = false
  @should_reconnect = options.fetch(:auto_reconnect, true)
  @reconnect_attempts = 0
  @logger = options[:logger] || Logger.new($stdout)
  @ping_interval = options.fetch(:ping_interval, PING_INTERVAL)
  @reconnect_delay = options.fetch(:reconnect_delay, RECONNECT_DELAY)
  initialize_io_state
end

Instance Attribute Details

#app_nameObject (readonly)

Returns the value of attribute app_name.



40
41
42
# File 'lib/ruby-asterisk/ari/websocket.rb', line 40

def app_name
  @app_name
end

#callbacksObject (readonly)

Returns the value of attribute callbacks.



40
41
42
# File 'lib/ruby-asterisk/ari/websocket.rb', line 40

def callbacks
  @callbacks
end

#connectedObject (readonly)

Returns the value of attribute connected.



40
41
42
# File 'lib/ruby-asterisk/ari/websocket.rb', line 40

def connected
  @connected
end

#urlObject (readonly)

Returns the value of attribute url.



40
41
42
# File 'lib/ruby-asterisk/ari/websocket.rb', line 40

def url
  @url
end

Instance Method Details

#connect {|self| ... } ⇒ self

Connect to the WebSocket endpoint

Yields:

  • (self)

    Block called when connection is established

Returns:

  • (self)


82
83
84
85
86
# File 'lib/ruby-asterisk/ari/websocket.rb', line 82

def connect(&block)
  @on_connect_callback = block
  @connection_thread = Thread.new { connection_loop }
  self
end

#connected?Boolean

Check if WebSocket is connected

Returns:

  • (Boolean)


120
121
122
# File 'lib/ruby-asterisk/ari/websocket.rb', line 120

def connected?
  !!(@connected && @driver && @driver.state == :open)
end

#disconnectself

Disconnect from the WebSocket

Returns:

  • (self)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/ruby-asterisk/ari/websocket.rb', line 102

def disconnect
  @should_reconnect = false
  stop_ping_timer
  close_connection
  wake_sleepers

  thread = @connection_thread
  @connection_thread = nil
  thread&.join(2) unless thread == Thread.current

  @connected = false
  @logger.info 'WebSocket disconnected'
  self
end

#on(event_type, &block) ⇒ self

Register a callback for a specific event type

Parameters:

  • event_type (String, Symbol)

    Event type to listen for (e.g., 'StasisStart')

  • block (Proc)

    Block to execute when event is received

Returns:

  • (self)


93
94
95
96
97
# File 'lib/ruby-asterisk/ari/websocket.rb', line 93

def on(event_type, &block)
  @callbacks[event_type.to_s] = [] unless @callbacks.key?(event_type.to_s)
  @callbacks[event_type.to_s] << block
  self
end

#send_message?(message) ⇒ Boolean

Send a message through the WebSocket

Parameters:

  • message (Hash, String)

    Message to send (will be converted to JSON if Hash)

Returns:

  • (Boolean)

    true if sent successfully



128
129
130
131
132
133
134
135
136
137
# File 'lib/ruby-asterisk/ari/websocket.rb', line 128

def send_message?(message)
  driver = @driver
  return false unless @connected && driver && driver.state == :open

  data = message.is_a?(Hash) ? JSON.generate(message) : message
  @driver_monitor.synchronize { driver.text(data) }
  true
rescue IOError, SystemCallError
  false
end