Class: RightScale::RouterClient

Inherits:
BaseRetryClient show all
Defined in:
lib/right_agent/clients/router_client.rb

Overview

HTTP interface to RightNet router

Constant Summary collapse

API_VERSION =

RightNet router API version for use in X-API-Version header

"2.0"
CONNECT_INTERVAL =

Initial interval between attempts to make a WebSocket connection

30
MAX_CONNECT_INTERVAL =

Maximum interval between attempts to make a WebSocket connection

60 * 60 * 24
RECONNECT_INTERVAL =

Initial interval between attempts to reconnect or long-poll when router is not responding

2
MAX_RECONNECT_INTERVAL =

Maximum interval between attempts to reconnect or long-poll when router is not responding

30
CHECK_INTERVAL =

Interval between checks for lost WebSocket connection

5
BACKOFF_FACTOR =

Backoff factor for connect and reconnect intervals

2
NORMAL_CLOSE =

WebSocket close status codes

1000
SHUTDOWN_CLOSE =
1001
PROTOCOL_ERROR_CLOSE =
1002
UNEXPECTED_ERROR_CLOSE =
1011
DEFAULT_LISTEN_TIMEOUT =

Default time to wait for an event or to ping WebSocket

60
MAX_LISTEN_FAILURES =

Maximum repeated listen failures at which point give up listening

10

Constants inherited from BaseRetryClient

BaseRetryClient::DEFAULT_OPEN_TIMEOUT, BaseRetryClient::DEFAULT_RECONNECT_INTERVAL, BaseRetryClient::DEFAULT_REQUEST_TIMEOUT, BaseRetryClient::DEFAULT_RETRY_INTERVALS, BaseRetryClient::DEFAULT_RETRY_TIMEOUT, BaseRetryClient::PERMITTED_STATE_TRANSITIONS

Instance Attribute Summary

Attributes inherited from BaseRetryClient

#state

Instance Method Summary collapse

Methods inherited from BaseRetryClient

#communicated, #init, #status

Constructor Details

#initialize(auth_client, options) ⇒ RouterClient

Create RightNet router client

Options Hash (options):

  • :open_timeout (Numeric)

    maximum wait for connection; defaults to DEFAULT_OPEN_TIMEOUT

  • :request_timeout (Numeric)

    maximum wait for response; defaults to DEFAULT_REQUEST_TIMEOUT

  • :listen_timeout (Numeric)

    maximum wait for event; defaults to DEFAULT_LISTEN_TIMEOUT

  • :long_polling_only (Boolean)

    never attempt to create a WebSocket, always long-polling instead

  • :retry_timeout (Numeric)

    maximum before stop retrying; defaults to DEFAULT_RETRY_TIMEOUT

  • :retry_intervals (Array)

    between successive retries; defaults to DEFAULT_RETRY_INTERVALS

  • :retry_enabled (Boolean)

    for requests that fail to connect or that return a retry result

  • :reconnect_interval (Numeric)

    for reconnect attempts after lose connectivity

  • :non_blocking (Boolean)

    i/o is to be used for HTTP requests by applying EM::HttpRequest and fibers instead of RestClient; requests remain synchronous

  • :exception_callback (Proc)

    for unexpected exceptions

Raises:

  • (ArgumentError)

    auth client does not support this client type



94
95
96
97
# File 'lib/right_agent/clients/router_client.rb', line 94

def initialize(auth_client, options)
  init(:router, auth_client, options.merge(:server_name => "RightNet", :api_version => API_VERSION))
  @options[:listen_timeout] ||= DEFAULT_LISTEN_TIMEOUT
end

Instance Method Details

#close(scope = :all) ⇒ TrueClass

Take any actions necessary to quiesce client interaction in preparation for agent termination but allow any active requests to complete



249
250
251
252
253
# File 'lib/right_agent/clients/router_client.rb', line 249

def close(scope = :all)
  super
  update_listen_state(:cancel)
  @websocket.close(SHUTDOWN_CLOSE, "Agent terminating") if @websocket
end

#listen(routing_keys) {|event| ... } ⇒ TrueClass

Receive events via an HTTP WebSocket if available, otherwise via an HTTP long-polling

Yields:

  • (event)

    required block called each time event received

Yield Parameters:

  • event (Hash)

    received

Raises:



228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/right_agent/clients/router_client.rb', line 228

def listen(routing_keys, &handler)
  raise ArgumentError, "Block missing" unless block_given?

  @event_uuids = nil
  @listen_interval = 0
  @listen_state = :choose
  @listen_failures = 0
  @connect_interval = CONNECT_INTERVAL
  @reconnect_interval = RECONNECT_INTERVAL

  listen_loop(routing_keys, &handler)
  true
end

#notify(event, routing_keys) ⇒ TrueClass

Route event Use WebSocket if possible Do not block this request even if in the process of closing since used for request responses

Raises:



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/right_agent/clients/router_client.rb', line 196

def notify(event, routing_keys)
  event[:uuid] ||= RightSupport::Data::UUID.generate
  event[:version] ||= AgentConfig.protocol_version
  params = {:event => event}
  params[:routing_keys] = routing_keys if routing_keys
  if @websocket
    path = event[:path] ? " #{event[:path]}" : ""
    to = routing_keys ? " to #{routing_keys.inspect}" : ""
    Log.info("Sending EVENT <#{event[:uuid]}> #{event[:type]}#{path}#{to}")
    @websocket.send(JSON.dump(params))
  else
    make_request(:post, "/notify", params, "notify", :request_uuid => event[:uuid], :filter_params => ["event"])
  end
  true
end

#push(type, payload, target, options = {}) ⇒ NilClass

Route a request to a single target or multiple targets with no response expected Persist the request en route to reduce the chance of it being lost at the expense of some additional network overhead Enqueue the request if the target is not currently available Never automatically retry the request if there is the possibility of it being duplicated Set time-to-live to be forever

Options Hash (options):

  • :request_uuid (String)

    uniquely identifying this request; defaults to randomly generated

  • :time_to_live (Numeric)

    seconds before request expires and is to be ignored; non-positive value or nil means never expire

Raises:



133
134
135
136
137
138
139
# File 'lib/right_agent/clients/router_client.rb', line 133

def push(type, payload, target, options = {})
  params = {
    :type => type,
    :payload => payload,
    :target => target }
  make_request(:post, "/push", params, type.split("/")[2], options)
end

#request(type, payload, target, options = {}) ⇒ Result, NilClass

Route a request to a single target with a response expected Automatically retry the request if a response is not received in a reasonable amount of time or if there is a non-delivery response indicating the target is not currently available Timeout the request if a response is not received in time, typically configured to 30 sec Because of retries there is the possibility of duplicated requests, and these are detected and discarded automatically for non-idempotent actions Allow the request to expire per the agent’s configured time-to-live, typically 1 minute

Options Hash (options):

  • :request_uuid (String)

    uniquely identifying this request; defaults to randomly generated

  • :time_to_live (Numeric)

    seconds before request expires and is to be ignored; non-positive value or nil means never expire

Raises:



172
173
174
175
176
177
178
# File 'lib/right_agent/clients/router_client.rb', line 172

def request(type, payload, target, options = {})
  params = {
    :type => type,
    :payload => payload,
    :target => target }
  make_request(:post, "/request", params, type.split("/")[2], options)
end

#stats(reset = false) ⇒ Hash

Current statistics for this client



266
267
268
269
270
271
# File 'lib/right_agent/clients/router_client.rb', line 266

def stats(reset = false)
  events = @stats["events"].all
  stats = super(reset)
  stats["events"] = events
  stats
end