Class: RightScale::OfflineHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/right_agent/offline_handler.rb

Overview

Handler for queueing of requests when offline relative to RightNet and then sending the requests when successfully reconnect

Constant Summary collapse

MAX_QUEUE_FLUSH_DELAY =

Maximum seconds to wait before starting flushing offline queue when disabling offline mode

60
MAX_QUEUED_REQUESTS =

Maximum number of offline queued requests before triggering restart vote

100
RESTART_VOTE_DELAY =

Number of seconds that should be spent in offline mode before triggering a restart vote

15 * 60

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(restart_callback, offline_stats) ⇒ OfflineHandler

Create offline queueing handler

Parameters

restart_callback(Proc)

Callback that is activated on each restart vote with votes being initiated

by offline queue exceeding MAX_QUEUED_REQUESTS
offline_stats(RightSupport::Stats::Activity)

Offline queue tracking statistics



63
64
65
66
67
68
69
70
71
# File 'lib/right_agent/offline_handler.rb', line 63

def initialize(restart_callback, offline_stats)
  @restart_vote = restart_callback
  @restart_vote_timer = nil
  @restart_vote_count = 0
  @offline_stats = offline_stats
  @state = :created
  @mode = :initializing
  @queue = []
end

Instance Attribute Details

#modeObject (readonly)

(Symbol) Current offline handling mode with possible values:

Value          Description
:initializing  Agent still initializing
:online        Agent connected
:offline       Agent disconnected


52
53
54
# File 'lib/right_agent/offline_handler.rb', line 52

def mode
  @mode
end

#queueObject

(Array) Offline queue



55
56
57
# File 'lib/right_agent/offline_handler.rb', line 55

def queue
  @queue
end

#stateObject (readonly)

(Symbol) Current queue state with possible values:

Value          Description                Action               Next state
:created       Queue created              init                 :initializing
:initializing  Agent still initializing   start                :running
:running       Queue has been started     disable when offline :flushing
:flushing      Sending queued requests    enable               :running
:terminating   Agent terminating


45
46
47
# File 'lib/right_agent/offline_handler.rb', line 45

def state
  @state
end

Instance Method Details

#disableObject

Switch back to sending requests after in-memory queue gets flushed Idempotent

Return

true

Always return true



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/right_agent/offline_handler.rb', line 149

def disable
  if offline? && @state != :created
    Log.info("[offline] Connection to RightNet re-established")
    @offline_stats.finish
    cancel_timer
    @state = :flushing
    # Wait a bit to avoid flooding RightNet
    EM.add_timer(rand(MAX_QUEUE_FLUSH_DELAY)) { flush }
  end
  true
end

#enableObject

Switch to offline mode In this mode requests are queued in memory rather than being sent Idempotent

Return

true

Always return true



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/right_agent/offline_handler.rb', line 125

def enable
  if offline?
    if @state == :flushing
      # If we were in offline mode then switched back to online but are still in the
      # process of flushing the in-memory queue and are now switching to offline mode
      # again then stop the flushing
      @state = :running
    end
  else
    Log.info("[offline] Disconnect from RightNet detected, entering offline mode")
    Log.info("[offline] Messages will be queued in memory until RightNet connection is re-established")
    @offline_stats.update
    @queue ||= []  # Ensure queue is valid without losing any messages when going offline
    @mode = :offline
    start_timer
  end
  true
end

#initObject

Initialize the offline queue All requests sent prior to running this initialization are queued and then are sent once this initialization has run All requests following this call and prior to calling start are prepended to the request queue

Return

true

Always return true



81
82
83
84
# File 'lib/right_agent/offline_handler.rb', line 81

def init
  @state = :initializing if @state == :created
  true
end

#offline?Boolean

Is agent currently offline?

Return

(Boolean)

true if agent offline, otherwise false

Returns:

  • (Boolean)


107
108
109
# File 'lib/right_agent/offline_handler.rb', line 107

def offline?
  @mode == :offline || @state == :created
end

#queue_request(kind, type, payload, target, token, expires_at, &callback) ⇒ Object

Queue given request in memory

Parameters

kind(Symbol)

Kind of request: :send_push or :send_request

type(String)

Dispatch route for the request; typically identifies actor and action

payload(Object)

Data to be sent with marshalling en route

target(Hash|NilClass)

Target for request

token(String)

Token uniquely identifying request

expires_at(Integer)

Time in seconds in Unix-epoch when this request expires and

is to be ignored by the receiver; value 0 means never expire

Block

Optional block used to process response asynchronously with the following parameter:

result(Result):: Response with an OperationResult of SUCCESS, RETRY, NON_DELIVERY, or ERROR

Return

true

Always return true



178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/right_agent/offline_handler.rb', line 178

def queue_request(kind, type, payload, target, token, expires_at, &callback)
  request = {:kind => kind, :type => type, :payload => payload, :target => target,
             :token => token, :expires_at => expires_at, :callback => callback}
  Log.info("[offline] Queuing request: #{request.inspect}")
  vote_to_restart if (@restart_vote_count += 1) >= MAX_QUEUED_REQUESTS
  if @state == :initializing
    # We are in the initialization callback, requests should be put at the head of the queue
    @queue.unshift(request)
  else
    @queue << request
  end
  true
end

#queueing?Boolean

In request queueing mode?

Return

(Boolean)

true if should queue request, otherwise false

Returns:

  • (Boolean)


115
116
117
# File 'lib/right_agent/offline_handler.rb', line 115

def queueing?
  offline? && @state != :flushing
end

#startObject

Switch to online mode and send all buffered messages

Return

true

Always return true



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/right_agent/offline_handler.rb', line 90

def start
  if @state == :initializing
    if @mode == :offline
      @state = :running
    else
      @state = :flushing
      flush
    end
    @mode = :online if @mode == :initializing
  end
  true
end

#terminateObject

Prepare for agent termination

Return

true

Always return true



196
197
198
199
200
# File 'lib/right_agent/offline_handler.rb', line 196

def terminate
  @state = :terminating
  cancel_timer
  true
end