aws-flow 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzZjOTA1Y2MzMjE0MTg0N2I2ZjAwMjQ0ZjY0NDBhNGQ1YjhjMTA1NQ==
4
+ ZmU2NjA0NjgwNTFlYTY1N2IzNDYzNGI3Y2RkYWRlOWQyZjdmYTM1ZA==
5
5
  data.tar.gz: !binary |-
6
- MzI3ZjhmNTE4ZTZhNWFkOTc2NGFiYTgxYjhlN2JiMDNmYWIwYmUwYw==
6
+ ZTNkYzFmOWQwNzA3MzE1YzkyYjJiZGQwZTFiYjhmZDU2MjRjMTA2Nw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Mzc5NDdjMzcyMGZlNmZmODQ1YTMxYzU5ZTU2MjVhZDZhZjcyMWZmZjMzZDU0
10
- ODgyNmU3ZjdlZDk5MDc1MWYyMDVlY2IzZjk4NGFlN2Q2NDkwYTI1YjAxOWFl
11
- M2Q0NDQ3MDI3NTkyNzZiNTZiNGM5ZDYwNGZiMDM2MDhhMjRlMGQ=
9
+ NjZiZTRjNTA3MWQ5M2NiZGUyYmJiOTc2MWNlZjUyNjhlMzdmZjc3MmM4NTgw
10
+ YzE5NmEyM2U3MDdlN2FhODA0MjVkMzljYzY3NGE3YTdjNjNkODcwNjkzMzdh
11
+ MjZiMGQ5NGNkZWI0NzMyODhhZWYwZDFiMmU2Yjc2MTM5MDYzZWM=
12
12
  data.tar.gz: !binary |-
13
- Njk4Y2ZkMzUxNGY5ZGI3MjA1NGI2YTQ5N2QwYTBlZDFiMzU3ZWIxZDIxOGZl
14
- NjViN2YyZjE3ODgzZjBjMGNhYzA2YjU5MTllODI5ODdiMjFkZjQ4M2QzYTM1
15
- NzZhNmFmNTYxM2E2MTMyMTQyOGI5NjY5OTU0N2I0YzBiZGI3N2Q=
13
+ NThjYjAzMDkxMjYwYTU0OTE2MGJlOWJkZGVmYzE5NDA1YTQ1ZTRkNGMzNzg5
14
+ ZjVhYTIzMDUwOGQ4NTU1OGIzMDM1NjBlMjkzM2FiYTk4OGRjNzA5NzZlODIx
15
+ MTkxZGZlZWUwYTNjNWNlN2M0NDc4MWQ3ZGRhN2IyOThkNmEwNDY=
@@ -21,6 +21,15 @@ module AWS
21
21
  # `DecisionTaskHandler` and pass it to {WorkflowTaskPoller} on
22
22
  # {WorkflowTaskPoller#initialize construction}.
23
23
  class DecisionTaskHandler
24
+
25
+ class << self
26
+ # Factory method to create a DecisionTaskHandler instance given a
27
+ # workflow class
28
+ def from_workflow_class workflow_class
29
+ self.new(WorkflowDefinitionFactory.generate_definition_map(workflow_class))
30
+ end
31
+ end
32
+
24
33
  attr_reader :workflow_definition_map
25
34
 
26
35
  # Creates a new `DecisionTaskHandler`.
@@ -16,7 +16,7 @@
16
16
  module AWS
17
17
  module Flow
18
18
  def self.version
19
- "2.1.0"
19
+ "2.2.0"
20
20
  end
21
21
  end
22
22
  end
@@ -153,26 +153,15 @@ module AWS
153
153
  workflow_class.workflows.delete_if do |workflow_type|
154
154
  workflow_type.version.nil? || workflow_type.name.nil?
155
155
  end
156
+
157
+ @workflow_definition_map.merge!(
158
+ WorkflowDefinitionFactory.generate_definition_map(workflow_class)
159
+ )
160
+
156
161
  workflow_class.workflows.each do |workflow_type|
