module Neighborparrot

Callbacks used by the client

Configuration settings and methods

Constants

ASSETS_SERVER
DEFAULT_SEND_TIMEOUT
DEFAULT_SERVER
EVENTS

Public Class Methods

configuration() click to toggle source

Return settings

# File lib/neighborparrot/config.rb, line 14
def self.configuration
  @@config
end
configure(params={}) click to toggle source

Setup the configuration options

  • :api_id => Your api ID in neighborparrot.com

  • :api_key => Your api key

  • :server => Server to connect (Only for development)

  • :dummy_tests => See neighboparrot/helpers/url_helpers

# File lib/neighborparrot/config.rb, line 9
def self.configure(params={})
  @@config.merge! params
end
open(request, params={}, &block) click to toggle source

Static helper. Create a EM Reactor and open the connexion on it

# File lib/neighborparrot/open.rb, line 51
def self.open(request, params={}, &block)
  EM.error_handler { |error| Neighborparrot.trigger_error error }

  EM.run do

    parrot = Neighborparrot::Reactor.new

    parrot.on_error do |error|
      Neighborparrot.trigger_error error
      EM.stop
    end
    parrot.on_message do |message|
      Neighborparrot.trigger_message message
    end
    parrot.on_connect { Neighborparrot.trigger_connect }

    parrot.open request, params
  end
end
reactor_running?() click to toggle source

@return true if module reactor running

# File lib/neighborparrot/reactor.rb, line 21
def self.reactor_running?
  @@class_reactor && @@class_reactor.running?
end
reactor_start() click to toggle source

Static a module reactor and keeping running and waiting

# File lib/neighborparrot/reactor.rb, line 7
def self.reactor_start
  if @@class_reactor.nil?
    return @@class_reactor = Reactor.new
  end
  @@class_reactor.start
end
reactor_stop() click to toggle source

Stop the module reactor

# File lib/neighborparrot/reactor.rb, line 15
def self.reactor_stop
  return unless @@class_reactor
  @@class_reactor.stop
end
send(request, params={}) click to toggle source

Send the message to the broker. Create a new reactor and run the request inside Any output is printed in the standard output. If you start a module reactor in some point in your program the request is scheduled in this reactor and return the control to your program. Module callbacks are used in this case.

# File lib/neighborparrot/send.rb, line 10
def self.send(request, params={})
  if self.reactor_running?
    return @@class_reactor.send request, params
  end
  response = nil
  error = false
  EM.run do
    parrot = Neighborparrot::Reactor.new
    parrot.on_error do |msg|
      error = msg
      parrot.stop
    end
      parrot.on_success do |resp|
      Neighborparrot.trigger_success resp
      response = resp
      parrot.stop
    end
    # Skip reactor queues
    parrot.send_to_broker(:request => request, :params => params)
  end
  fail error if error
  return response
end
sign_connect_request(query, params={}) click to toggle source
# File lib/neighborparrot/auth.rb, line 5
def self.sign_connect_request(query, params={})
  endpoint = query[:service] == 'es' ? '/open' : '/ws'
  sign_request('GET', endpoint, query, params)
end
sign_request(method, path, request, params={}) click to toggle source
# File lib/neighborparrot/auth.rb, line 14
def self.sign_request(method, path, request, params={})
  params = Neighborparrot.configuration.merge params
  token = Signature::Token.new(params[:api_id], params[:api_key])
  sign_request = Signature::Request.new(method, path, request)
  auth_hash = sign_request.sign(token)
  request.merge(auth_hash)
end
sign_send_request(body, params={}) click to toggle source
# File lib/neighborparrot/auth.rb, line 10
def self.sign_send_request(body, params={})
  sign_request('POST', '/send',body, params)
end

Private Class Methods

default_values() click to toggle source
# File lib/neighborparrot/config.rb, line 24
def self.default_values
  {
    :server => DEFAULT_SERVER ,
    :assets_server => ASSETS_SERVER,
    :send_timeout => DEFAULT_SEND_TIMEOUT
  }
end

Public Instance Methods

close() click to toggle source
# File lib/neighborparrot/open.rb, line 45
def close
  return unless connected?
  @source.close
end
connected?() click to toggle source
# File lib/neighborparrot/open.rb, line 41
def connected?
  @source && @source.ready_state == EM::EventSource::OPEN
end
open(request, params={}) click to toggle source

Open a Event Source connection with the broker

# File lib/neighborparrot/reactor.rb, line 82
def open(request, params={})
  EM.schedule { open_connection request, params }
end
open_connection(request, params={}) click to toggle source

