aws-flow 1.0.8 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -1
  3. data/Rakefile +18 -31
  4. data/aws-flow.gemspec +1 -1
  5. data/lib/aws/decider.rb +1 -2
  6. data/lib/aws/decider/activity.rb +99 -53
  7. data/lib/aws/decider/activity_definition.rb +43 -7
  8. data/lib/aws/decider/async_decider.rb +56 -57
  9. data/lib/aws/decider/async_retrying_executor.rb +4 -5
  10. data/lib/aws/decider/data_converter.rb +2 -2
  11. data/lib/aws/decider/decider.rb +46 -41
  12. data/lib/aws/decider/decision_context.rb +2 -2
  13. data/lib/aws/decider/exceptions.rb +6 -6
  14. data/lib/aws/decider/executor.rb +15 -11
  15. data/lib/aws/decider/flow_defaults.rb +54 -22
  16. data/lib/aws/decider/generic_client.rb +7 -7
  17. data/lib/aws/decider/history_helper.rb +0 -0
  18. data/lib/aws/decider/implementation.rb +5 -5
  19. data/lib/aws/decider/options.rb +285 -155
  20. data/lib/aws/decider/state_machines.rb +10 -10
  21. data/lib/aws/decider/task_handler.rb +5 -5
  22. data/lib/aws/decider/task_poller.rb +152 -15
  23. data/lib/aws/decider/utilities.rb +14 -14
  24. data/lib/aws/decider/version.rb +1 -1
  25. data/lib/aws/decider/worker.rb +21 -20
  26. data/lib/aws/decider/workflow_client.rb +78 -31
  27. data/lib/aws/decider/workflow_clock.rb +1 -1
  28. data/lib/aws/decider/workflow_definition.rb +5 -5
  29. data/lib/aws/decider/workflow_definition_factory.rb +1 -1
  30. data/lib/aws/decider/workflow_enabled.rb +1 -1
  31. data/lib/aws/flow/async_backtrace.rb +19 -18
  32. data/lib/aws/flow/async_scope.rb +32 -16
  33. data/lib/aws/flow/begin_rescue_ensure.rb +61 -56
  34. data/lib/aws/flow/fiber.rb +14 -6
  35. data/lib/aws/flow/flow_utils.rb +9 -6
  36. data/lib/aws/flow/future.rb +43 -18
  37. data/lib/aws/flow/implementation.rb +34 -18
  38. data/lib/aws/flow/simple_dfa.rb +12 -4
  39. data/lib/aws/flow/tasks.rb +120 -86
  40. data/{test/aws → spec/aws/integration}/integration_spec.rb +0 -0
  41. data/{test/aws → spec/aws/unit}/async_backtrace_spec.rb +1 -0
  42. data/{test/aws → spec/aws/unit}/async_scope_spec.rb +0 -0
  43. data/{test/aws → spec/aws/unit}/begin_rescue_ensure_spec.rb +90 -2
  44. data/{test/aws → spec/aws/unit}/decider_spec.rb +41 -53
  45. data/{test/aws → spec/aws/unit}/external_task_spec.rb +0 -0
  46. data/{test/aws → spec/aws/unit}/factories.rb +0 -0
  47. data/{test/aws → spec/aws/unit}/fiber_condition_variable_spec.rb +0 -0
  48. data/{test/aws → spec/aws/unit}/fiber_spec.rb +0 -0
  49. data/{test/aws → spec/aws/unit}/flow_spec.rb +0 -0
  50. data/{test/aws → spec/aws/unit}/future_spec.rb +0 -0
  51. data/{test/aws → spec/aws/unit}/preinclude_tests.rb +0 -0
  52. data/{test/aws → spec/aws/unit}/rubyflow.rb +0 -0
  53. data/{test/aws → spec/aws/unit}/simple_dfa_spec.rb +0 -0
  54. data/{test/aws → spec}/spec_helper.rb +0 -0
  55. metadata +30 -30
@@ -13,33 +13,40 @@
13
13
  # permissions and limitations under the License.
14
14
  ##
15
15
 
16
- # This file contains our implementation of fibers for 1.8
16
+ # This file contains our implementation of fibers for 1.8.
17
17
  module AWS
18
18
  module Flow
19
19
  module Core
20
20
  require 'fiber'
21
+ # @api private
21
22
  class FlowFiber < Fiber
23
+ # @api private
22
24
  def initialize(*args)
23
25
  ObjectSpace.define_finalizer(self, self.class.finalize(self.object_id))
24
26
  super(args)
25
27
  end
28
+ # @api private
26
29
  class << self
27
30
  attr_accessor :local_variables
28
31
  end