157
- options = workflow_type.options
158
- execution_method = options.execution_method
159
- version = workflow_type.version
160
- registration_options = options.get_registration_options
161
- implementation_options = nil
162
- get_state_method = workflow_class.get_state_method
163
- signals = workflow_class.signals
164
-
165
- @workflow_definition_map[workflow_type] = WorkflowDefinitionFactory.new(
166
- workflow_class,
167
- workflow_type,
168
- registration_options,
169
- options,
170
- execution_method,
171
- signals,
172
- get_state_method
173
- )
174
162
  # TODO should probably do something like
175
163
  # GenericWorkflowWorker#registerWorkflowTypes
164
+ options = workflow_type.options
176
165
  workflow_hash = options.get_options(
177
166
  [
178
167
  :default_task_start_to_close_timeout,
@@ -181,7 +170,7 @@ module AWS
181
170
  ], {
182
171
  :domain => @domain.name,
183
172
  :name => workflow_type.name,
184
- :version => version
173
+ :version => workflow_type.version
185
174
  }
186
175
  )
187
176
 
@@ -17,6 +17,38 @@ module AWS
17
17
  module Flow
18
18
 
19
19
  class WorkflowDefinitionFactory
20
+
21
+ class << self
22
+ # Method to create a workflow definition map from a workflow class
23
+ def generate_definition_map(workflow_class)
24
+
25
+ unless workflow_class.respond_to?(:workflows)
26
+ raise ArgumentError.new("workflow_class must extend module AWS::Flow::Workflows")
27
+ end
28
+
29
+ workflow_definition_map = {}
30
+
31
+ workflow_class.workflows.each do |workflow_type|
32
+ options = workflow_type.options
33
+ execution_method = options.execution_method
34
+ registration_options = options.get_registration_options
35
+ get_state_method = workflow_class.get_state_method
36
+ signals = workflow_class.signals
37
+
38
+ workflow_definition_map[workflow_type] = self.new(
39
+ workflow_class,
40
+ workflow_type,
41
+ registration_options,
42
+ options,
43
+ execution_method,
44
+ signals,
45
+ get_state_method
46
+ )
47
+ end
48
+ workflow_definition_map
49
+ end
50
+ end
51
+
20
52
  attr_reader :converter
21
53
  def initialize(klass, workflow_type, registration_options, implementation_options, workflow_method, signals, get_state_method)
22
54
  @klass = klass