Open a persistent connection to the Neighbor in a new thread and return true if all works unless :foreground options is true. Current options to the connectio are:

@param [String] channel to connect @param [Hash] Params for the connection. this params can be:

  • :foreground [Boolean] run the connection in the foreground

    stoping the clode flow until the connection is closed by server or
    another thread call close
    
  • :api_id => Your api ID in neighborparrot.com

  • :api_key => Your api key

  • :server => Server to connect (Only for development)

# File lib/neighborparrot/open.rb, line 17
def open_connection(request, params={})
  params = Neighborparrot.configuration.merge params
  return unless check_params request.merge(params), :post
  return if dummy_connections?
  uri = URI.parse(params[:server])
  url = "#{params[:server]}/open"
  signed_request = Neighborparrot.sign_connect_request(request, params)
  @source = EM::EventSource.new(url, signed_request)
  @source.inactivity_timeout = 120
  @source.message do |message|
   EM.next_tick { trigger_message message }
  end
  @source.error do |error|
    puts "Error #{error}"
    EM.next_tick { trigger_error error }
  end

  @source.open do
    EM.next_tick { trigger_connect }
  end

  @source.start
end
running?() click to toggle source

@return true if reactor running

# File lib/neighborparrot/reactor.rb, line 65
def running?
  EM.reactor_running?
end
send(request, params={}) click to toggle source

Send a message to a channel If empty data, refuse to send nothing @request [Hash] params

  • :channel => The channel name

  • :data => Your payload

@params optional parameters @return [Boolean] true if sended

# File lib/neighborparrot/reactor.rb, line 76
def send(request, params={})
  EM.schedule { @out_queue.push({ :request => request, :params => params }) }
end
send_to_broker(options) click to toggle source

Send the message to the broker This is the final step of a send request in the reactor process

# File lib/neighborparrot/send.rb, line 36
def send_to_broker(options)
  params = Neighborparrot.configuration.merge options[:params]
  request = options[:request]
  # TODO: Refactor
  # return unless check_params request
  return if request[:data].nil? || request[:data].length == 0
  return if params[:dummy_connections]

  signed_request = Neighborparrot.sign_send_request request, params

  url = "#{params[:server]}/send"
  http = EventMachine::HttpRequest.new(url).post :body => signed_request
  http.errback{ |msg| trigger_error msg }
  http.callback do
    if http.response_header.status == 200
      trigger_success http.response, params
    else
      trigger_error http.response
    end
  end
end
start() click to toggle source

Start the reactor if not running

# File lib/neighborparrot/reactor.rb, line 56
def start
  reactor_start unless running?
end
stop() click to toggle source

Stop the reactor

# File lib/neighborparrot/reactor.rb, line 61
def stop
  EM.schedule { EM.stop }
end

Private Instance Methods

check_params(p, action=:send) click to toggle source

Check mandatory parameters @param [Hash] parameters @param [Symbol] action [:send/:open]

# File lib/neighborparrot/config.rb, line 44
def check_params(p, action=:send)
  trigger_error "Channel can't be nil" if p[:channel].nil? || p[:channel].length == 0
  trigger_error "ERROR# Neighborparrot: api_id can't be nil" if p[:api_id].nil? || p[:api_id].length == 0
  trigger_error "ERROR# Neighborparrot: api_key can't be nil" if p[:api_key].nil? || p[:api_key].length == 0
  if action == :open
    trigger_error "ERROR# Neighborparrot: socket_id can't be nil" if p[:socket_id].nil? || p[:socket_id].length == 0
  end
  true
end
dummy_connections?() click to toggle source

Return true if neighborparrot is in dummy connection mode

# File lib/neighborparrot/config.rb, line 36
def dummy_connections?
  @@config[:dummy_tests] && in_rails? && Rails.env.test?
end
in_rails?() click to toggle source

In rails?

# File lib/neighborparrot/config.rb, line 55
def in_rails?
  defined?(Rails) == 'constant'
end
init_queue() click to toggle source

Prepare the sent queue for send the message to the broker as soon as possible

# File lib/neighborparrot/reactor.rb, line 102
def init_queue
  @out_queue = EM::Queue.new
  processor = proc { |msg|
    send_to_broker msg
    @out_queue.pop(&processor)
  }
  @out_queue.pop(&processor)
end
reactor_start() click to toggle source

Create a thread for the reactor and startit

# File lib/neighborparrot/reactor.rb, line 88
def reactor_start
  if EM.reactor_running?
    return init_queue unless @out_queue
  end
  @em_thread = Thread.new {
    EM.run  do
      EM.error_handler{ |e| trigger_error e }
      init_queue
    end
  }
end