29
32
  @local_variables = Hash.new {|hash, key| hash[key] = {}}
33
+ # @api private
30
34
  def self.finalize(obj_id)
31
35
  proc { FlowFiber.local_variables.delete(obj_id) }
32
36
  end
37
+ # @api private
33
38
  def self.[](index)
34
39
  self.local_variables[index]
35
40
  end
41
+ # @api private
36
42
  def self.[]=(key, value)
37
43
  self.local_variables[key] = value
38
44
  end
39
45
 
40
- # Will unset all the values for ancestors of this fiber, assuming that
46
+ # Unsets all the values for ancestors of this fiber, assuming that
41
47
  # they have the same value for key. That is, they will unset upwards until
42
- # the first time the value stored at key is changed
48
+ # the first time the value stored at key is changed.
49
+ # @api private
43
50
  def self.unset(current_fiber, key)
44
51
  current_value = FlowFiber[current_fiber.object_id][key]
45
52
  parent = FlowFiber[current_fiber.object_id][:parent]
@@ -54,8 +61,9 @@ module AWS
54
61
  FlowFiber[current_fiber.object_id].delete(key)
55
62
  end
56
63
 
64
+ # @api private
57
65
  def initialize
58
- # Child fibers should inherit their parents FiberLocals
66
+ # Child fibers should inherit their parents FiberLocals.
59
67
  FlowFiber[Fiber.current.object_id].each_pair do |key, val|
60
68
  FlowFiber[self.object_id][key] = val
61
69
  end
@@ -63,15 +71,15 @@ module AWS
63
71
  super
64
72
  end
65
73
 
74
+ # @api private
66
75
  def [](key)
67
76
  FlowFiber[self.object_id][key]
68
77
  end
78
+ # @api private
69
79
  def []=(key, value)
70
80
  FlowFiber[self.object_id][key] = value
71
81
  end
72
-
73
82
  end
74
-
75
83
  end
76
84
  end
77
85
  end
@@ -17,7 +17,9 @@
17
17
  module AWS
18
18
  module Flow
19
19
  module Core
20
+ # @api private
20
21
  class IllegalStateException < Exception; end
22
+ # @api private
21
23
  class CancellationException < Exception
22
24
  attr_accessor :reason, :details
23
25
  def initialize(reason = nil, details = nil)
@@ -26,14 +28,15 @@ module AWS
26
28
  end
27
29
  end
28
30
 
31
+ # @api private
29
32
  def make_backtrace(parent_backtrace)
30
- # 1 frame for the function that actually removes the stack traces
33
+ # 1 frame for the function that actually removes the stack traces.
31
34
  # 1 frame for the function that calls into the function that removes
32
- # frames in AsyncBacktrace
33
- # 1 frame for the call into this function
34
- # 1 frame for the initialize call of the BRE or External Task
35
- # 1 frame for the new call into the BRE or ET
36
- # 1 frame for the AsyncScope initialize that the BRE/ET has to be in
35
+ # frames in AsyncBacktrace.
36
+ # 1 frame for the call into this function.
37
+ # 1 frame for the initialize call of the BeginRescueEnsure or ExternalTask.
38
+ # 1 frame for the new call into the BeginRescueEnsure or ExternalTask.
39
+ # 1 frame for the AsyncScope initialize that the BeginRescueEnsure/ExternalTask has to be in.
37
40
 
38
41
  # "./lib/aws/rubyflow/asyncBacktrace.rb:75:in `caller'"
39
42
  # "./lib/aws/rubyflow/asyncBacktrace.rb:21:in `create'"
@@ -20,17 +20,23 @@ module AWS
20
20
  module Core
21
21
  class AlreadySetException < Exception; end
22
22
 
23
- # A Future represents the result of an asynchronous computation. Methods are
24
- # provided to check if the computation is complete(Future#set), to wait for
25
- # its completion(Future#wait), and to retrieve the result of the
26
- # computation(Future#get). The result can only be retrieved using method get
27
- # when the computation has completed, blocking if necessary until it is
28
- # ready. This is okay, however, because it will block that Fiber, and
29
- # another Fiber will start executing
23
+ # Represents the result of an asynchronous computation. Methods are
24
+ # provided to:
25
+ #
26
+ # * retrieve the result of the computation, once it is complete ({Future#get}).
27
+ # * check if the computation is complete ({Future#set?})
28
+ # * execute a block when computation is complete ({Future#on_set})
29
+ #
30
+ # The result of a Future can only be retrieved when the computation has
31
+ # completed. {Future#get} blocks execution, if necessary, until the
32
+ # Future is ready. This is okay: because it will block that fiber,
33
+ # another fiber will start executing.
34
+ #
30
35
  class Future
