simpler_workflow 0.2.7 → 0.3.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/.travis.yml +1 -3
- data/lib/simpler_workflow.rb +1 -6
- data/lib/simpler_workflow/activity.rb +59 -32
- data/lib/simpler_workflow/activity_registry.rb +95 -0
- data/lib/simpler_workflow/domain.rb +25 -13
- data/lib/simpler_workflow/version.rb +1 -1
- data/lib/simpler_workflow/workflow.rb +130 -99
- data/simpler_workflow.gemspec +7 -1
- data/spec/activity_spec.rb +132 -0
- data/spec/spec_helper.rb +9 -2
- data/spec/workflow_spec.rb +245 -0
- metadata +87 -25
- data/lib/simpler_workflow/workflow_collection.rb +0 -16
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/lib/simpler_workflow.rb
CHANGED
@@ -54,12 +54,7 @@ module SimplerWorkflow
|
|
54
54
|
autoload :Domain, 'simpler_workflow/domain'
|
55
55
|
autoload :Workflow, 'simpler_workflow/workflow'
|
56
56
|
autoload :Activity, 'simpler_workflow/activity'
|
57
|
+
autoload :ActivityRegistry, 'simpler_workflow/activity_registry'
|
57
58
|
autoload :OptionsAsMethods, 'simpler_workflow/options_as_methods'
|
58
59
|
autoload :DefaultExceptionReporter, 'simpler_workflow/default_exception_reporter'
|
59
60
|
end
|
60
|
-
|
61
|
-
class Map
|
62
|
-
def Map.from_json(json)
|
63
|
-
from_hash(JSON.parse(json))
|
64
|
-
end
|
65
|
-
end
|
@@ -2,30 +2,27 @@ module SimplerWorkflow
|
|
2
2
|
class Activity
|
3
3
|
include OptionsAsMethods
|
4
4
|
|
5
|
+
DEFAULT_OPTIONS = {
|
6
|
+
:default_task_list => name,
|
7
|
+
:default_task_start_to_close_timeout => 5 * 60,
|
8
|
+
:default_task_schedule_to_start_timeout => 5 * 60,
|
9
|
+
:default_task_schedule_to_close_timeout => 10 * 60,
|
10
|
+
:default_task_heartbeat_timeout => :none
|
11
|
+
}
|
12
|
+
|
5
13
|
attr_reader :domain, :name, :version, :options, :next_activity
|
6
14
|
|
7
|
-
def initialize(domain, name, version
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
:default_task_schedule_to_close_timeout => 10 * 60,
|
14
|
-
:default_task_heartbeat_timeout => :none
|
15
|
-
}
|
16
|
-
@options = default_options.merge(options)
|
17
|
-
@domain = domain
|
18
|
-
@name = name
|
19
|
-
@version = version
|
20
|
-
@failure_policy = :fail
|
21
|
-
self
|
22
|
-
end
|
15
|
+
def initialize(domain, name, version)
|
16
|
+
@options = DEFAULT_OPTIONS.dup
|
17
|
+
@domain = domain
|
18
|
+
@name = name
|
19
|
+
@version = version
|
20
|
+
@failure_policy = :fail
|
23
21
|
end
|
24
22
|
|
25
23
|
def on_success(activity, version = nil)
|
26
24
|
case activity
|
27
25
|
when Hash
|
28
|
-
activity.symbolize_keys!
|
29
26
|
name = activity[:name].to_sym
|
30
27
|
version = activity[:version]
|
31
28
|
when String
|
@@ -33,7 +30,8 @@ module SimplerWorkflow
|
|
33
30
|
when Symbol
|
34
31
|
name = activity
|
35
32
|
end
|
36
|
-
|
33
|
+
|
34
|
+
@next_activity = Activity[domain, name, version]
|
37
35
|
end
|
38
36
|
|
39
37
|
def on_fail(failure_policy)
|
@@ -48,6 +46,10 @@ module SimplerWorkflow
|
|
48
46
|
@perform_task = block
|
49
47
|
end
|
50
48
|
|
49
|
+
def name
|
50
|
+
@name.to_s
|
51
|
+
end
|
52
|
+
|
51
53
|
def perform_task(task)
|
52
54
|
logger.info("Performing task #{name}")
|
53
55
|
@perform_task.call(task)
|
@@ -61,7 +63,31 @@ module SimplerWorkflow
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def to_activity_type
|
64
|
-
domain.activity_types[name
|
66
|
+
domain.activity_types[name, version]
|
67
|
+
end
|
68
|
+
|
69
|
+
def persist_attributes
|
70
|
+
activities.persist_attributes(self)
|
71
|
+
end
|
72
|
+
|
73
|
+
def simple_db_attributes
|
74
|
+
attributes = {
|
75
|
+
domain: domain.name,
|
76
|
+
name: name,
|
77
|
+
version: version,
|
78
|
+
failure_policy: failure_policy
|
79
|
+
}
|
80
|
+
|
81
|
+
if (next_activity)
|
82
|
+
attributes[:next_activity_name] = next_activity.name
|
83
|
+
attributes[:next_activity_version] = next_activity.version
|
84
|
+
end
|
85
|
+
|
86
|
+
attributes
|
87
|
+
end
|
88
|
+
|
89
|
+
def simple_db_name
|
90
|
+
"#{name}-#{version}"
|
65
91
|
end
|
66
92
|
|
67
93
|
def start_activity_loop
|
@@ -129,25 +155,26 @@ module SimplerWorkflow
|
|
129
155
|
domain.activity_tasks.count(name).to_i
|
130
156
|
end
|
131
157
|
|
132
|
-
def self.[](
|
133
|
-
|
134
|
-
when String
|
135
|
-
name = name.to_sym
|
136
|
-
when Hash
|
137
|
-
name.symbolize_keys!
|
138
|
-
version = name[:version]
|
139
|
-
name = name[:name]
|
140
|
-
end
|
141
|
-
activities[[name, version]]
|
158
|
+
def self.[](*activity_tuple)
|
159
|
+
activities[*activity_tuple]
|
142
160
|
end
|
143
161
|
|
144
|
-
def self.
|
145
|
-
activities[
|
162
|
+
def self.[]=(*activity_tuple)
|
163
|
+
activities.[]=(*activity_tuple)
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.register(domain, name, version, activity)
|
167
|
+
activities.register(domain, name, version, activity)
|
146
168
|
end
|
147
169
|
|
148
170
|
protected
|
171
|
+
|
172
|
+
def activities
|
173
|
+
self.class.activities
|
174
|
+
end
|
175
|
+
|
149
176
|
def self.activities
|
150
|
-
@activities ||=
|
177
|
+
@activities ||= ActivityRegistry.new
|
151
178
|
end
|
152
179
|
|
153
180
|
def self.swf
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module SimplerWorkflow
|
2
|
+
class ActivityRegistry
|
3
|
+
def register(*activity_tuple)
|
4
|
+
domain = activity_tuple.shift
|
5
|
+
activity = activity_tuple.pop if activity_tuple.last.is_a?(Activity)
|
6
|
+
raise "Activity missing from registration" unless activity
|
7
|
+
|
8
|
+
registry_for_domain(domain)[activity_tuple] = activity
|
9
|
+
end
|
10
|
+
|
11
|
+
alias :[]= :register
|
12
|
+
|
13
|
+
def get(*activity_tuple)
|
14
|
+
domain = activity_tuple.shift
|
15
|
+
|
16
|
+
if AWS::SimpleWorkflow::ActivityType === domain
|
17
|
+
name = domain.name.to_sym
|
18
|
+
version = domain.version
|
19
|
+
domain = domain.domain
|
20
|
+
else
|
21
|
+
name = activity_tuple.first
|
22
|
+
|
23
|
+
case name
|
24
|
+
when Hash
|
25
|
+
version = name[:version]
|
26
|
+
name = name[:name].to_sym
|
27
|
+
when String, Symbol
|
28
|
+
name = name.to_sym
|
29
|
+
version = activity_tuple.last
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
registry_for_domain(domain)[[name, version]]
|
34
|
+
end
|
35
|
+
|
36
|
+
alias :[] :get
|
37
|
+
|
38
|
+
def persist_attributes(activity)
|
39
|
+
domain = Domain.for(activity.domain)
|
40
|
+
|
41
|
+
sdb_domain(domain).items.create(activity.simple_db_name, activity.simple_db_attributes)
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
def registries
|
46
|
+
@registries ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def registry_for_domain(domain)
|
50
|
+
domain = Domain.for(domain)
|
51
|
+
|
52
|
+
unless sdb_domain(domain).exists?
|
53
|
+
sdb.domains.create(sdb_domain_name(domain))
|
54
|
+
end
|
55
|
+
|
56
|
+
registries[domain.name.to_sym] ||= Hash.new do |registry, (name, version)|
|
57
|
+
activity = Activity.new(domain, name, version)
|
58
|
+
attributes = sdb_attributes(domain, activity.simple_db_name)
|
59
|
+
|
60
|
+
unless attributes.empty?
|
61
|
+
activity.on_fail(attributes[:failure_policy]) if attributes.has_key?(:failure_policy)
|
62
|
+
activity.on_fail(attributes['failure_policy']) if attributes.has_key?('failure_policy')
|
63
|
+
activity.on_success(name: attributes[:next_activity_name], version: attributes[:next_activity_version]) if attributes.has_key?(:next_activity_name)
|
64
|
+
activity.on_success(name: attributes['next_activity_name'], version: attributes['next_activity_version']) if attributes.has_key?('next_activity_name')
|
65
|
+
end
|
66
|
+
registry[[name, version]] = activity
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def sdb_domain_name(domain)
|
71
|
+
"swf-#{domain.name}-activities"
|
72
|
+
end
|
73
|
+
|
74
|
+
def sdb_domain(domain)
|
75
|
+
sdb.domains[sdb_domain_name(domain)]
|
76
|
+
end
|
77
|
+
|
78
|
+
def sdb_attributes(domain, sdb_name)
|
79
|
+
if item = sdb_domain(domain).items[sdb_name]
|
80
|
+
h = item.attributes.to_h
|
81
|
+
h.each { |k, v| h[k] = v.first }
|
82
|
+
else
|
83
|
+
{}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.sdb
|
88
|
+
@sdb ||= AWS::SimpleDB.new
|
89
|
+
end
|
90
|
+
|
91
|
+
def sdb
|
92
|
+
self.class.sdb
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -18,21 +18,33 @@ module SimplerWorkflow
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def Domain.[](domain_name)
|
21
|
-
Domain.domains(domain_name)
|
21
|
+
Domain.domains(domain_name.to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
def Domain.for(domain)
|
25
|
+
case domain
|
26
|
+
when String, Symbol
|
27
|
+
Domain[domain]
|
28
|
+
when Domain
|
29
|
+
domain
|
30
|
+
when AWS::SimpleWorkflow::Domain
|
31
|
+
Domain[domain.name]
|
32
|
+
end
|
22
33
|
end
|
23
34
|
|
24
35
|
def register_workflow(name, version, &block)
|
25
36
|
unless workflow = Workflow[name, version]
|
26
37
|
workflow = Workflow.new(self, name, version)
|
27
|
-
end
|
28
38
|
|
29
|
-
|
39
|
+
workflow.instance_eval(&block) if block_given?
|
30
40
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
41
|
+
begin
|
42
|
+
self.domain.workflow_types.register(name, version, workflow.options)
|
43
|
+
rescue ::AWS::SimpleWorkflow::Errors::TypeAlreadyExistsFault
|
44
|
+
# Instance already registered...
|
45
|
+
end
|
35
46
|
end
|
47
|
+
|
36
48
|
workflow
|
37
49
|
end
|
38
50
|
|
@@ -54,18 +66,18 @@ module SimplerWorkflow
|
|
54
66
|
domain.activity_types
|
55
67
|
end
|
56
68
|
|
57
|
-
def register_activity(name, version, &block)
|
58
|
-
|
59
|
-
|
60
|
-
activity = Activity.new(self, name, version)
|
61
|
-
end
|
69
|
+
def register_activity(name, version = nil, &block)
|
70
|
+
logger.info("Registering Activity[#{name},#{version}]")
|
71
|
+
activity = activities[self, name, version]
|
62
72
|
|
63
73
|
activity.instance_eval(&block) if block
|
64
74
|
|
75
|
+
activity.persist_attributes
|
76
|
+
|
65
77
|
begin
|
66
78
|
self.domain.activity_types.register(name.to_s, version, activity.options)
|
67
79
|
rescue ::AWS::SimpleWorkflow::Errors::TypeAlreadyExistsFault
|
68
|
-
#
|
80
|
+
SimplerWorkflow.logger.info("Activity[#{name}, #{version}] already registered with SWF.")
|
69
81
|
end
|
70
82
|
|
71
83
|
activity
|
@@ -21,11 +21,8 @@ module SimplerWorkflow
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def initial_activity(name, version = nil)
|
24
|
-
|
25
|
-
|
26
|
-
elsif activity = domain.activity_types[name.to_s, version]
|
27
|
-
@initial_activity_type = activity
|
28
|
-
end
|
24
|
+
activity = Activity[domain, name.to_sym, version]
|
25
|
+
@initial_activity_type = activity.to_activity_type
|
29
26
|
end
|
30
27
|
|
31
28
|
def decision_loop
|
@@ -47,26 +44,11 @@ module SimplerWorkflow
|
|
47
44
|
SimplerWorkflow.after_fork.call
|
48
45
|
end
|
49
46
|
|
50
|
-
|
51
47
|
loop do
|
52
48
|
begin
|
53
49
|
logger.info("Waiting for a decision task for #{name.to_s}, #{version} listening to #{task_list}")
|
54
50
|
domain.decision_tasks.poll_for_single_task(task_list) do |decision_task|
|
55
|
-
decision_task
|
56
|
-
logger.info("Received decision task")
|
57
|
-
decision_task.new_events.each do |event|
|
58
|
-
logger.info("Processing #{event.event_type}")
|
59
|
-
case event.event_type
|
60
|
-
when 'WorkflowExecutionStarted'
|
61
|
-
start_execution(decision_task, event)
|
62
|
-
when 'ActivityTaskCompleted'
|
63
|
-
activity_completed(decision_task, event)
|
64
|
-
when 'ActivityTaskFailed'
|
65
|
-
activity_failed(decision_task, event)
|
66
|
-
when 'ActivityTaskTimedOut'
|
67
|
-
activity_timed_out(decision_task, event)
|
68
|
-
end
|
69
|
-
end
|
51
|
+
handle_decision_task(decision_task)
|
70
52
|
end
|
71
53
|
Process.exit 0 if @time_to_exit
|
72
54
|
rescue Timeout::Error => e
|
@@ -77,9 +59,7 @@ module SimplerWorkflow
|
|
77
59
|
end
|
78
60
|
rescue => e
|
79
61
|
context = {
|
80
|
-
:
|
81
|
-
:workflow => to_workflow_type,
|
82
|
-
:decision_task => decision_task
|
62
|
+
:workflow => to_workflow_type
|
83
63
|
}
|
84
64
|
SimplerWorkflow.exception_reporter.report(e, context)
|
85
65
|
raise e
|
@@ -89,69 +69,7 @@ module SimplerWorkflow
|
|
89
69
|
end
|
90
70
|
|
91
71
|
def task_list
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
def start_execution(decision_task, event)
|
96
|
-
logger.info "Starting the execution of the job."
|
97
|
-
if @on_start_execution && @on_start_execution.respond_to?(:call)
|
98
|
-
@on_start_execution.call(decision_task, event)
|
99
|
-
else
|
100
|
-
decision_task.schedule_activity_task initial_activity_type, :input => event.attributes.input
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def activity_completed(decision_task, event)
|
105
|
-
if @on_activity_completed && @on_activity_completed.respond_to?(:call)
|
106
|
-
@on_activity_completed.call(decision_task, event)
|
107
|
-
else
|
108
|
-
if event.attributes.keys.include?(:result)
|
109
|
-
result = Map.from_json(event.attributes.result)
|
110
|
-
next_activity = result[:next_activity]
|
111
|
-
activity_type = domain.activity_types[next_activity[:name], next_activity[:version]]
|
112
|
-
decision_task.schedule_activity_task activity_type, :input => scheduled_event(decision_task, event).attributes.input
|
113
|
-
else
|
114
|
-
logger.info("Workflow #{name}, #{version} completed")
|
115
|
-
decision_task.complete_workflow_execution :result => 'success'
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def activity_failed(decision_task, event)
|
121
|
-
logger.info("Activity failed.")
|
122
|
-
if @on_activity_failed && @on_activity_failed.respond_to?(:call)
|
123
|
-
@on_activity_failed.call(decision_task, event)
|
124
|
-
else
|
125
|
-
if event.attributes.keys.include?(:details)
|
126
|
-
details = Map.from_json(event.attributes.details)
|
127
|
-
case details.failure_policy.to_sym
|
128
|
-
when :abort, :cancel
|
129
|
-
decision_task.cancel_workflow_execution
|
130
|
-
when :fail
|
131
|
-
decision_task.fail_workflow_execution
|
132
|
-
when :retry
|
133
|
-
logger.info("Retrying activity #{last_activity(decision_task, event).name} #{last_activity(decision_task, event).version}")
|
134
|
-
decision_task.schedule_activity_task last_activity(decision_task, event), :input => last_input(decision_task, event)
|
135
|
-
end
|
136
|
-
else
|
137
|
-
decision_task.cancel_workflow_execution
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def activity_timed_out(decision_task, event)
|
143
|
-
logger.info("Activity timed out.")
|
144
|
-
if @on_activity_timed_out && @on_activity_timed_out.respond_to?(:call)
|
145
|
-
@on_activity_timed_out.call(decision_task, event)
|
146
|
-
else
|
147
|
-
case event.attributes.timeoutType
|
148
|
-
when 'START_TO_CLOSE', 'SCHEDULE_TO_START', 'SCHEDULE_TO_CLOSE'
|
149
|
-
logger.info("Retrying activity #{last_activity(decision_task, event).name} #{last_activity(decision_task, event).version} due to timeout.")
|
150
|
-
decision_task.schedule_activity_task last_activity(decision_task, event), :input => last_input(decision_task, event)
|
151
|
-
when 'HEARTBEAT'
|
152
|
-
decision_task.cancel_workflow_execution
|
153
|
-
end
|
154
|
-
end
|
72
|
+
options[:default_task_list][:name].to_s
|
155
73
|
end
|
156
74
|
|
157
75
|
def to_workflow_type
|
@@ -164,19 +82,19 @@ module SimplerWorkflow
|
|
164
82
|
end
|
165
83
|
|
166
84
|
def on_start_execution(&block)
|
167
|
-
|
85
|
+
event_handlers['WorkflowExecutionStarted'] = WorkflowEventHandler.new(&block)
|
168
86
|
end
|
169
87
|
|
170
88
|
def on_activity_completed(&block)
|
171
|
-
|
89
|
+
event_handlers['ActivityTaskCompleted'] = WorkflowEventHandler.new(&block)
|
172
90
|
end
|
173
91
|
|
174
92
|
def on_activity_failed(&block)
|
175
|
-
|
93
|
+
event_handlers['ActivityTaskFailed'] = WorkflowEventHandler.new(&block)
|
176
94
|
end
|
177
95
|
|
178
96
|
def on_activity_timed_out(&block)
|
179
|
-
|
97
|
+
event_handlers['ActivityTaskTimedOut'] = WorkflowEventHandler.new(&block)
|
180
98
|
end
|
181
99
|
|
182
100
|
def self.[](name, version)
|
@@ -187,6 +105,18 @@ module SimplerWorkflow
|
|
187
105
|
workflows[[name, version]] = workflow
|
188
106
|
end
|
189
107
|
|
108
|
+
def scheduled_event(decision_task, event)
|
109
|
+
decision_task.scheduled_event(event)
|
110
|
+
end
|
111
|
+
|
112
|
+
def last_activity(decision_task, event)
|
113
|
+
scheduled_event(decision_task, event).attributes.activity_type
|
114
|
+
end
|
115
|
+
|
116
|
+
def last_input(decision_task, event)
|
117
|
+
scheduled_event(decision_task, event).attributes.input
|
118
|
+
end
|
119
|
+
|
190
120
|
protected
|
191
121
|
def self.workflows
|
192
122
|
@workflows ||= {}
|
@@ -196,20 +126,121 @@ module SimplerWorkflow
|
|
196
126
|
SimplerWorkflow.swf
|
197
127
|
end
|
198
128
|
|
199
|
-
def
|
200
|
-
|
129
|
+
def logger
|
130
|
+
SimplerWorkflow.logger
|
201
131
|
end
|
202
132
|
|
203
|
-
def
|
204
|
-
|
133
|
+
def handle_decision_task(decision_task)
|
134
|
+
decision_task.extend AWS::SimpleWorkflow::DecisionTaskAdditions
|
135
|
+
logger.info("Received decision task")
|
136
|
+
decision_task.new_events.each do |event|
|
137
|
+
logger.info("Processing #{event.event_type}")
|
138
|
+
event_handlers.fetch(event.event_type, DefaultEventHandler.new(self)).process(decision_task, event)
|
139
|
+
end
|
205
140
|
end
|
206
141
|
|
207
|
-
def
|
208
|
-
|
142
|
+
def event_handlers
|
143
|
+
@event_handlers ||= Map[
|
144
|
+
:WorkflowExecutionStarted , WorkflowExecutionStartedHandler.new(self) ,
|
145
|
+
:ActivityTaskCompleted , ActivityTaskCompletedHandler.new(self) ,
|
146
|
+
:ActivityTaskFailed , ActivityTaskFailedHandler.new(self) ,
|
147
|
+
:ActivityTaskTimedOut , ActivityTaskTimedOutHandler.new(self)
|
148
|
+
]
|
209
149
|
end
|
210
150
|
|
211
|
-
|
212
|
-
|
151
|
+
class DefaultEventHandler
|
152
|
+
attr_accessor :workflow
|
153
|
+
|
154
|
+
def initialize(workflow)
|
155
|
+
@workflow = workflow
|
156
|
+
end
|
157
|
+
|
158
|
+
def scheduled_event(*args)
|
159
|
+
workflow.scheduled_event(*args)
|
160
|
+
end
|
161
|
+
|
162
|
+
def domain
|
163
|
+
workflow.domain
|
164
|
+
end
|
165
|
+
|
166
|
+
def last_activity(*args)
|
167
|
+
workflow.last_activity(*args)
|
168
|
+
end
|
169
|
+
|
170
|
+
def last_input(*args)
|
171
|
+
workflow.last_input(*args)
|
172
|
+
end
|
173
|
+
|
174
|
+
def initial_activity_type
|
175
|
+
workflow.initial_activity_type
|
176
|
+
end
|
177
|
+
|
178
|
+
def process(*args); end
|
179
|
+
end
|
180
|
+
|
181
|
+
class WorkflowEventHandler
|
182
|
+
attr_accessor :handler
|
183
|
+
|
184
|
+
def initialize(&block)
|
185
|
+
@handler = block
|
186
|
+
end
|
187
|
+
|
188
|
+
def process(decision_task, event)
|
189
|
+
handler.call(decision_task, event)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
class ActivityTaskTimedOutHandler < DefaultEventHandler
|
194
|
+
def process(decision_task, event)
|
195
|
+
case event.attributes.timeoutType
|
196
|
+
when 'START_TO_CLOSE', 'SCHEDULE_TO_START', 'SCHEDULE_TO_CLOSE'
|
197
|
+
last_activity_type = last_activity(decision_task, event)
|
198
|
+
SimplerWorkflow.logger.info("Retrying activity #{last_activity_type.name} #{last_activity_type.version} due to timeout.")
|
199
|
+
decision_task.schedule_activity_task last_activity_type, :input => last_input(decision_task, event)
|
200
|
+
when 'HEARTBEAT'
|
201
|
+
decision_task.fail_workflow_execution
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class ActivityTaskFailedHandler < DefaultEventHandler
|
207
|
+
def process(decision_task, event)
|
208
|
+
last_activity_type = last_activity(decision_task, event)
|
209
|
+
failed_activity = domain.activities[last_activity_type]
|
210
|
+
|
211
|
+
case failed_activity.failure_policy
|
212
|
+
when :abort, :cancel
|
213
|
+
SimplerWorkflow.logger.info("Cancelling workflow execution.")
|
214
|
+
decision_task.cancel_workflow_execution
|
215
|
+
when :retry
|
216
|
+
SimplerWorkflow.logger.info("Retrying activity #{last_activity_type.name} #{last_activity_type.version}")
|
217
|
+
decision_task.schedule_activity_task last_activity_type, :input => last_input(decision_task, event)
|
218
|
+
else
|
219
|
+
SimplerWorkflow.logger.info("Failing the workflow execution.")
|
220
|
+
decision_task.fail_workflow_execution
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
class ActivityTaskCompletedHandler < DefaultEventHandler
|
226
|
+
def process(decision_task, event)
|
227
|
+
last_activity_type = last_activity(decision_task, event)
|
228
|
+
|
229
|
+
completed_activity = domain.activities[last_activity_type]
|
230
|
+
|
231
|
+
if next_activity = completed_activity.next_activity
|
232
|
+
activity_type = domain.activity_types[next_activity.name, next_activity.version]
|
233
|
+
decision_task.schedule_activity activity_type, input: scheduled_event(decision_task, event).attributes.input
|
234
|
+
else
|
235
|
+
decision_task.complete_workflow_execution(result: 'success')
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class WorkflowExecutionStartedHandler < DefaultEventHandler
|
241
|
+
def process(decision_task, event)
|
242
|
+
decision_task.schedule_activity_task initial_activity_type, input: event.attributes.input
|
243
|
+
end
|
213
244
|
end
|
214
245
|
end
|
215
246
|
end
|
data/simpler_workflow.gemspec
CHANGED
@@ -26,10 +26,16 @@ EOM
|
|
26
26
|
gem.name = "simpler_workflow"
|
27
27
|
gem.require_paths = ["lib"]
|
28
28
|
gem.version = SimplerWorkflow::VERSION
|
29
|
+
gem.required_ruby_version = '>= 1.9.0'
|
29
30
|
|
30
|
-
gem.add_dependency 'aws-sdk'
|
31
|
+
gem.add_dependency 'aws-sdk'
|
31
32
|
gem.add_dependency 'map'
|
33
|
+
gem.add_development_dependency 'map'
|
32
34
|
gem.add_development_dependency 'rake'
|
33
35
|
gem.add_development_dependency 'rspec'
|
34
36
|
gem.add_development_dependency 'travis-lint'
|
37
|
+
gem.add_development_dependency 'pry'
|
38
|
+
gem.add_development_dependency 'pry-nav'
|
39
|
+
gem.add_development_dependency 'logging'
|
40
|
+
|
35
41
|
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SimplerWorkflow
|
4
|
+
describe Activity do
|
5
|
+
let(:client) { AWS.config.simple_workflow_client }
|
6
|
+
let(:describe_domain_response) { client.stub_for(:describe_domain) }
|
7
|
+
let(:list_domains_response) { client.stub_for(:list_domains) }
|
8
|
+
|
9
|
+
let(:decision_task) { mock(AWS::SimpleWorkflow::DecisionTask) }
|
10
|
+
|
11
|
+
let(:domain) { SimplerWorkflow.domain('test-domain') }
|
12
|
+
|
13
|
+
let(:domain_desc) {{
|
14
|
+
'configuration' => { 'workflowExecutionRetentionPeriodInDays' => '2' },
|
15
|
+
'domainInfo' => {
|
16
|
+
'name' => domain.name,
|
17
|
+
'description' => 'desc',
|
18
|
+
'status' => 'REGISTERED',
|
19
|
+
},
|
20
|
+
}}
|
21
|
+
|
22
|
+
let(:domains_desc) {
|
23
|
+
{
|
24
|
+
'domainInfos' => [
|
25
|
+
domain_desc['domainInfo']
|
26
|
+
]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
let(:sdb) { AWS::SimpleDB.new }
|
31
|
+
|
32
|
+
before :each do
|
33
|
+
describe_domain_response.stub(:data).and_return(domain_desc)
|
34
|
+
client.stub(:describe_domain).and_return(describe_domain_response)
|
35
|
+
list_domains_response.stub(:data).and_return(domains_desc)
|
36
|
+
client.stub(:list_domains).and_return(list_domains_response)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "Registering a new activity" do
|
40
|
+
context "default activity" do
|
41
|
+
subject(:activity) { domain.register_activity('test-activity', '1.0.0') }
|
42
|
+
|
43
|
+
its(:name) { should == 'test-activity' }
|
44
|
+
its(:version) { should == '1.0.0' }
|
45
|
+
its(:domain) { should == domain }
|
46
|
+
its(:failure_policy) { should == :fail }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "Setting the failure policy" do
|
50
|
+
subject(:activity) do
|
51
|
+
domain.register_activity('test-activity', '1.0.1') do
|
52
|
+
on_fail :retry
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
its(:failure_policy) { should == :retry }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "Setting the next activity" do
|
60
|
+
subject(:activity) do
|
61
|
+
domain.register_activity('test-success', '1.0.0') do
|
62
|
+
on_success 'next-activity', '1.0.0'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
its(:next_activity) { should == Activity[domain, 'next-activity', '1.0.0'] }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "performing a task" do
|
70
|
+
subject(:activity) do
|
71
|
+
domain.register_activity('test-task', '1.0.0') do
|
72
|
+
perform_activity do |task|
|
73
|
+
task.complete! 'result' => "success"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should execute the task handler." do
|
79
|
+
task = mock(AWS::SimpleWorkflow::ActivityTask)
|
80
|
+
task.should_receive(:complete!).with("result" => "success")
|
81
|
+
|
82
|
+
activity.perform_task(task)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "We should always return an activity from the registry" do
|
87
|
+
subject(:activity) { Activity[domain, 'not-a-real-activity', '1.0.0'] }
|
88
|
+
|
89
|
+
its(:name) { should == 'not-a-real-activity' }
|
90
|
+
its(:version) { should == '1.0.0' }
|
91
|
+
its(:failure_policy) { should == :fail }
|
92
|
+
end
|
93
|
+
|
94
|
+
context "We are retrieving an activity that was register in a different process" do
|
95
|
+
subject(:activity) { Activity[domain, 'registered-somewhere-else', '1.0.0'] }
|
96
|
+
|
97
|
+
it "should build the activity from the SDB data..." do
|
98
|
+
Activity.activities.should_receive(:sdb_attributes).with(domain, "registered-somewhere-else-1.0.0").and_return({
|
99
|
+
:failure_policy => 'retry',
|
100
|
+
:next_activity_name => 'yet-another-activity',
|
101
|
+
:next_activity_version => '1.0.0'
|
102
|
+
})
|
103
|
+
|
104
|
+
Activity.activities.should_receive(:sdb_attributes).with(domain, 'yet-another-activity-1.0.0').and_return({})
|
105
|
+
|
106
|
+
activity.failure_policy.should == :retry
|
107
|
+
activity.next_activity.should == Activity[domain, 'yet-another-activity', '1.0.0']
|
108
|
+
activity.next_activity.failure_policy.should == :fail
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context "Just in case we get strings from amazon SDB..." do
|
114
|
+
subject(:activity) { Activity[domain, 'registered-somewhere-else', '2.0.0'] }
|
115
|
+
|
116
|
+
it "should build the activity from the SDB data... with Strings this time..." do
|
117
|
+
Activity.activities.should_receive(:sdb_attributes).with(domain, "registered-somewhere-else-2.0.0").and_return({
|
118
|
+
'failure_policy' => 'retry',
|
119
|
+
'next_activity_name' => 'yet-another-activity',
|
120
|
+
'next_activity_version' => '2.0.0'
|
121
|
+
})
|
122
|
+
|
123
|
+
Activity.activities.should_receive(:sdb_attributes).with(domain, 'yet-another-activity-2.0.0').and_return({})
|
124
|
+
|
125
|
+
activity.failure_policy.should == :retry
|
126
|
+
activity.next_activity.should == Activity[domain, 'yet-another-activity', '2.0.0']
|
127
|
+
activity.next_activity.failure_policy.should == :fail
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,6 +7,9 @@
|
|
7
7
|
#
|
8
8
|
|
9
9
|
require 'simpler_workflow'
|
10
|
+
require 'aws/simple_workflow'
|
11
|
+
require 'pry'
|
12
|
+
require 'logging'
|
10
13
|
|
11
14
|
RSpec.configure do |config|
|
12
15
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -17,8 +20,12 @@ RSpec.configure do |config|
|
|
17
20
|
AWS.stub!
|
18
21
|
AWS.config(:access_key_id => 'TESTKEY', :secret_access_key => 'TESTSECRET')
|
19
22
|
end
|
20
|
-
end
|
21
23
|
|
22
|
-
|
24
|
+
$logger = Logging.logger("test.log")
|
25
|
+
end
|
23
26
|
|
27
|
+
class SimplerWorkflow::Workflow::WorkflowEventHandler
|
28
|
+
def workflow_event_handler?
|
29
|
+
is_a?(SimplerWorkflow::Workflow::WorkflowEventHandler)
|
30
|
+
end
|
24
31
|
end
|
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SimplerWorkflow
|
4
|
+
describe Workflow do
|
5
|
+
let(:client) { AWS.config.simple_workflow_client }
|
6
|
+
let(:describe_domain_response) { client.stub_for(:describe_domain) }
|
7
|
+
let(:list_domains_response) { client.stub_for(:list_domains) }
|
8
|
+
|
9
|
+
let(:decision_task) { mock(AWS::SimpleWorkflow::DecisionTask) }
|
10
|
+
|
11
|
+
let(:domain) { SimplerWorkflow.domain('test-domain') }
|
12
|
+
|
13
|
+
let(:domain_desc) {{
|
14
|
+
'configuration' => { 'workflowExecutionRetentionPeriodInDays' => '2' },
|
15
|
+
'domainInfo' => {
|
16
|
+
'name' => domain.name,
|
17
|
+
'description' => 'desc',
|
18
|
+
'status' => 'REGISTERED',
|
19
|
+
},
|
20
|
+
}}
|
21
|
+
|
22
|
+
let(:domains_desc) {
|
23
|
+
{
|
24
|
+
'domainInfos' => [
|
25
|
+
domain_desc['domainInfo']
|
26
|
+
]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
before :each do
|
31
|
+
describe_domain_response.stub(:data).and_return(domain_desc)
|
32
|
+
client.stub(:describe_domain).and_return(describe_domain_response)
|
33
|
+
list_domains_response.stub(:data).and_return(domains_desc)
|
34
|
+
client.stub(:list_domains).and_return(list_domains_response)
|
35
|
+
end
|
36
|
+
|
37
|
+
context "Registering a new workflow." do
|
38
|
+
before :each do
|
39
|
+
Workflow.send :public, :event_handlers
|
40
|
+
end
|
41
|
+
|
42
|
+
context "default workflows" do
|
43
|
+
let(:workflow) { domain.register_workflow('test-workflow', '1.0.0') }
|
44
|
+
|
45
|
+
let(:event_handlers) { workflow.event_handlers }
|
46
|
+
|
47
|
+
it "should allow the registration of a domain." do
|
48
|
+
workflow.name.should == 'test-workflow'
|
49
|
+
workflow.version.should == '1.0.0'
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have a default tasklist" do
|
53
|
+
workflow.task_list.should == workflow.name
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have a default task start to close timeout" do
|
57
|
+
workflow.options[:default_task_start_to_close_timeout].should == "120"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should have a default execution start to close timeout" do
|
61
|
+
workflow.options[:default_execution_start_to_close_timeout].should == "120"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should have a default child policy of terminate" do
|
65
|
+
workflow.options[:default_child_policy].should == 'TERMINATE'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should have default handlers' do
|
69
|
+
event_handlers.should_not be_nil
|
70
|
+
end
|
71
|
+
|
72
|
+
%w(WorkflowExecutionStarted ActivityTaskCompleted ActivityTaskFailed ActivityTaskTimedOut).each do |event|
|
73
|
+
it "should have a default event handler for #{event}" do
|
74
|
+
handler = event_handlers[event]
|
75
|
+
handler.should_not be_nil
|
76
|
+
handler.class.name.should == "SimplerWorkflow::Workflow::#{event}Handler"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should call the right handler for #{event}" do
|
80
|
+
new_event = Map.new
|
81
|
+
new_event.set(:event_type, event)
|
82
|
+
|
83
|
+
decision_task.should_receive(:new_events).and_return([new_event])
|
84
|
+
|
85
|
+
event_handlers[new_event.event_type].should_receive(:process).with(decision_task, new_event)
|
86
|
+
|
87
|
+
workflow.send :handle_decision_task, decision_task
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "The workflow's initial activity" do
|
92
|
+
before :each do
|
93
|
+
workflow.initial_activity :test_activity, '1.0.0'
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
it "should store the initial activity" do
|
98
|
+
workflow.send(:initial_activity_type).should == domain.activity_types[:test_activity, '1.0.0']
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should start a workflow based on the declared initial activity" do
|
102
|
+
event = stub( :attributes => stub( :input => "Mary had a little lamb"))
|
103
|
+
decision_task.should_receive(:schedule_activity_task).with(domain.activity_types[:test_activity, '1.0.0'], input: event.attributes.input)
|
104
|
+
|
105
|
+
event_handlers[:WorkflowExecutionStarted].process(decision_task, event)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "An activity completed." do
|
110
|
+
it "should complete the execution if we have results but to not provide a next activity" do
|
111
|
+
event = Map.new
|
112
|
+
event.set(:attributes, :result, '{"blah":"Hello"}')
|
113
|
+
|
114
|
+
scheduled_activity = domain.register_activity(:completion_activity, '1.0.0')
|
115
|
+
|
116
|
+
scheduled_event = Map.new
|
117
|
+
scheduled_event.set(:attributes, :input, "mary had a little lamb")
|
118
|
+
scheduled_event.set(:attributes, :activity_type, scheduled_activity.to_activity_type)
|
119
|
+
|
120
|
+
decision_task.should_receive(:scheduled_event).with(event).and_return(scheduled_event)
|
121
|
+
decision_task.should_receive(:complete_workflow_execution).with(result: 'success')
|
122
|
+
|
123
|
+
event_handlers[:ActivityTaskCompleted].process(decision_task, event)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should schedule the next activity if the current one declares one" do
|
127
|
+
event = Map.new
|
128
|
+
event.set(:attributes, :result, "success")
|
129
|
+
|
130
|
+
test_activity = domain.register_activity(:test_activity, '1.0.0')
|
131
|
+
|
132
|
+
scheduled_activity = domain.register_activity(:success_activity, '1.0.0') do
|
133
|
+
on_success :test_activity, '1.0.0'
|
134
|
+
end
|
135
|
+
|
136
|
+
next_activity = test_activity.to_activity_type
|
137
|
+
|
138
|
+
scheduled_event = Map.new
|
139
|
+
scheduled_event.set(:attributes, :input, "mary had a little lamb")
|
140
|
+
scheduled_event.set(:attributes, :activity_type, scheduled_activity.to_activity_type)
|
141
|
+
|
142
|
+
decision_task.should_receive(:scheduled_event).with(event).twice.and_return(scheduled_event)
|
143
|
+
decision_task.should_receive(:schedule_activity).with(next_activity, input: scheduled_event.attributes.input)
|
144
|
+
|
145
|
+
event_handlers[:ActivityTaskCompleted].process(decision_task, event)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "An activity task failed" do
|
150
|
+
it "should fail the execution if instructed to do so" do
|
151
|
+
event = Map.new
|
152
|
+
|
153
|
+
test_activity = domain.register_activity(:failed_activity, '1.0.0')
|
154
|
+
|
155
|
+
scheduled_event = Map.new
|
156
|
+
scheduled_event.set(:attributes, :input, "Mary had a little lamb")
|
157
|
+
scheduled_event.set(:attributes, :activity_type, test_activity.to_activity_type)
|
158
|
+
|
159
|
+
decision_task.should_receive(:fail_workflow_execution)
|
160
|
+
decision_task.should_receive(:scheduled_event).with(event).and_return(scheduled_event)
|
161
|
+
|
162
|
+
event_handlers[:ActivityTaskFailed].process(decision_task, event)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should cancel the execution if instructed to abort" do
|
166
|
+
event = Map.new
|
167
|
+
test_activity = domain.register_activity(:failed_activity, '1.0.1') do
|
168
|
+
on_fail :abort
|
169
|
+
end
|
170
|
+
|
171
|
+
scheduled_event = Map.new
|
172
|
+
scheduled_event.set(:attributes, :input, "Mary had a little lamb")
|
173
|
+
scheduled_event.set(:attributes, :activity_type, test_activity.to_activity_type)
|
174
|
+
|
175
|
+
decision_task.should_receive(:scheduled_event).with(event).and_return(scheduled_event)
|
176
|
+
decision_task.should_receive(:cancel_workflow_execution)
|
177
|
+
|
178
|
+
event_handlers[:ActivityTaskFailed].process(decision_task, event)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should cancel the execution if instructed to do so" do
|
182
|
+
event = Map.new
|
183
|
+
|
184
|
+
test_activity = domain.register_activity(:failed_activity, '1.0.2') do
|
185
|
+
on_fail :cancel
|
186
|
+
end
|
187
|
+
|
188
|
+
scheduled_event = Map.new
|
189
|
+
scheduled_event.set(:attributes, :input, "Mary had a little lamb")
|
190
|
+
scheduled_event.set(:attributes, :activity_type, test_activity.to_activity_type)
|
191
|
+
|
192
|
+
decision_task.should_receive(:scheduled_event).with(event).and_return(scheduled_event)
|
193
|
+
decision_task.should_receive(:cancel_workflow_execution)
|
194
|
+
|
195
|
+
event_handlers[:ActivityTaskFailed].process(decision_task, event)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should reschedule the activity if requested" do
|
199
|
+
event = Map.new
|
200
|
+
|
201
|
+
test_activity = domain.register_activity(:failed_activity, '1.0.3') do
|
202
|
+
on_fail :retry
|
203
|
+
end
|
204
|
+
|
205
|
+
scheduled_event = Map.new
|
206
|
+
scheduled_event.set(:attributes, :input, "Mary had a little lamb")
|
207
|
+
scheduled_event.set(:attributes, :activity_type, test_activity.to_activity_type)
|
208
|
+
|
209
|
+
decision_task.should_receive(:scheduled_event).with(event).twice.and_return(scheduled_event)
|
210
|
+
decision_task.should_receive(:schedule_activity_task).with(test_activity.to_activity_type, input: scheduled_event.attributes.input)
|
211
|
+
|
212
|
+
event_handlers[:ActivityTaskFailed].process(decision_task, event)
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
context "an activity timed out" do
|
218
|
+
%w(START_TO_CLOSE SCHEDULE_TO_CLOSE SCHEDULE_TO_START).each do |timeout_type|
|
219
|
+
it "should retry a timed out decision task on #{timeout_type}" do
|
220
|
+
activity_type = domain.activity_types[:test_activity, "1.0.0"]
|
221
|
+
event = Map.new
|
222
|
+
event.set(:attributes, :timeoutType, timeout_type)
|
223
|
+
scheduled_event = Map.new
|
224
|
+
scheduled_event.set(:attributes, :input, "Mary had a little lamb")
|
225
|
+
scheduled_event.set(:attributes, :activity_type, activity_type)
|
226
|
+
|
227
|
+
decision_task.should_receive(:scheduled_event).twice.and_return(scheduled_event)
|
228
|
+
decision_task.should_receive(:schedule_activity_task).with(activity_type, input: scheduled_event.attributes.input)
|
229
|
+
event_handlers[:ActivityTaskTimedOut].process(decision_task, event)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should fail a workflow execution when the heartbeat fails" do
|
234
|
+
event = Map.new
|
235
|
+
event.set(:attributes, :timeoutType, 'HEARTBEAT')
|
236
|
+
|
237
|
+
decision_task.should_receive(:fail_workflow_execution)
|
238
|
+
|
239
|
+
event_handlers[:ActivityTaskTimedOut].process(decision_task, event)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
metadata
CHANGED
@@ -1,34 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simpler_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
prerelease: 6
|
5
|
+
version: 0.3.0.beta
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Frederic Jean
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
none: false
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
15
21
|
name: aws-sdk
|
22
|
+
prerelease: false
|
16
23
|
requirement: !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
25
|
requirements:
|
19
|
-
- -
|
26
|
+
- - ! '>='
|
20
27
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
28
|
+
version: '0'
|
22
29
|
type: :runtime
|
23
|
-
|
30
|
+
- !ruby/object:Gem::Dependency
|
24
31
|
version_requirements: !ruby/object:Gem::Requirement
|
25
32
|
none: false
|
26
33
|
requirements:
|
27
|
-
- -
|
34
|
+
- - ! '>='
|
28
35
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- !ruby/object:Gem::Dependency
|
36
|
+
version: '0'
|
31
37
|
name: map
|
38
|
+
prerelease: false
|
32
39
|
requirement: !ruby/object:Gem::Requirement
|
33
40
|
none: false
|
34
41
|
requirements:
|
@@ -36,15 +43,31 @@ dependencies:
|
|
36
43
|
- !ruby/object:Gem::Version
|
37
44
|
version: '0'
|
38
45
|
type: :runtime
|
39
|
-
|
46
|
+
- !ruby/object:Gem::Dependency
|
40
47
|
version_requirements: !ruby/object:Gem::Requirement
|
41
48
|
none: false
|
42
49
|
requirements:
|
43
50
|
- - ! '>='
|
44
51
|
- !ruby/object:Gem::Version
|
45
52
|
version: '0'
|
53
|
+
name: map
|
54
|
+
prerelease: false
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :development
|
46
62
|
- !ruby/object:Gem::Dependency
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
47
69
|
name: rake
|
70
|
+
prerelease: false
|
48
71
|
requirement: !ruby/object:Gem::Requirement
|
49
72
|
none: false
|
50
73
|
requirements:
|
@@ -52,15 +75,15 @@ dependencies:
|
|
52
75
|
- !ruby/object:Gem::Version
|
53
76
|
version: '0'
|
54
77
|
type: :development
|
55
|
-
|
78
|
+
- !ruby/object:Gem::Dependency
|
56
79
|
version_requirements: !ruby/object:Gem::Requirement
|
57
80
|
none: false
|
58
81
|
requirements:
|
59
82
|
- - ! '>='
|
60
83
|
- !ruby/object:Gem::Version
|
61
84
|
version: '0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
85
|
name: rspec
|
86
|
+
prerelease: false
|
64
87
|
requirement: !ruby/object:Gem::Requirement
|
65
88
|
none: false
|
66
89
|
requirements:
|
@@ -68,15 +91,31 @@ dependencies:
|
|
68
91
|
- !ruby/object:Gem::Version
|
69
92
|
version: '0'
|
70
93
|
type: :development
|
71
|
-
|
94
|
+
- !ruby/object:Gem::Dependency
|
72
95
|
version_requirements: !ruby/object:Gem::Requirement
|
73
96
|
none: false
|
74
97
|
requirements:
|
75
98
|
- - ! '>='
|
76
99
|
- !ruby/object:Gem::Version
|
77
100
|
version: '0'
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
101
|
name: travis-lint
|
102
|
+
prerelease: false
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
type: :development
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
name: pry
|
118
|
+
prerelease: false
|
80
119
|
requirement: !ruby/object:Gem::Requirement
|
81
120
|
none: false
|
82
121
|
requirements:
|
@@ -84,13 +123,38 @@ dependencies:
|
|
84
123
|
- !ruby/object:Gem::Version
|
85
124
|
version: '0'
|
86
125
|
type: :development
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
name: pry-nav
|
87
134
|
prerelease: false
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
type: :development
|
142
|
+
- !ruby/object:Gem::Dependency
|
88
143
|
version_requirements: !ruby/object:Gem::Requirement
|
89
144
|
none: false
|
90
145
|
requirements:
|
91
146
|
- - ! '>='
|
92
147
|
- !ruby/object:Gem::Version
|
93
148
|
version: '0'
|
149
|
+
name: logging
|
150
|
+
prerelease: false
|
151
|
+
requirement: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ! '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
type: :development
|
94
158
|
description: A wrapper around Amazon's Simple Workflow Service
|
95
159
|
email:
|
96
160
|
- fred@snugghome.com
|
@@ -112,21 +176,23 @@ files:
|
|
112
176
|
- lib/aws/simple_workflow/decision_task_additions.rb
|
113
177
|
- lib/simpler_workflow.rb
|
114
178
|
- lib/simpler_workflow/activity.rb
|
179
|
+
- lib/simpler_workflow/activity_registry.rb
|
115
180
|
- lib/simpler_workflow/default_exception_reporter.rb
|
116
181
|
- lib/simpler_workflow/domain.rb
|
117
182
|
- lib/simpler_workflow/options_as_methods.rb
|
118
183
|
- lib/simpler_workflow/tasks.rb
|
119
184
|
- lib/simpler_workflow/version.rb
|
120
185
|
- lib/simpler_workflow/workflow.rb
|
121
|
-
- lib/simpler_workflow/workflow_collection.rb
|
122
186
|
- lib/tasks/simpler_workflow.rake
|
123
187
|
- simpler_workflow.gemspec
|
188
|
+
- spec/activity_spec.rb
|
124
189
|
- spec/domain_spec.rb
|
125
190
|
- spec/simpler_workflow_spec.rb
|
126
191
|
- spec/spec_helper.rb
|
192
|
+
- spec/workflow_spec.rb
|
127
193
|
homepage: https://github.com/fredjean/simpler_workflow
|
128
194
|
licenses: []
|
129
|
-
post_install_message: ! "simpler_workflow 0.
|
195
|
+
post_install_message: ! "simpler_workflow 0.3.0.beta\n========================\n\nHave
|
130
196
|
a look at https://github.com/fredjean/simpler_workflow/wiki/MIgrating-to-0.2.0 if
|
131
197
|
you\nare upgrading from a 0.1.x version of the gem. There is a fundamental change
|
132
198
|
in how the \nactivity and decision loops are run. You may need to adjust your application
|
@@ -140,19 +206,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
140
206
|
requirements:
|
141
207
|
- - ! '>='
|
142
208
|
- !ruby/object:Gem::Version
|
143
|
-
version:
|
144
|
-
segments:
|
145
|
-
- 0
|
146
|
-
hash: 618930098461104391
|
209
|
+
version: 1.9.0
|
147
210
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
211
|
none: false
|
149
212
|
requirements:
|
150
|
-
- - ! '
|
213
|
+
- - ! '>'
|
151
214
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
153
|
-
segments:
|
154
|
-
- 0
|
155
|
-
hash: 618930098461104391
|
215
|
+
version: 1.3.1
|
156
216
|
requirements: []
|
157
217
|
rubyforge_project:
|
158
218
|
rubygems_version: 1.8.23
|
@@ -161,6 +221,8 @@ specification_version: 3
|
|
161
221
|
summary: A wrapper and DSL around Amazon's Simple Workflow Service with the goal of
|
162
222
|
making it almost pleasant to define workflows.
|
163
223
|
test_files:
|
224
|
+
- spec/activity_spec.rb
|
164
225
|
- spec/domain_spec.rb
|
165
226
|
- spec/simpler_workflow_spec.rb
|
166
227
|
- spec/spec_helper.rb
|
228
|
+
- spec/workflow_spec.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module SimplerWorkflow
|
2
|
-
class WorkflowCollection
|
3
|
-
def [](name, version)
|
4
|
-
registry[[name,version]]
|
5
|
-
end
|
6
|
-
|
7
|
-
def []=(name, version, value)
|
8
|
-
registry[[name, version]] = value
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
def registry
|
13
|
-
@registry ||= {}
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|