@@ -0,0 +1,158 @@
1
+ module AWS
2
+ module Flow
3
+ module Replayer
4
+
5
+ # This class is used by the Replayer to fetch the DecisionTask which will
6
+ # be used by the DecisionTaskHandler. This is an 'abstract' class. We need
7
+ # to extend it and implement get_history_page and get_execution_info
8
+ # methods to use it.
9
+ class DecisionTaskProvider
10
+
11
+ # This method fetches the workflow history and wraps all the history events,
12
+ # workflow type, workflow execution inside a decision task for the
13
+ # decider to work on
14
+ def get_decision_task(replay_upto = nil)
15
+ # Get workflow execution info so that we can populate the workflowType
16
+ # and execution fields of the DecisionTask.
17
+ execution_info = get_execution_info
18
+ events = get_history
19
+
20
+ # Truncate history if replay_upto variable is set so that we only
21
+ # replay the history till the specified event
22
+ events = truncate_history(events, replay_upto)
23
+ return nil if events.nil?
24
+
25
+ # Generate the hash to instantiate a DecisionTask. We can set
26
+ # taskToken and nextPageToken to nil since we don't need the values
27
+ # in the replayer
28
+ data = {
29
+ 'taskToken' => nil,
30
+ 'workflowExecution' => execution_info["execution"],
31
+ 'workflowType' => execution_info["workflowType"],
32
+ 'events' => events,
33
+ 'nextPageToken' => nil
34
+ }
35
+ AWS::SimpleWorkflow::DecisionTask.new(nil, nil, data)
36
+ end
37
+
38
+ # This method truncates the workflow history to the event_id specified
39
+ # by the replay_upto variable
40
+ def truncate_history(events, replay_upto = nil)
41
+ return nil if events.nil? || events.empty?
42
+
43
+ # Just return the original array of events if replay_upto is not set
44
+ # or if the number of events is less than replay_upto
45
+ return events if replay_upto.nil? || events.last['eventId'] <= replay_upto
46
+
47
+ # Select the events whose eventId is lesser than replay_upto
48
+ truncated = events.select { |event| event['eventId'] <= replay_upto }
49
+ return nil if truncated.empty?
50
+ truncated
51
+ end
52
+
53
+ # This method is used to fetch the actual history. Implementing classes
54
+ # must override this method.
55
+ def get_history(page_token = nil); end
56
+
57
+ # This method is used to fetch the WorkflowExecutionInfo to fill in the
58
+ # DecisionTask details. Implementing classes must override this method
59
+ def get_execution_info; end
60
+
61
+ end
62
+
63
+ # This DecisionTaskProvider loads the decision task directly from the
64
+ # SimpleWorkflowService
65
+ class ServiceDecisionTaskProvider < DecisionTaskProvider
66
+ attr_reader :domain, :execution, :swf
67
+
68
+ def initialize(options = {})
69
+ raise ArgumentError.new("options hash must contain :domain") if options[:domain].nil?
70
+ raise ArgumentError.new("options hash must contain :execution") if options[:execution].nil?
71
+ @execution = options[:execution]
72
+ @domain = options[:domain]
73
+ @swf = AWS::SimpleWorkflow.new.client
74
+ end
75
+
76
+ def get_history
77
+ events = []
78
+ # Get the first page of the workflow history
79
+ page = get_history_page
80
+ page["events"].each { |x| events << x }
81
+
82
+ # Get the remaining pages of the workflow history
83
+ until page["nextPageToken"].nil?
84
+ page = get_history_page(page["nextPageToken"])
85
+ page["events"].each { |x| events << x }
86
+ end
87
+ events
88
+ end
89
+
90
+ # This method calls the service to fetch a page of workflow history
91
+ def get_history_page(page_token = nil)
92
+ # generate the request options for the service call. Optionally merge
93
+ # next_page_token to the hash if the page_token value is not nil.
94
+ request_opts = {
95
+ domain: @domain,
96
+ execution: @execution,
97
+ }.merge(page_token ? { next_page_token: page_token } : {})
98
+
99
+ @swf.get_workflow_execution_history(request_opts)
100
+ end
101
+
102
+ # This method calls the service to get the workflow execution
103
+ # information
104
+ def get_execution_info
105
+ execution = @swf.describe_workflow_execution(
106
+ domain: @domain,
107
+ execution: @execution
108
+ )
109
+ execution["executionInfo"]
110
+ end
111
+
112
+ end
113
+
114
+ # WorkflowReplayer is an AWS Flow Framework utility that is used to
115
+ # 'replay' a workflow history in the decider against the workflow
116
+ # implementation. It is a useful debugging tool.
117
+ #
118
+ # Usage -
119
+ #
120
+ # # Create an instance of the replayer with the required options -
121
+ #
122
+ # replayer = AWS::Flow::Replayer::WorkflowReplayer.new(
123
+ # domain: '<domain_name>',
124
+ # execution: {
125
+ # workflow_id: "<workflow_id",
126
+ # run_id: "<run_id>"
127
+ # },
128
+ # workflow_class: WorkflowClass
129
+ # )
130
+ #
131
+ # # Call the replay method (optionally) with the replay_upto event_id number -
132
+ #
133
+ # decision = replayer.replay(20)
134
+ #
135
+ class WorkflowReplayer
136
+ attr_reader :task_handler, :task_provider
137
+
138
+ def initialize(options)
139
+ raise ArgumentError.new("You must pass in an options hash") if options.nil?
140
+ raise ArgumentError.new("options hash must contain :workflow_class") if options[:workflow_class].nil?
141
+
142
+ # Create the service decision task helper to fetch and truncate the
143
+ # history
144
+ @task_provider = ServiceDecisionTaskProvider.new(options)
145
+ @task_handler = DecisionTaskHandler.from_workflow_class(options[:workflow_class])
146
+ end
147
+
148
+ # This method performs the actual replay.
149
+ def replay(replay_upto = nil)
150
+ task = @task_provider.get_decision_task(replay_upto)
151
+ @task_handler.handle_decision_task(task) unless task.nil?
152
+ end
153
+
154
+ end
155
+
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,91 @@
1
+ require "spec_helper"
2
+ include Test::Integ
3
+
4
+ describe Replayer do
5
+ before(:all) do
6
+
7
+ @swf, @domain = setup_swf("ReplayerTest")
8
+
9
+ class ReplayerTestActivity
10
+ extend Activities
11
+ activity :activity_a do
12
+ {
13
+ version: "1.0"
14
+ }
15
+ end
16
+ def activity_a; end
17
+ end
18
+
19
+ class ReplayerTestWorkflow
20
+ extend Workflows
21
+ workflow :small, :large do
22
+ {
23
+ version: "1.0",
24
+ default_execution_start_to_close_timeout: 600
25
+ }
26
+ end
27
+ activity_client(:client) { { from_class: "ReplayerTestActivity" } }
28
+ def small
29
+ client.activity_a
30
+ end
31
+ def large
32
+ 25.times { client.send_async(:activity_a) }
33
+ create_timer(1)
34
+ end
35
+ end
36
+
37
+ class ReplayerIntegTest
38
+ class << self
39
+ def run(domain, method)
40
+ workflow_worker = AWS::Flow::WorkflowWorker.new(domain.client, domain, "replayer_wf_tasklist", ReplayerTestWorkflow)
41
+ activity_worker = AWS::Flow::ActivityWorker.new(domain.client, domain, "replayer_act_tasklist", ReplayerTestActivity)
42
+ workflow_worker.register
43
+ activity_worker.register
44
+
45
+ executor = AWS::Flow::ForkingExecutor.new(max_workers: 5)
46
+ executor.execute { activity_worker.start }
47
+ executor.execute { workflow_worker.start }
48
+
49
+ client = AWS::Flow::workflow_client(domain.client, domain) { { from_class: "ReplayerTestWorkflow" } }
50
+ execution = client.send(method)
51
+ wait_for_execution(execution)
52
+ executor.shutdown(1)
53
+ execution
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ it "tests a small workflow history as a sanity test" do
60
+ execution = ReplayerIntegTest.run(@domain, :small)
61
+ replayer = WorkflowReplayer.new(
62
+ domain: @domain.name,
63
+ execution: {
64
+ workflow_id: execution.workflow_id,
65
+ run_id: execution.run_id
66
+ },
67
+ workflow_class: ReplayerTestWorkflow
68
+ )
69
+
70
+ replayer.replay(32)[:decisions].first[:decision_type].should == "CompleteWorkflowExecution"
71
+ end
72
+
73
+ it "tests a large workflow history to ensure paged histories are loaded correctly" do
74
+ execution = ReplayerIntegTest.run(@domain, :large)
75
+ replayer = WorkflowReplayer.new(
76
+ domain: @domain.name,
77
+ execution: {
78
+ workflow_id: execution.workflow_id,
79
+ run_id: execution.run_id
80
+ },
81
+ workflow_class: ReplayerTestWorkflow
82
+ )
83
+
84
+ decisions = replayer.replay(3)
85
+ decisions = decisions[:decisions].map{ |x| x[:decision_type] }
86
+ decisions.select { |x| x == "ScheduleActivityTask" }.size.should == 25
87
+ decisions.select { |x| x == "StartTimer" }.size.should == 1
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,290 @@
1
+ require "spec_helper"
2
+
3
+ describe Replayer do
4
+
5
+ describe DecisionTaskProvider do
6
+
7
+ context "#get_decision_task" do
8
+
9
+ it "constructs the correct DecisionTask object" do
10
+ task_provider = DecisionTaskProvider.new
11
+
12
+ allow(task_provider).to receive(:get_history).and_return(
13
+ ["event_1", "event_2", "event_3"]
14
+ )
15
+
16
+ AWS::SimpleWorkflow::HistoryEvent.stub(:new) { |x,y| y }
17
+
18
+ allow(task_provider).to receive(:get_execution_info).and_return({
19
+ 'execution' => {
20
+ 'workflowId' => 'workflow_id',
21
+ 'runId' => 'run_id'
22
+ },
23
+ 'workflowType' => {
24
+ 'name' => 'FooWorkflow',
25
+ 'version' => '1.0'
26
+ }
27
+ })
28
+
29
+ task = task_provider.get_decision_task
30
+ (task.is_a? AWS::SimpleWorkflow::DecisionTask).should be_true
31
+ task.workflow_execution.workflow_id.should == 'workflow_id'
32
+ task.workflow_execution.run_id.should == 'run_id'
33
+ task.workflow_type.name.should == 'FooWorkflow'
34
+ task.workflow_type.version.should == '1.0'
35
+ task.next_token.should be_nil
36
+ task.task_token.should be_nil
37
+ task.events.to_a.should == ["event_1", "event_2", "event_3"]
38
+
39
+ end
40
+
41
+ it "returns nil if event list is empty" do
42
+ task_provider = DecisionTaskProvider.new
43
+ allow(task_provider).to receive(:get_history_page).and_return([])
44
+ allow(task_provider).to receive(:get_execution_info).and_return({
45
+ 'execution'=> {
46
+ workflow_id: '',
47
+ run_id: ''
48
+ },
49
+ 'nextPageToken'=>'foo'
50
+ })
51
+ task = task_provider.get_decision_task
52
+ task.should be_nil
53
+ end
54
+
55
+ it "truncates history correctly" do
56
+ task_provider = DecisionTaskProvider.new
57
+
58
+ allow(task_provider).to receive(:get_history).and_return(
59
+ [ { "eventId" => 1 }, { "eventId" => 2 }, { "eventId" => 3 } ]
60
+ )
61
+
62
+ AWS::SimpleWorkflow::HistoryEvent.stub(:new) { |x,y| y }
63
+
64
+ allow(task_provider).to receive(:get_execution_info).and_return({
65
+ 'execution' => {
66
+ 'workflowId' => 'workflow_id',
67
+ 'runId' => 'run_id'
68
+ },
69
+ 'workflowType' => {
70
+ 'name' => 'FooWorkflow',
71
+ 'version' => '1.0'
72
+ }
73
+ })
74
+
75
+ task = task_provider.get_decision_task(2)
76
+ task.events.to_a.should == [ { "eventId" => 1 }, { "eventId" => 2 } ]
77
+
78
+ task = task_provider.get_decision_task(5)
79
+ task.events.to_a.should == [ { "eventId" => 1 }, { "eventId" => 2 }, { "eventId" => 3 } ]
80
+
81
+ task = task_provider.get_decision_task(0)
82
+ task.should be_nil
83
+
84
+ task = task_provider.get_decision_task(-1)
85
+ task.should be_nil
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ describe ServiceDecisionTaskProvider do
93
+
94
+ context "#get_history" do
95
+
96
+ it "concatenates paginated history correctly" do
97
+ task_provider = ServiceDecisionTaskProvider.new(
98
+ domain: 'foo',
99
+ execution: 'bar'
100
+ )
101
+
102
+ allow(task_provider).to receive(:get_history_page).and_return(
103
+ { 'events' => ["event_1", "event_2", "event_3"], 'nextPageToken' => "foo" },
104
+ )
105
+ allow(task_provider).to receive(:get_history_page).with("foo").and_return(
106
+ { 'events' => ["event_4", "event_5", "event_6"], 'nextPageToken' => nil },
107
+ )
108
+
109
+ history = task_provider.get_history
110
+ history.should == ["event_1", "event_2", "event_3", "event_4", "event_5", "event_6"]
111
+
112
+ end
113
+
114
+ it "returns nil if event list is empty" do
115
+ task_provider = ServiceDecisionTaskProvider.new(
116
+ domain: 'foo',
117
+ execution: 'bar'
118
+ )
119
+
120
+ allow(task_provider).to receive(:get_history_page).and_return(
121
+ {'events'=>[], 'nextPageToken'=>nil}
122
+ )
123
+
124
+ history = task_provider.get_history
125
+ history.should be_empty
126
+ end
127
+
128
+ end
129
+
130
+ context "#get_history_page" do
131
+
132
+ it "calls the service with the correct parameters" do
133
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125)
134
+ .to receive(:get_workflow_execution_history).once.with(
135
+ domain: 'foo',
136
+ execution: 'bar',
137
+ )
138
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125)
139
+ .to receive(:get_workflow_execution_history).once.with(
140
+ domain: 'foo',
141
+ execution: 'bar',
142
+ next_page_token: 'next_page'
143
+ )
144
+
145
+ task_provider = ServiceDecisionTaskProvider.new(
146
+ domain: 'foo',
147
+ execution: 'bar'
148
+ )
149
+
150
+ task_provider.get_history_page
151
+ task_provider.get_history_page("next_page")
152
+ end
153
+
154
+ end
155
+
156
+ context "#get_execution_info" do
157
+
158
+ it "calls the service with the correct parameters" do
159
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125)
160
+ .to receive(:describe_workflow_execution).once.with(
161
+ domain: 'foo',
162
+ execution: 'bar',
163
+ ).and_return( { "executionInfo" => "foo" } )
164
+
165
+ task_provider = ServiceDecisionTaskProvider.new(
166
+ domain: 'foo',
167
+ execution: 'bar'
168
+ )
169
+
170
+ task_provider.get_execution_info
171
+ end
172
+
173
+ end
174
+
175
+ end
176
+
177
+ describe WorkflowReplayer do
178
+
179
+ context "#initialize" do
180
+
181
+ it "initializes WorkflowReplayer with the correct options" do
182
+ expect{WorkflowReplayer.new(nil)}.to raise_error(ArgumentError)
183
+ expect{WorkflowReplayer.new({})}.to raise_error(ArgumentError)
184
+ end
185
+
186
+ it "initializes :task_handler correctly" do
187
+ class ReplayerTestWorkflowClass
188
+ extend AWS::Flow::Workflows
189
+ workflow :a, :b, :c do
190
+ {
191
+ version: "1.0",
192
+ }
193
+ end
194
+ end
195
+
196
+ expect_any_instance_of(AWS::SimpleWorkflow).to receive(:client).and_return(nil)
197
+ WorkflowDefinitionFactory.stub(:new).and_return("MyWorkflowDefinitionFactory")
198
+
199
+ replayer = WorkflowReplayer.new(
200
+ domain: 'Foo',
201
+ execution: 'Bar',
202
+ workflow_class: ReplayerTestWorkflowClass
203
+ )
204
+ (replayer.task_handler.is_a? DecisionTaskHandler).should be_true
205
+
206
+ definitons = replayer.task_handler.workflow_definition_map.map do |key, value|
207
+ [key.name, value]
208
+ end
209
+ definitons.should == [
210
+ ["ReplayerTestWorkflowClass.a", "MyWorkflowDefinitionFactory"],
211
+ ["ReplayerTestWorkflowClass.b", "MyWorkflowDefinitionFactory"],
212
+ ["ReplayerTestWorkflowClass.c", "MyWorkflowDefinitionFactory"],
213
+ ]
214
+
215
+ end
216
+
217
+ it "initializes :task_provider correctly" do
218
+ expect_any_instance_of(AWS::SimpleWorkflow).to receive(:client).and_return(nil)
219
+
220
+ DecisionTaskHandler.stub(:from_workflow_class)
221
+
222
+ replayer = WorkflowReplayer.new(
223
+ domain: 'Foo',
224
+ execution: 'Bar',
225
+ workflow_class: ReplayerTestWorkflowClass
226
+ )
227
+ (replayer.task_provider.is_a? ServiceDecisionTaskProvider).should be_true
228
+ replayer.task_provider.domain.should == 'Foo'
229
+ replayer.task_provider.execution.should == 'Bar'
230
+ replayer.task_provider.swf.should be_nil
231
+
232
+ end
233
+
234
+ end
235
+
236
+ context "#replay" do
237
+
238
+ before(:all) do
239
+ class ReplayerTestWorkflowClass
240
+ extend AWS::Flow::Workflows
241
+ workflow :a do
242
+ {
243
+ version: "1.0",
244
+ }
245
+ end
246
+ end
247
+ end
248
+
249
+ it "uses correct logic" do
250
+ expect_any_instance_of(AWS::SimpleWorkflow).to receive(:client).and_return(nil)
251
+ expect_any_instance_of(ServiceDecisionTaskProvider).to receive(:get_decision_task).and_return("foo")
252
+ expect_any_instance_of(DecisionTaskHandler).to receive(:handle_decision_task).with("foo")
253
+
254
+ WorkflowDefinitionFactory.stub(:new).and_return("MyWorkflowDefinitionFactory")
255
+
256
+ replayer = WorkflowReplayer.new(
257
+ domain: 'Foo',
258
+ execution: 'Bar',
259
+ workflow_class: ReplayerTestWorkflowClass
260
+ )
261
+
262
+ replayer.replay
263
+ end
264
+
265
+ it "can replay multiple times for same execution" do
266
+ expect_any_instance_of(AWS::SimpleWorkflow).to receive(:client).and_return(nil)
267
+ expect_any_instance_of(ServiceDecisionTaskProvider).to receive(:get_decision_task).with(nil).and_return("foo")
268
+ expect_any_instance_of(ServiceDecisionTaskProvider).to receive(:get_decision_task).with(1).and_return("foo")
269
+ expect_any_instance_of(ServiceDecisionTaskProvider).to receive(:get_decision_task).with(10).and_return("foo")
270
+ expect_any_instance_of(DecisionTaskHandler).to receive(:handle_decision_task).with("foo").exactly(3).times
271
+
272
+ WorkflowDefinitionFactory.stub(:new).and_return("MyWorkflowDefinitionFactory")
273
+
274
+ replayer = WorkflowReplayer.new(
275
+ domain: 'Foo',
276
+ execution: 'Bar',
277
+ workflow_class: ReplayerTestWorkflowClass
278
+ )
279
+
280
+ replayer.replay
281
+ replayer.replay(1)
282
+ replayer.replay(10)
283
+
284
+ end
285
+
286
+ end
287
+
288
+ end
289
+
290
+ end
@@ -16,9 +16,11 @@
16
16
  require 'bundler/setup'