31
36
 
32
- # Sets the value of the future, and notifies all of the Fibers that tried
33
- # to get when this future wasn't ready.
37
+ # Sets the value of the {Future}, and notifies all of the fibers that
38
+ # tried to call {#get} when this future wasn't ready.
39
+ # @api private
34
40
  def set(result=nil)
35
41
  raise AlreadySetException if @set
36
42
  @set = true
@@ -40,14 +46,21 @@ module AWS
40
46
  self
41
47
  end
42
48
 
43
- # determines whether the object is a flow future. The contract is that
44
- # flow futures must have a #get method.
49
+ # Is the object is an AWS Flow future? AWS Flow futures *must* have a
50
+ # {#get} method.
51
+ # @api private
45
52
  def is_flow_future?
46
53
  true
47
54
  end
48
55
 
49
- # Blocks if Future is not set
50
- # raises CancellationError when task is cancelled
56
+ # Blocks if future is not set. Returns the result of the future once
57
+ # {#set} is true.
58
+ #
59
+ # @return
60
+ # The result of the future.
61
+ #
62
+ # @raise CancellationError
63
+ # when the task is cancelled.
51
64
  def get
52
65
  until @set
53
66
  @conditional ||= FiberConditionVariable.new
@@ -56,16 +69,22 @@ module AWS
56
69
  @result
57
70
  end
58
71
 
72
+ # @return
73
+ # true if the {Future} has been set.
59
74
  def set?
60
75
  @set
61
76
  end
62
77
 
78
+ # Unsets the future.
79
+ #
80
+ # @api private
63
81
  def unset
64
82
  @set = nil
65
83
  @result = nil
66
84
  end
67
85
 
68
- # Add a callback, block, which will fire when the future is set
86
+ # Adds a callback, passed in as a block, which will fire when the future
87
+ # is set.
69
88
  def on_set(&block)
70
89
  @listeners ||= []
71
90
  # TODO probably want to use lambda here
@@ -73,19 +92,23 @@ module AWS
73
92
  end
74
93
  end
75
94
 
76
- # Based on the ruby core source:
95
+ # Represents a fiber condition variable.
96
+ # Based on the Ruby core source:
77
97
  # https://github.com/ruby/ruby/blob/trunk/lib/thread.rb
98
+ # @api private
78
99
  class FiberConditionVariable
79
100
  #
80
101
  # Creates a new ConditionVariable
81
102
  #
103
+ # @api private
82
104
  def initialize
83
105
  @waiters = []
84
106
  end
85
107
 
86
-
87
- # Have the current fiber wait on this condition variable, and wake up when
88
- # the FiberConditionVariable is signalled/broadcaster
108
+ # Have the current fiber wait on this condition variable, and wake up
109
+ # when the FiberConditionVariable is signaled/broadcasted.
110
+ #
111
+ # @api private
89
112
  def wait
90
113
  fiber = ::Fiber.current
91
114
  @waiters << fiber
@@ -96,6 +119,7 @@ module AWS
96
119
  #
97
120
  # Wakes up the first fiber in line waiting for this lock.
98
121
  #
122
+ # @api private
99
123
  def signal
100
124
  t = @waiters.shift
101
125
  t.schedule if t && t.alive?
@@ -105,6 +129,7 @@ module AWS
105
129
  #
106
130
  # Wakes up all fibers waiting for this lock.
107
131
  #
132
+ # @api private
108
133
  def broadcast
109
134
  signal until @waiters.empty?
110
135
  self
@@ -13,17 +13,22 @@
13
13
  # permissions and limitations under the License.
14
14
  #++
15
15
 
16
- # This file contains the externally visible parts of flow that are expected to be used by customers of flow
16
+ # This file contains the externally visible parts of flow that are expected to be used by customers of flow.
17
17
  module AWS
18
18
  module Flow
19
19
  module Core
20
+
21
+ # A basic exception class with no context.
20
22
  class NoContextException < Exception; end
21
23
 
24
+ # @param [Future] future
25
+ # Unused; defaults to **nil**.
26
+ #
22
27
  # @param block
23
28
  # The block of code to be executed when the task is run.
24
29
  #
25
30
  # @raise [NoContextException]
26
- # If the current fiber does not respond to {#__context__}.
31
+ # If the current fiber does not respond to `Fiber.__context__`.
27
32
  #
28
33
  # @return [Future]
29
34
  # The tasks result, which is a {Future}.
@@ -46,7 +51,7 @@ module AWS
46
51
  # The tasks result, which is a {Future}.
47
52
  #
48
53
  # @raise [NoContextException]
