Class: NewRelic::Agent::WorkerLoop

Inherits:
Object
  • Object
show all
Defined in:
lib/new_relic/agent/worker_loop.rb

Overview

A worker loop executes a set of registered tasks on a single thread. A task is a proc or block with a specified call period in seconds.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ WorkerLoop

Optional argument :duration (in seconds) for how long the worker loop runs or :limit (integer) for max number of iterations



17
18
19
20
21
22
23
24
25
# File 'lib/new_relic/agent/worker_loop.rb', line 17

def initialize(opts={})
  @should_run = true
  @next_invocation_time = Time.now
  @period = 60.0
  @duration = opts[:duration] if opts[:duration]
  @limit = opts[:limit] if opts[:limit]
  @iterations = 0
  @propagate_errors = opts.fetch(:propagate_errors, false)
end

Instance Attribute Details

#periodObject

Returns the value of attribute period.



13
14
15
# File 'lib/new_relic/agent/worker_loop.rb', line 13

def period
  @period
end

#propagate_errorsObject

Returns the value of attribute propagate_errors.



13
14
15
# File 'lib/new_relic/agent/worker_loop.rb', line 13

def propagate_errors
  @propagate_errors
end

Instance Method Details

#keep_running?Boolean

a simple accessor for @should_run

Returns:

  • (Boolean)


61
62
63
# File 'lib/new_relic/agent/worker_loop.rb', line 61

def keep_running?
  @should_run && under_duration? && under_limit?
end

#run(period = nil, &block) ⇒ Object

Run infinitely, calling the registered tasks at their specified call periods. The caller is responsible for creating the thread that runs this worker loop. This will run the task immediately.



42
43
44
45
46
47
48
49
50
# File 'lib/new_relic/agent/worker_loop.rb', line 42

def run(period=nil, &block)
  setup(period, block)
  while keep_running? do
    sleep_time = schedule_next_invocation
    sleep(sleep_time) if sleep_time > 0
    run_task if keep_running?
    @iterations += 1
  end
end

#run_taskObject

Executes the block given to the worker loop, and handles many possible errors. Also updates the execution time so that the next run occurs on schedule, even if we execute at some odd time



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/new_relic/agent/worker_loop.rb', line 81

def run_task
  if @propagate_errors
    @task.call
  else
    begin
      @task.call
    rescue ServerError => e
      ::NewRelic::Agent.logger.debug "Server Error:", e
    rescue NewRelic::Agent::ForceRestartException, NewRelic::Agent::ForceDisconnectException
      # blow out the loop
      raise
    rescue RuntimeError => e
      # This is probably a server error which has been logged in the server along
      # with your account name.
      ::NewRelic::Agent.logger.error "Error running task in worker loop, likely a server error:", e
    rescue Timeout::Error, NewRelic::Agent::ServerConnectionException
      # Want to ignore these because they are handled already
    rescue SystemExit, NoMemoryError, SignalException
      raise
    rescue => e
      # Don't blow out the stack for anything that hasn't already propagated
      ::NewRelic::Agent.logger.error "Error running task in Agent Worker Loop:", e
    end
  end
end

#schedule_next_invocationObject



52
53
54
55
56
57
58
# File 'lib/new_relic/agent/worker_loop.rb', line 52

def schedule_next_invocation
  now = Time.now
  while @next_invocation_time <= now && @period > 0
    @next_invocation_time += @period
  end
  @next_invocation_time - Time.now
end

#setup(period, task) ⇒ Object

Reset state that is changed by running the worker loop



28
29
30
31
32
33
34
35
36
37
# File 'lib/new_relic/agent/worker_loop.rb', line 28

def setup(period, task)
  @task = task
  @period = period if period
  @should_run = true
  @iterations = 0

  now = Time.now
  @deadline = now + @duration if @duration
  @next_invocation_time = (now + @period)
end

#stopObject

Sets @should_run to false. Returns false



74
75
76
# File 'lib/new_relic/agent/worker_loop.rb', line 74

def stop
  @should_run = false
end

#under_duration?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/new_relic/agent/worker_loop.rb', line 65

def under_duration?
  !@deadline || Time.now < @deadline
end

#under_limit?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/new_relic/agent/worker_loop.rb', line 69

def under_limit?
  @limit.nil? || @iterations < @limit
end