Class: RightScale::RightHttpClient

Inherits:
Object
  • Object
show all
Includes:
RightSupport::Ruby::EasySingleton
Defined in:
lib/right_agent/clients/right_http_client.rb

Overview

HTTP interface to RightNet router and to RightNet services in RightApi It is intended for use by instance agents and infrastructure servers The interface supports sending requests and sending/receiving events Events are received over a WebSocket if possible, otherwise via long-polling Requests to RightNet and RightApi are automatically retried to overcome connectivity failures A status callback is provided so that the user of this client can take action (e.g., queue requests) when connectivity is lost Health checks are sent periodically to try to recover from connectivity failures

Instance Method Summary collapse

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 Only router and api clients are closed, not auth client



237
238
239
240
241
# File 'lib/right_agent/clients/right_http_client.rb', line 237

def close(scope = :all)
  @router.close(scope) if @router
  @api.close(scope) if @api
  true
end

#communicated(types = []) { ... } ⇒ TrueClass

Set callback for each successful communication excluding health checks

Yields:

  • required block executed after successful communication

Raises:

  • (RuntimeError)

    init was not called



221
222
223
224
225
226
227
# File 'lib/right_agent/clients/right_http_client.rb', line 221

def communicated(types = [], &callback)
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  @auth.communicated(&callback) if types.empty? || types.include?(:auth)
  @api.communicated(&callback) if @api && (types.empty? || types.include?(:api))
  @router.communicated(&callback) if @router && (types.empty? || types.include?(:router))
  true
end

#init(auth_client, options = {}) ⇒ TrueClass

Initialize RightNet client Must be called before any other functions are usable

Options Hash (options):

  • :open_timeout (Numeric)

    maximum wait for connection

  • :request_timeout (Numeric)

    maximum wait for response

  • :listen_timeout (Numeric)

    maximum wait for event when long-polling

  • :retry_timeout (Numeric)

    maximum before stop retrying

  • :retry_intervals (Array)

    between successive retries

  • :retry_enabled (Boolean)

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

  • :non_blocking (Boolean)

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

  • :long_polling_only (Boolean)

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

  • :filter_params (Array)

    symbols or strings for names of request parameters whose values are to be hidden when logging

Raises:

  • (ArgumentError)

    no auth client



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/right_agent/clients/right_http_client.rb', line 58

def init(auth_client, options = {})
  raise ArgumentError, "No authorization client provided" unless auth_client.is_a?(AuthClient)
  @status = {}
  callback = lambda { |type, state| update_status(type, state) }
  @auth = auth_client
  @status[:auth] = @auth.status(&callback)
  @router = RouterClient.new(@auth, options)
  @status[:router] = @router.status(&callback)
  if @auth.api_url
    @api = ApiClient.new(@auth, options)
    @status[:api] = @api.status(&callback)
  end
  true
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:

Raises:



184
185
186
187
# File 'lib/right_agent/clients/right_http_client.rb', line 184

def listen(routing_keys, &handler)
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  @router.listen(routing_keys, &handler)
end

#notify(event, routing_keys) ⇒ TrueClass

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

Raises:



165
166
167
168
# File 'lib/right_agent/clients/right_http_client.rb', line 165

def notify(event, routing_keys)
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  @router.notify(event, routing_keys)
end

#push(type, payload = nil, target = nil, 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:



107
108
109
110
111
# File 'lib/right_agent/clients/right_http_client.rb', line 107

def push(type, payload = nil, target = nil, options = {})
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  client = (@api && @api.support?(type)) ? @api : @router
  client.push(type, payload, target, options)
end

#request(type, payload = nil, target = nil, 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:



144
145
146
147
148
# File 'lib/right_agent/clients/right_http_client.rb', line 144

def request(type, payload = nil, target = nil, options = {})
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  client = (@api && @api.support?(type)) ? @api : @router
  client.request(type, payload, target, options)
end

#self_hrefString, NilClass

Resource href associated with the user of this client



192
193
194
# File 'lib/right_agent/clients/right_http_client.rb', line 192

def self_href
  @api.self_href if @api
end

#stats(reset = false) ⇒ Hash

Current statistics for this client

Raises:

  • (RuntimeError)

    init was not called



251
252
253
254
255
256
257
258
# File 'lib/right_agent/clients/right_http_client.rb', line 251

def stats(reset = false)
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  stats = {}
  stats["auth stats"] = @auth.stats(reset)
  stats["router stats"] = @router.stats(reset)
  stats["api stats"] = @api.stats(reset) if @api
  stats
end

#status {|type, status| ... } ⇒ Hash

Record callback to be notified of status changes Multiple callbacks are supported

Yields:

  • (type, status)

    called when status changes (optional)

Yield Parameters:

  • type (Symbol)

    of client reporting status change: :auth, :api, or :router

  • state (Symbol)

    of client

Raises:

  • (RuntimeError)

    init was not called



206
207
208
209
210
# File 'lib/right_agent/clients/right_http_client.rb', line 206

def status(&callback)
  raise RuntimeError, "#{self.class.name}#init was not called" unless @auth
  @status_callbacks = (@status_callbacks || []) << callback if callback
  @status
end