49
- # If the current fiber does not respond to {#__context__}.
54
+ # If the current fiber does not respond to `Fiber.__context__`.
50
55
  #
51
56
  def daemon_task(&block)
52
57
  fiber = ::Fiber.current
@@ -65,7 +70,7 @@ module AWS
65
70
  # @return [nil]
66
71
  #
67
72
  # @raise [NoContextException]
68
- # If the current fiber does not respond to {#__context__}.
73
+ # If the current fiber does not respond to `Fiber.__context__`.
69
74
  #
70
75
  def external_task(&block)
71
76
  fiber = ::Fiber.current
@@ -77,15 +82,17 @@ module AWS
77
82
  nil
78
83
  end
79
84
 
80
-
85
+ # Creates a new error handler for asynchronous tasks.
86
+ #
87
+ # @param block
88
+ # A block that defines the {BeginRescueEnsure#begin}, {BeginRescueEnsure#rescue}, and {BeginRescueEnsure#ensure}
89
+ # methods.
81
90
  #
91
+ # @return
92
+ # The result of the `begin` statement if there is no error; otherwise the value of the `return` statement.
82
93
  #
83
- # * *Args* :
84
- # - block -> a block, which is passed in a BeginRescueEnsureWrapper, and which will define the BeginRescueEnsure#begin, BeginRescueEnsure#rescue, and BeginRescueEnsure#ensure methods
85
- # * *Returns* :
86
- # - The result of the begin statement, if there is no error, otherwise the value of the return statement
87
- # * *Raises* :
88
- # - +NoContextException+ -> If the current fiber does not respond to #__context__
94
+ # @raise [NoContextException]
95
+ # If the current fiber does not respond to `Fiber.__context__`.
89
96
  #
90
97
  def error_handler(&block)
91
98
  fiber = ::Fiber.current
@@ -98,15 +105,24 @@ module AWS
98
105
  begin_rescue_ensure
99
106
  end
100
107
 
101
- # @param block
102
- # A code block, which is passed within a {BeginRescueEnsureWrapper}, and which must define the
103
- # {BeginRescueEnsure#begin}, {BeginRescueEnsure#rescue}, and {BeginRescueEnsure#ensure} methods.
104
- # @!visibility private
108
+ # @api private
109
+ #
105
110
  def _error_handler(&block)
106
111
  error_handler(&block).result
107
112
  end
108
113
 
109
114
 
115
+ # Waits for the passed-in function to complete, setting values for the provided futures when it does.
116
+ #
117
+ # @param function
118
+ # The function to wait for.
119
+ #
120
+ # @param [Array<Future>] futures
121
+ # A list of futures to provide values for when the function completes.
122
+ #
123
+ # @return [Array<Future>]
124
+ # A list of the set futures, in the order of being set.
125
+ #
110
126
  def wait_for_function(function, *futures)
111
127
  conditional = FiberConditionVariable.new
112
128
  futures.flatten!
@@ -125,10 +141,10 @@ module AWS
125
141
 
126
142
  # Blocks until *any* of the arguments are set.
127
143
  #
128
- # @param [Array] futures
144
+ # @param [Array<Future>] futures
129
145
  # A list of futures to wait for. The function will return when at least one of these is set.
130
146
  #
131
- # @return [Array]
147
+ # @return [Array<Future>]
132
148
  # A list of the set futures, in the order of being set.
133
149
  #
134
150
  def wait_for_any(*futures)
@@ -140,7 +156,7 @@ module AWS
140
156
  # @param [Array<Future>] futures
141
157
  # A list of futures to wait for. The function will return only when all of them are set.
142
158
  #
143
- # @return [Array]
159
+ # @return [Array<Future>]
144
160
  # A list of the set futures, in the order of being set.
145
161
  #
146
162
  def wait_for_all(*futures)
@@ -17,16 +17,18 @@ module AWS
17
17
  module Flow
18
18
  module Core
19
19
 
20
- # Contains a Data Flow Analysis (DFA)-like framework, where transition functions can perform arbitrary computation
21
- # before moving to the next state
20
+ # Contains a data flow analysis (DFA)-like framework, where transition functions can perform arbitrary computation
21
+ # before moving to the next state.
22
+ # @api private
22
23
  module SimpleDFA
23
24
  attr_accessor :transitions, :symbols, :states, :start_state
24
25
 
25
- # Creates a new SimpleDFA instance.
26
+ # Creates a new `SimpleDFA` instance.
26
27
  #
27
28
  # @param start_state
28
29
  # The state with which to start the framework.
29
30
  #
31
+ # @api private
30
32
  def init(start_state)
31
33
  include InstanceMethods
