simpler_workflow 0.2.7 → 0.3.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- 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
|