Module: Dynflow::Action::Polling

Defined in:
lib/dynflow/action/polling.rb

Constant Summary collapse

Poll =
Algebrick.atom

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



7
8
9
# File 'lib/dynflow/action/polling.rb', line 7

def self.included(base)
  base.send :include, Action::Timeouts
end

Instance Method Details

#attempts_before_next_intervalObject



68
69
70
# File 'lib/dynflow/action/polling.rb', line 68

def attempts_before_next_interval
  5
end

#done?Boolean

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


32
33
34
# File 'lib/dynflow/action/polling.rb', line 32

def done?
  raise NotImplementedError
end

#external_taskObject

External task data. It should return nil when the task has not been triggered yet.



49
50
51
# File 'lib/dynflow/action/polling.rb', line 49

def external_task
  output[:task]
end

#external_task=(external_task_data) ⇒ Object



53
54
55
# File 'lib/dynflow/action/polling.rb', line 53

def external_task=(external_task_data)
  output[:task] = external_task_data
end

#initiate_external_actionObject



83
84
85
# File 'lib/dynflow/action/polling.rb', line 83

def initiate_external_action
  self.external_task = invoke_external_task
end

#invoke_external_taskObject

Raises:

  • (NotImplementedError)


36
37
38
# File 'lib/dynflow/action/polling.rb', line 36

def invoke_external_task
  raise NotImplementedError
end

#on_finishObject



44
45
# File 'lib/dynflow/action/polling.rb', line 44

def on_finish
end

#poll_attemptsObject



107
108
109
# File 'lib/dynflow/action/polling.rb', line 107

def poll_attempts
  output[:poll_attempts] ||= { total: 0, failed: 0 }
end

#poll_external_taskObject

Raises:

  • (NotImplementedError)


40
41
42
# File 'lib/dynflow/action/polling.rb', line 40

def poll_external_task
  raise NotImplementedError
end

#poll_external_task_with_rescueObject



98
99
100
101
102
103
104
105
# File 'lib/dynflow/action/polling.rb', line 98

def poll_external_task_with_rescue
  poll_attempts[:total] += 1
  self.external_task = poll_external_task
  poll_attempts[:failed] = 0
rescue => error
  poll_attempts[:failed] += 1
  rescue_external_task(error)
end

#poll_intervalObject

Returns the time to wait between two polling intervals.



73
74
75
76
# File 'lib/dynflow/action/polling.rb', line 73

def poll_interval
  interval_level = poll_attempts[:total] / attempts_before_next_interval
  poll_intervals[interval_level] || poll_intervals.last
end

#poll_intervalsObject

What is the trend in waiting for next polling event. It allows to strart with frequent polling, but slow down once it’s clear this task will take some time: the idea is we don’t care that much in finishing few seconds sooner, when the task takes orders of minutes/hours. It allows not overwhelming the backend-servers with useless requests. By default, it switches to next interval after attempts_before_next_interval number of attempts



64
65
66
# File 'lib/dynflow/action/polling.rb', line 64

def poll_intervals
  [0.5, 1, 2, 4, 8, 16]
end

#poll_max_retriesObject

How man times in row should we retry the polling before giving up



79
80
81
# File 'lib/dynflow/action/polling.rb', line 79

def poll_max_retries
  3
end

#rescue_external_task(error) ⇒ Object



111
112
113
114
115
116
117
118
# File 'lib/dynflow/action/polling.rb', line 111

def rescue_external_task(error)
  if poll_attempts[:failed] < poll_max_retries
    action_logger.warn("Polling failed, attempt no. #{poll_attempts[:failed]}, retrying in #{poll_interval}")
    action_logger.warn(error)
  else
    raise error
  end
end

#resume_external_actionObject



87
88
89
90
91
# File 'lib/dynflow/action/polling.rb', line 87

def resume_external_action
  poll_external_task_with_rescue
rescue
  initiate_external_action
end

#run(event = nil) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/dynflow/action/polling.rb', line 13

def run(event = nil)
  case event
  when nil
    if external_task
      resume_external_action
    else
      initiate_external_action
    end
  when Poll
    poll_external_task_with_rescue
  when Action::Timeouts::Timeout
    process_timeout
    suspend
  else
    raise "unrecognized event #{event}"
  end
  done? ? on_finish : suspend_and_ping
end

#suspend_and_pingObject



93
94
95
96
# File 'lib/dynflow/action/polling.rb', line 93

def suspend_and_ping
  plan_event(Poll, poll_interval)
  suspend
end