32
34
  @start_state = start_state
@@ -39,6 +41,7 @@ module AWS
39
41
  # @return the start state
40
42
  # The start state that was provided when this instance was created.
41
43
  #
44
+ # @api private
42
45
  def get_start_state
43
46
  @start_state
44
47
  end
@@ -46,10 +49,12 @@ module AWS
46
49
  # @return [Array]
47
50
  # The list of all transitions that were added with {#add_transition}.
48
51
  #
52
+ # @api private
49
53
  def get_transitions
50
54
  @transitions
51
55
  end
52
56
 
57
+ # @api private
53
58
  def define_general(state, &block)
54
59
  @symbols.each do |symbol|
55
60
  if @transitions[[state, symbol]].nil?
@@ -58,19 +63,23 @@ module AWS
58
63
  end
59
64
  end
60
65
 
66
+ # @api private
61
67
  def add_transition(state, symbol, &block)
62
68
  @symbols << symbol unless @symbols.include? symbol
63
69
  @states << state unless @states.include? state
64
70
  @transitions[[state, symbol]] = block
65
71
  end
66
72
 
73
+ # @api private
67
74
  def uncovered_transitions
68
75
  @states.product(@symbols) - @transitions.keys
69
76
  end
70
77
 
78
+ # @api private
71
79
  module InstanceMethods
72
80
  attr_accessor :current_state
73
81
 
82
+ # @api private
74
83
  def consume(symbol)
75
84
  @current_state ||= self.class.get_start_state
76
85
  func_to_call = self.class.get_transitions[[@current_state, symbol]]
@@ -79,7 +88,6 @@ module AWS
79
88
  end
80
89
  end
81
90
  end
82
-
83
91
  end
84
92
  end
85
93
  end
@@ -13,37 +13,48 @@
13
13
  # permissions and limitations under the License.
14
14
  ##
15
15
 
16
- # Contains all the task methods, which allow arbitrary blocks of code to be run asynchronously
16
+ # Contains all the task methods, which allow arbitrary blocks of code to be run asynchronously.
17
17
 
18
18
  module AWS
19
19
  module Flow
20
20
  module Core
21
+ # @api private
21
22
  class Task < FlowFiber
22
23
  attr_reader :result, :block
23
24
  attr_accessor :backtrace, :__context__, :parent
24
25
 
25
- # Creates a new Task.
26
+ # Creates a new task.
26
27
  #
27
28
  # @param __context__
28
- # A Task needs a reference to the __context__ that created it so that when the "task" macro is called it can
29
- # find the __context__ which the new Task should be added to.
29
+ # A task needs a reference to the __context__ that created it so that when the "task" macro is called it can
30
+ # find the __context__, which the new task should be added to.
30
31
  #
31
32
  # @param block
32
33
  # A block of code that will be run by the task.
33
34
  #
35
+ # @api private
34
36
  def initialize(__context__, &block)
35
37
  @__context__ = __context__
36
38
  @result = Future.new
37
39
  @block = block
38
40
 
39
41
  # Is the task alive?
42
+ #
43
+ # @return Boolean
44
+ # true if the task is alive and has not been canceled.
45
+ #
46
+ # @api private
40
47
  def alive?
41
48
  super && !@cancelled
42
49
  #!!@alive# && !@cancelled
43
50
  end
44
51
 
52
+ # Retrieves the executor for this task.
53
+ #
45
54
  # @return
46
55
  # The executor for this task.
56
+ #
57
+ # @api private
47
58
  def executor
48
59
  @__context__.executor
49
60
  end
@@ -51,7 +62,7 @@ module AWS
51
62
  super() do
52
63
  begin
53
64
  # Not return because 1.9 will freak about local jump problems if you
54
- # try to return, as this is inside a block
65
+ # try to return, as this is inside a block.
55
66
  next if @cancelled
56
67
  @result.set(lambda(&block).call)
57
68
  next if @cancelled
@@ -68,32 +79,37 @@ module AWS
68
79
  end
69
80
 
70
81
  #
71
- # Passes the get_heirs calls to the context, to ensure uniform handling of get_heirs
82
+ # Passes all `get_heirs` calls to the class that is holding the context,
83
+ # to ensure uniform handling of `get_heirs`.
72
84
  #
85
+ # @api private
73
86
  def get_heirs
74
87
  @__context__.get_heirs
75
88
  end
76
89
 
90
+ # Will always be false. Provides a common API for BeginRescueEnsure to
91
+ # ensure they are maintaining their nonDaemonHeirsCount correctly.
77
92
  #
78
- # Returns true/false, depending on if we are in a daemon task or not
79
- #
93
+ # @api private
80
94
  def is_daemon?
