class Signalwire::Relay::Client

Attributes

connected[RW]
host[RW]
project[RW]
protocol[RW]
session[RW]
url[RW]

Public Class Methods

new(project:, token:, host: nil) click to toggle source

Creates a Relay client

@param project [String] Your SignalWire project identifier @param token [String] Your SignalWire secret token @param SIGNALWIRE_HOST [String] Your SignalWire space URL (not needed for production usage)

# File lib/signalwire/relay/client.rb, line 17
def initialize(project:, token:, host: nil)
  @project = project
  @token = token
  @host = host || ENV.fetch('SIGNALWIRE_HOST', Signalwire::Relay::DEFAULT_URL)
  @url = clean_up_space_url(@host)
  @protocol = nil

  @connected = false

  setup_session
  setup_handlers
  setup_events
end

Public Instance Methods

calling() click to toggle source
# File lib/signalwire/relay/client.rb, line 91
def calling
  @calling ||= Signalwire::Relay::Calling::Instance.new(self)
end
clean_up_space_url(space_url) click to toggle source
# File lib/signalwire/relay/client.rb, line 44
def clean_up_space_url(space_url)
  uri = URI.parse(space_url)
  # oddly, URI.parse interprets a simple hostname as a path
  if uri.scheme.nil? && uri.host.nil?
    unless uri.path.nil?
      uri.scheme = 'wss'
      uri.host = uri.path
      uri.path = ''
    end
  end

  uri.to_s
end
connect!() click to toggle source

Starts the client connection

# File lib/signalwire/relay/client.rb, line 33
def connect!
  logger.debug "Connecting to #{@url}"
  session.connect!
end
contexts() click to toggle source
# File lib/signalwire/relay/client.rb, line 114
def contexts
  @contexts ||= Concurrent::Array.new
end
disconnect!() click to toggle source

Terminates the session

# File lib/signalwire/relay/client.rb, line 40
def disconnect!
  session.disconnect!
end
execute(command, &block) click to toggle source
# File lib/signalwire/relay/client.rb, line 58
def execute(command, &block)
  @session.execute(command, &block)
end
messaging() click to toggle source
# File lib/signalwire/relay/client.rb, line 95
def messaging
  @messaging ||= Signalwire::Relay::Messaging::Instance.new(self)
end
relay_execute(command, timeout = Signalwire::Relay::COMMAND_TIMEOUT, &block) click to toggle source

TODO: refactor this for style

# File lib/signalwire/relay/client.rb, line 63
def relay_execute(command, timeout = Signalwire::Relay::COMMAND_TIMEOUT, &block)
  promise = Concurrent::Promises.resolvable_future

  execute(command) do |event|
    promise.fulfill event
  end

  promise.wait timeout

  if promise.fulfilled?
    event = promise.value
    code = event.dig(:result, :result, :code)
    message = event.dig(:result, :result, :message)
    success = code == '200' ? :success : :failure

    if code
      block.call(event, success) if block_given?
      logger.error "Relay command failed with code #{code} and message: #{message}" unless success
    else
      logger.error("Relay error occurred, code #{event.error_code}: #{event.error_message}") if event.error?
      block.call(event, :failure) if block_given?
    end
  else
    logger.error 'Unknown Relay command failure, command timed out'
    block.call(event, :failure) if block_given?
  end
end
setup_context(context) click to toggle source
# File lib/signalwire/relay/client.rb, line 99
def setup_context(context)
  return if contexts.include?(context)
  receive_command = {
    protocol: @protocol,
    method: 'signalwire.receive',
    params: {
      context: context
    }
  }

  relay_execute receive_command do
    contexts << context
  end
end

Private Instance Methods

protocol_setup() click to toggle source
# File lib/signalwire/relay/client.rb, line 132
def protocol_setup
  setup = {
    protocol: 'signalwire',
    method: 'setup',
    params: {
    }
  }

  # hijack our protocol
  setup[:params][:protocol] = @protocol if @protocol

  @session.execute(setup) do |event|
    @protocol = event.dig(:result, :result, :protocol)
    logger.debug "Protocol set up as #{protocol}"

    notification_request = {
      "protocol": @protocol,
      "command": 'add',
      "channels": ['notifications']
    }

    @session.subscribe(notification_request) do
      logger.debug "Subscribed to notifications for #{protocol}"
      @connected = true
      @contexts = Concurrent::Array.new
      broadcast :ready, self
    end
  end
end
setup_events() click to toggle source
# File lib/signalwire/relay/client.rb, line 170
def setup_events
  @session.on :message, %i[\[\] method] => 'blade.broadcast' do |event|
    relay = Signalwire::Relay::Event.from_blade(event)
    broadcast :event, relay
    broadcast :task, relay if relay.dig(:params, :event) == "queuing.relay.tasks"
  end
end
setup_handlers() click to toggle source
# File lib/signalwire/relay/client.rb, line 120
def setup_handlers
  @session.on :connected do |event|
    logger.debug 'Relay client connected'
    broadcast :connecting, event
    if event.error?
      logger.error("Error setting up Blade connection")
    else
      protocol_setup
    end
  end
end
setup_session() click to toggle source
# File lib/signalwire/relay/client.rb, line 162
def setup_session
  auth = {
    project: @project,
    token: @token
  }
  @session = Signalwire::Blade::Connection.new(url: url, authentication: auth)
end