module Neighborparrot
Callbacks used by the client
Configuration settings and methods
Constants
- ASSETS_SERVER
- DEFAULT_SEND_TIMEOUT
- DEFAULT_SERVER
- EVENTS
Public Class Methods
Return settings
# File lib/neighborparrot/config.rb, line 14 def self.configuration @@config end
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
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
@return true if module reactor running
# File lib/neighborparrot/reactor.rb, line 21 def self.reactor_running? @@class_reactor && @@class_reactor.running? end
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
Stop the module reactor
# File lib/neighborparrot/reactor.rb, line 15 def self.reactor_stop return unless @@class_reactor @@class_reactor.stop end
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
# 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
# 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
# File lib/neighborparrot/auth.rb, line 10 def self.sign_send_request(body, params={}) sign_request('POST', '/send',body, params) end
Private Class Methods
# 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
# File lib/neighborparrot/open.rb, line 45 def close return unless connected? @source.close end
# File lib/neighborparrot/open.rb, line 41 def connected? @source && @source.ready_state == EM::EventSource::OPEN end
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 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
@return true if reactor running
# File lib/neighborparrot/reactor.rb, line 65 def running? EM.reactor_running? end
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 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 the reactor if not running
# File lib/neighborparrot/reactor.rb, line 56 def start reactor_start unless running? end
Stop the reactor
# File lib/neighborparrot/reactor.rb, line 61 def stop EM.schedule { EM.stop } end
Private Instance Methods
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
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?
# File lib/neighborparrot/config.rb, line 55 def in_rails? defined?(Rails) == 'constant' end
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
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