81
95
  return false
82
96
  end
83
97
 
84
- # Used by Future#signal to schedule the task for re-evaluation.
98
+ # Used by {Future#signal} to schedule the task for re-evaluation.
85
99
  #
86
100
  # This will simply add the task back to the list of things to be run in the parent's event loop.
87
101
  #
102
+ # @api private
88
103
  def schedule
89
104
  @__context__ << self
90
105
  end
91
106
 
92
- # Cancel will prevent the execution of this particular task, if possible
107
+ # Prevents the execution of this particular task, if possible.
93
108
  #
94
109
  # @param error
95
- # The error that is the cause of the cancellation
110
+ # The error that is the cause of the cancellation.
96
111
  #
112
+ # @api private
97
113
  def cancel(error)
98
114
  @cancelled = true
99
115
  @__context__.remove(self)
@@ -102,9 +118,9 @@ module AWS
102
118
  # Fails the given task with the specified error.
103
119
  #
104
120
  # @param error
105
- # The error that is the cause of the cancellation
121
+ # The error that is the cause of the failure.
106
122
  #
107
- # @!visibility private
123
+ # @api private
108
124
  def fail(this_task, error)
109
125
  @__context__.fail(this_task, error)
110
126
  end
@@ -112,73 +128,80 @@ module AWS
112
128
  # raise error
113
129
  # end
114
130
 
115
- # Adds a task to this task's context
131
+ # Adds a task to this task's context.
116
132
  #
117
133
  # @param this_task
118
134
  # The task to add.
119
135
  #
136
+ # @api private
120
137
  def <<(this_task)
121
138
  @__context__.parent << this_task
122
139
  end
123
140
 
124
- # Removes a task from this task's context
141
+ # Removes a task from this task's context.
125
142
  #
126
143
  # @param this_task
127
144
  # The task to remove.
128
145
  #
146
+ # @api private
129
147
  def remove(this_task)
130
148
  @__context__.remove(this_task)
131
149
  end
132
-
133
-
134
150
  end
135
151
 
136
-
137
- # Similar to a regular Task in all functioning except that it is not assured a chance to execute. Whereas a
138
- # begin/run/execute block cannot be closed out while there are still nonDaemonHeirs, it can happily entered the
139
- # closed state with daemon heirs, making them essentially unrunnable.
152
+ # Represents a task that might not execute. Similar to a regular task in
153
+ # all functions except that it is not assured a chance to execute. Whereas
154
+ # a begin/run/execute block cannot be closed while there are still
155
+ # `nonDaemonHeirs`, a DaemonTask can enter the closed state with daemon
156
+ # heirs, making them essentially unrunnable.
157
+ #
158
+ # @api private
140
159
  class DaemonTask < Task
141
-
160
+ # @api private
142
161
  def is_daemon?
143
162
  return true
144
163
  end
145
-
146
164
  end
147
165
 
148
- # External Tasks are used to bridge asynchronous execution to external asynchronous APIs or events. It is passed a block, like so
166
+ # Used to bridge asynchronous execution to external asynchronous APIs or
167
+ # events. It is passed a block, like so:
149
168
  #
150
169
  # external_task do |t|
151
170
  # t.cancellation_handler { |h, cause| h.fail(cause) }
152
171
  # t.initiate_task { |h| trace << :task_started; h.complete; }
153
172
  # end
154
173
  #
155
- # The {ExternalTask#initiate_task} method is expected to call an external API and return without blocking.
156
- # Completion or failure of the external task is reported through ExternalTaskCompletionHandle, which is passed into
157
- # the initiate_task and cancellation_handler blocks. The cancellation handler, defined in the same block as the
158
- # initiate_task, is used to report the cancellation of the external task.
174
+ # The {ExternalTask#initiate_task} method is expected to call an external
175
+ # API and return without blocking. Completion or failure of the external
176
+ # task is reported through ExternalTaskCompletionHandle, which is passed
177
+ # into the initiate_task and cancellation_handler blocks. The cancellation
178
+ # handler, defined in the same block as the initiate_task, is used to
179
+ # report the cancellation of the external task.
159
180
  #
181
+ # @api private
160
182
  class ExternalTask < FlowFiber
161
183
  attr_reader :block
162
184
  attr_accessor :cancelled, :inCancellationHandler, :parent, :backtrace, :__context__
163
185
 
164
186
 
165
- # Will always be false, provides a common api for BRE's to ensure they are maintaining their nonDaemonHeirsCount
166
- # correctly
167
- # @!visibility private
187
+ # Will always be false, provides a common API for BeginRescueEnsure's to
188
+ # ensure they are maintaining their nonDaemonHeirsCount correctly.
189
+ #
190
+ # @api private
168
191
  def is_daemon?
