aws-flow 2.1.0 → 2.2.0

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.
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