Module: Dynflow::Action::Polling

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

Constant Summary collapse

Poll =
Algebrick.atom

Instance Method Summary collapse

Instance Method Details

#attempts_before_next_intervalObject



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

def attempts_before_next_interval
  5
end

#done?Boolean

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


21
22
23
# File 'lib/dynflow/action/polling.rb', line 21

def done?
  raise NotImplementedError
end

#external_taskObject

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



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

def external_task
  output[:task]
end

#external_task=(external_task_data) ⇒ Object



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

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

#initiate_external_actionObject



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

def initiate_external_action
  self.external_task = invoke_external_task
  suspend_and_ping unless done?
end

#invoke_external_taskObject

Raises:

  • (NotImplementedError)


25
26
27
# File 'lib/dynflow/action/polling.rb', line 25

def invoke_external_task
  raise NotImplementedError
end

#poll_attemptsObject



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

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

#poll_external_taskObject

Raises:

  • (NotImplementedError)


29
30
31
# File 'lib/dynflow/action/polling.rb', line 29

def poll_external_task
  raise NotImplementedError
end

#poll_external_task_with_rescueObject



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

def poll_external_task_with_rescue
  poll_attempts[:total] += 1
  self.external_task = poll_external_task
  poll_attempts[:failed] = 0
  suspend_and_ping unless done?
rescue => error
  poll_attempts[:failed] += 1
  rescue_poll_external_task(error)
end

#poll_intervalObject

Returns the time to wait between two polling intervals.



59
60
61
62
# File 'lib/dynflow/action/polling.rb', line 59

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



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

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



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

def poll_max_retries
  3
end

#rescue_poll_external_task(error) ⇒ Object



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

def rescue_poll_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)
    suspend_and_ping
  else
    raise error
  end
end

#resume_external_actionObject



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

def resume_external_action
  poll_external_task_with_rescue
rescue
  initiate_external_action
end

#run(event = nil) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/dynflow/action/polling.rb', line 6

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
  else
    raise "unrecognized event #{event}"
  end
end

#suspend_and_pingObject



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

def suspend_and_ping
  suspend { |suspended_action| world.clock.ping suspended_action, poll_interval, Poll }
end