169
192
  false
170
193
  end
171
194
 
172
195
  #
173
- # Passes the get_heirs calls to the context, to ensure uniform handling of
174
- # get_heirs
196
+ # Passes the get_heirs calls to the context, to ensure uniform handling
197
+ # of get_heirs
175
198
  #
176
- # @!visibility private
199
+ # @api private
177
200
  def get_heirs
178
201
  @__context__.get_heirs
179
202
  end
180
203
 
181
- # @!visibility private
204
+ # @api private
182
205
  def initialize(options = {}, &block)
183
206
  @inCancellationHandler = false
184
207
  @block = block
@@ -188,43 +211,47 @@ module AWS
188
211
  block.call(self)
189
212
  end
190
213
 
191
- # This method is here because the way we create ExternalTasks is a little
192
- # tricky - if the parent isn't passed in on construction(as is the case with
193
- # the external_task function), then the parent will only be set after
194
- # ExternalTask#initialize is called. We'd prefer to set it in the initiailze,
195
- # however, the backtrace relies on the parent's backtrace, and so we cannot do
196
- # that. Instead, we use this method to lazily create it, when it is
197
- # called. The method itself simply sets the backtrace to the the
198
- # make_backtrace of the parent's backtrace, if the backtrace is not already
199
- # set, and will otherwise simply return the backtrace
200
- # @!visibility private
214
+ # This method is here because the way we create external tasks is a
215
+ # little tricky. If the parent isn't passed in on construction(as is the
216
+ # case with the external_task function), then the parent will only be
217
+ # set after ExternalTask#initialize is called. We'd prefer to set it in
218
+ # initialize, however, the backtrace relies on the parent's backtrace,
219
+ # and so we cannot do that. Instead, we use this method to lazily create
220
+ # it when it is called. The method itself simply sets the backtrace to
221
+ # the make_backtrace of the parent's backtrace, if the backtrace is not
222
+ # already set, and will otherwise simply return the backtrace
223
+ #
224
+ # @api private
201
225
  def backtrace
202
226
  @backtrace ||= make_backtrace(@parent.backtrace)
203
227
  end
204
228
 
205
- # Add a task which removes yourself, and pass it through the parents executor
206
- # @!visibility private
229
+ # Add a task that removes yourself, and pass it through the parents executor.
230
+ #
231
+ # @api private
207
232
  def remove_from_parent
208
233
  @__context__.executor << FlowFiber.new { @parent.remove(self) }
209
234
  end
210
235
 
211
- # Add a task which fails yourself with the suppiled error, and pass it through
212
- # the parents executor
213
- # @!visibility private
236
+ # Add a task that fails yourself with the suppiled error, and pass it
237
+ # through the parents executor.
238
+ #
239
+ # @api private
214
240
  def fail_to_parent(error)
215
241
  @__context__.executor << FlowFiber.new { @parent.fail(self, error) }
216
242
  end
217
243
 
218
244
 
219
- # Part of the interface provided by Fiber, has to overridden to properly
220
- # reflect that an ExternalTasks alive-ness relies on it's
221
- # ExternalTaskCompletionHandle
222
- # @!visibility private
245
+ # Part of the interface provided by fiber, has to overridden to properly
246
+ # reflect that an external tasks alive-ness relies on its
247
+ # ExternalTaskCompletionHandle.
248
+ #
249
+ # @api private
223
250
  def alive?
224
251
  ! @handle.completed
225
252
  end
226
253
 
227
- # @!visibility private
254
+ # @api private
228
255
  def cancel(cause)
229
256
  return if @cancelled
230
257
  return if @handle.failure != nil || @handle.completed
@@ -252,20 +279,23 @@ module AWS
252
279
  end
253
280
  end
254
281
 
255
- # Store the cancellation handler block passed in for later reference
256
- # @!visibility private
282
+ # Store the passed-in cancellation handler block for later reference.
283
+ #
284
+ # @api private
257
285
  def cancellation_handler(&block)
258
286
  @cancellation_task = lambda { |cause| block.call(@handle, cause) }
259
287
  end
260
288
 
261
- # Store the block passed in for later
262
- # @!visibility private
289
+ # Store the passed-in block for later.
290
+ #
291
+ # @api private
263
292
  def initiate_task(&block)
264
293
  @initiation_task = lambda { block.call(@handle) }
265
294
  end
266
295
 
267
- # From the interface provided by Fiber, will execute the External Task
268
- # @!visibility private
296
+ # From the interface provided by fiber, will execute the external task.
297
+ #
298
+ # @api private
269
299
  def resume