17
17
  require 'aws/flow'
18
18
  require 'aws/decider'
19
+ require 'aws/replayer'
19
20
  require 'runner'
20
21
 
21
22
  include AWS::Flow
23
+ include AWS::Flow::Replayer
22
24
 
23
25
  def constantize(camel_case_word)
24
26
  names = camel_case_word.split('::')
@@ -77,7 +79,7 @@ module Test
77
79
  #ForkingExecutor.executors = []
78
80
  end
79
81
 
80
- def setup_swf
82
+ def setup_swf domain_name=nil
81
83
  current_date = Time.now.strftime("%d-%m-%Y")
82
84
  file_name = "/tmp/" + current_date
83
85
  if File.exists?(file_name)
@@ -89,13 +91,8 @@ module Test
89
91
  File.open(file_name, 'w+') {|f| f.write(last_run)}
90
92
  current_date = Time.now.strftime("%d-%m-%Y")
91
93
  swf = AWS::SimpleWorkflow.new
92
- $rubyflow_decider_domain = "rubyflow_#{current_date}-#{last_run}"
93
- begin
94
- domain = swf.domains.create($rubyflow_decider_domain, "10")
95
- rescue AWS::SimpleWorkflow::Errors::DomainAlreadyExistsFault => e
96
- domain = swf.domains[$rubyflow_decider_domain]
97
- end
98
- @swf, @domain = swf, domain
94
+ $rubyflow_decider_domain = domain_name || "rubyflow_#{current_date}-#{last_run}"
95
+ domain = setup_domain($rubyflow_decider_domain)
99
96
  return swf, domain
100
97
  end
101
98
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Steger, Paritosh Mohan, Jacques Thomas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-30 00:00:00.000000000 Z
11
+ date: 2014-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-v1
@@ -79,6 +79,7 @@ files:
79
79
  - lib/aws/flow/implementation.rb
80
80
  - lib/aws/flow/simple_dfa.rb
81
81
  - lib/aws/flow/tasks.rb
82
+ - lib/aws/replayer.rb
82
83
  - lib/aws/runner.rb
83
84
  - spec/aws/decider/integration/activity_spec.rb
84
85
  - spec/aws/decider/integration/integration_spec.rb
@@ -105,6 +106,8 @@ files:
105
106
  - spec/aws/flow/flow_spec.rb
106
107
  - spec/aws/flow/future_spec.rb
107
108
  - spec/aws/flow/simple_dfa_spec.rb
109
+ - spec/aws/replayer/integration/replayer_spec.rb
110
+ - spec/aws/replayer/unit/replayer_spec.rb
108
111
  - spec/aws/runner/integration/runner_integration_spec.rb
109
112
  - spec/aws/runner/unit/runner_unit_spec.rb
110
113
  - spec/spec_helper.rb