270
300
  return if @cancelled
271
301
  begin
@@ -279,27 +309,28 @@ module AWS
279
309
  end
280
310
 
281
311
  # Used to complete or fail an external task initiated through
282
- # ExternalTask#initiate_task, and thus handles the logic of what to do when the
283
- # external task is failed.
284
- # @!visibility private
312
+ # ExternalTask#initiate_task, and thus handles the logic of what to do
313
+ # when the external task is failed.
314
+ #
315
+ # @api private
285
316
  class ExternalTaskCompletionHandle
286
317
  attr_accessor :completed, :failure, :external_task
287
318
 
288
- # @!visibility private
319
+ # @api private
289
320
  def initialize(external_task)
290
321
  @external_task = external_task
291
322
  end
292
323
 
293
- # Will merge the backtrace, set the @failure, and then fail the task from the parent
294
- # @!visibility private
324
+ # Merges the backtrace, sets the @failure, and then fails the task from
325
+ # the parent.
295
326
  #
296
327
  # @param error
297
- # The exception to fail on
328
+ # The exception to fail on.
298
329
  #
299
330
  # @raise IllegalStateException
300
- # Raises if failure hasn't been set, or if the task is already completed
331
+ # Raises if failure hasn't been set, or if the task is already completed.
301
332
  #
302
- # @!visibility private
333
+ # @api private
303
334
  def fail(error)
304
335
  if ! @failure.nil?
305
336
  raise IllegalStateException, "Invalid ExternalTaskCompletionHandle"
@@ -320,12 +351,12 @@ module AWS
320
351
  end
321
352
  end
322
353
 
323
- # Set's the task to complete, and removes it from it's parent
354
+ # Sets the task to complete, and removes it from its parent.
324
355
  #
325
356
  # @raise IllegalStateException
326
- # If the failure hasn't been set, or if the task is already completed
357
+ # If the failure hasn't been set, or if the task is already completed.
327
358
  #
328
- # @!visibility private
359
+ # @api private
329
360
  def complete
330
361
  if ! failure.nil?
331
362
  raise IllegalStateException, ""
@@ -339,15 +370,19 @@ module AWS
339
370
  end
340
371
  end
341
372
 
342
- # TaskContext is the class that holds some meta-information for tasks, and which stores the parent link for tasks.
343
- # It seperates some of the concerns between tasks and what they have to know to follow back up the chain.
373
+ # Holds some metadata for tasks and stores the parent link for tasks. It
374
+ # separates some of the concerns between tasks and what they have to know
375
+ # to follow back up the chain.
344
376
  #
345
- # All the methods here will simply delegate calls, either up to the parent, or down to the task
346
- # @!visibility private
377
+ # All the methods here will simply delegate calls, either up to the
378
+ # parent, or down to the task.
379
+ #
380
+ # @api private
347
381
  class TaskContext
348
382
 
349
383
  attr_accessor :daemon, :parent, :backtrace, :cancelled
350
384
 
385
+ # @api private
351
386
  def initialize(options = {})
352
387
  @parent = options[:parent]
353
388
  @task = options[:task]
@@ -356,49 +391,48 @@ module AWS
356
391
  @daemon = options[:daemon]
357
392
  end
358
393
 
359
- # @!visibility private
394
+ # @api private
360
395
  def get_closest_containing_scope
361
396
  @task
362
397
  # @ parent
363
398
  end
364
399
 
365
- # @!visibility private
400
+ # @api private
366
401
  def alive?
367
402
  @task.alive?
368
403
  end
369
404
 
370
- # @!visibility private
405
+ # @api private
371
406
  def executor
372
407
  @parent.executor
373
408
  end
374
409
 
375
- # @!visibility private
410
+ # @api private
376
411
  def get_heirs
377
412
  str = "I am a #{@task.class}
378
413
  and my block looks like #{@task.block}"
379
414
  end
380
415
 
381
- # @!visibility private
416
+ # @api private
382
417
  def fail(this_task, error)
383
418
  @parent.fail(this_task, error)
384
419
  end
385
420
 
386
- # @!visibility private
421
+ # @api private
387
422
  def remove(thread)
388
423
  @parent.remove(thread)
389
424
  end
390
425
 
391
- # @!visibility private
426
+ # @api private
392
427
  def cancel(error_type)
393
428
  @task.cancelled = true
394
429
  @parent.cancel(self)
395
430
  end
396
431
 
397
- # @!visibility private
432
+ # @api private
398
433
  def <<(task)
399
434
  @parent << task
400
435
  end
401
-
402
436
  end
403
437
  end
404
438
  end