aws-flow 1.3.0 → 2.0.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.
Files changed (48) hide show
  1. checksums.yaml +15 -0
  2. data/aws-flow.gemspec +1 -0
  3. data/lib/aws/decider/activity.rb +8 -6
  4. data/lib/aws/decider/async_decider.rb +1 -0
  5. data/lib/aws/decider/async_retrying_executor.rb +3 -3
  6. data/lib/aws/decider/decider.rb +16 -14
  7. data/lib/aws/decider/executor.rb +35 -22
  8. data/lib/aws/decider/flow_defaults.rb +28 -14
  9. data/lib/aws/decider/generic_client.rb +3 -4
  10. data/lib/aws/decider/options.rb +91 -117
  11. data/lib/aws/decider/state_machines.rb +1 -0
  12. data/lib/aws/decider/utilities.rb +15 -0
  13. data/lib/aws/decider/version.rb +1 -1
  14. data/lib/aws/decider/worker.rb +14 -8
  15. data/lib/aws/decider/workflow_client.rb +16 -11
  16. data/lib/aws/runner.rb +43 -39
  17. data/spec/aws/decider/integration/activity_spec.rb +345 -0
  18. data/spec/aws/{integration → decider/integration}/integration_spec.rb +818 -1183
  19. data/spec/aws/decider/integration/setup.rb +3 -0
  20. data/spec/aws/decider/unit/activity_spec.rb +233 -0
  21. data/spec/aws/decider/unit/async_retrying_executor_spec.rb +131 -0
  22. data/spec/aws/{unit → decider/unit}/decider_spec.rb +171 -718
  23. data/spec/aws/decider/unit/executor_spec.rb +123 -0
  24. data/spec/aws/decider/unit/flow_defaults_spec.rb +62 -0
  25. data/spec/aws/decider/unit/misc_spec.rb +101 -0
  26. data/spec/aws/decider/unit/options_spec.rb +289 -0
  27. data/spec/aws/decider/unit/retry_spec.rb +217 -0
  28. data/spec/aws/{unit → decider/unit}/rubyflow.rb +0 -0
  29. data/spec/aws/decider/unit/setup.rb +3 -0
  30. data/spec/aws/decider/unit/worker_spec.rb +325 -0
  31. data/spec/aws/decider/unit/workflow_client_spec.rb +83 -0
  32. data/spec/aws/{unit → flow}/async_backtrace_spec.rb +0 -0
  33. data/spec/aws/{unit → flow}/async_scope_spec.rb +0 -0
  34. data/spec/aws/{unit → flow}/begin_rescue_ensure_spec.rb +1 -0
  35. data/spec/aws/{unit → flow}/external_task_spec.rb +0 -0
  36. data/spec/aws/{unit → flow}/factories.rb +0 -0
  37. data/spec/aws/{unit → flow}/fiber_condition_variable_spec.rb +0 -0
  38. data/spec/aws/{unit → flow}/fiber_spec.rb +0 -0
  39. data/spec/aws/{unit → flow}/flow_spec.rb +0 -0
  40. data/spec/aws/{unit → flow}/future_spec.rb +0 -0
  41. data/spec/aws/{unit → flow}/simple_dfa_spec.rb +0 -0
  42. data/spec/aws/{integration → runner/integration}/runner_integration_spec.rb +16 -43
  43. data/spec/aws/{unit → runner/unit}/runner_unit_spec.rb +18 -18
  44. data/spec/spec_helper.rb +264 -2
  45. metadata +37 -28
  46. data/spec/aws/unit/executor_spec.rb +0 -49
  47. data/spec/aws/unit/options_spec.rb +0 -293
  48. data/spec/aws/unit/preinclude_tests.rb +0 -149
@@ -0,0 +1,83 @@
1
+ require_relative 'setup'
2
+
3
+
4
+ describe WorkflowClient do
5
+
6
+ class TestWorkflow
7
+ extend AWS::Flow::Workflows
8
+
9
+ workflow :start
10
+ def start
11
+ return "This is the entry point"
12
+ end
13
+ end
14
+ before(:each) do
15
+ workflow_type_object = double("workflow_type", :name => "TestWorkflow.start", :start_execution => "" )
16
+ @client = WorkflowClient.new(FakeServiceClient.new, FakeDomain.new(workflow_type_object), TestWorkflow, StartWorkflowOptions.new)
17
+ end
18
+ it "makes sure that configure works correctly" do
19
+ @client.reconfigure(:start) {{ :task_list => "This nonsense" }}
20
+ @client.start
21
+ end
22
+
23
+ context "#start_workflow" do
24
+
25
+ before(:all) do
26
+ class WorkflowClientTestWorkflow
27
+ extend AWS::Flow::Workflows
28
+ workflow :workflow_a, :workflow_b do
29
+ {
30
+ version: "1.0",
31
+ default_execution_start_to_close_timeout: 600,
32
+ default_task_list: "tasklist_a"
33
+ }
34
+ end
35
+ workflow :workflow_c do
36
+ {
37
+ version: "1.0",
38
+ default_execution_start_to_close_timeout: 300,
39
+ default_task_list: "tasklist_c"
40
+ }
41
+ end
42
+ end
43
+ end
44
+
45
+ context "multiple workflow definitions in a single workflow class" do
46
+
47
+ it "ensures we can have multiple workflows in one class - by calling the first workflow" do
48
+ type = FakeWorkflowType.new("domain", "WorkflowClientTestWorkflow.workflow_a", "1.0")
49
+ domain = FakeDomain.new(type)
50
+ swf = AWS::SimpleWorkflow.new
51
+ client = AWS::Flow::workflow_client(swf.client, domain) { { from_class: "WorkflowClientTestWorkflow" } }
52
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125).to receive(:start_workflow_execution).twice { |options| options[:workflow_type][:name].should == "WorkflowClientTestWorkflow.workflow_a"; { run_id: "run_id" } }
53
+ client.start_execution
54
+ client.workflow_a
55
+ end
56
+
57
+ it "ensures we can have multiple workflows in one class - by calling the second workflow" do
58
+ type = FakeWorkflowType.new("domain", "WorkflowClientTestWorkflow.workflow_c", "1.0")
59
+ domain = FakeDomain.new(type)
60
+ swf = AWS::SimpleWorkflow.new
61
+ client = AWS::Flow::workflow_client(swf.client, domain) { { from_class: "WorkflowClientTestWorkflow" } }
62
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125).to receive(:start_workflow_execution) { |options| options[:workflow_type][:name].should == "WorkflowClientTestWorkflow.workflow_c"; { run_id: "run_id" } }
63
+ client.workflow_c
64
+ end
65
+
66
+ it "ensures we can define multiple workflows with same options" do
67
+
68
+ type = FakeWorkflowType.new("domain", "WorkflowClientTestWorkflow.workflow_a", "1.0")
69
+ domain = FakeDomain.new(type)
70
+ swf = AWS::SimpleWorkflow.new
71
+ client = AWS::Flow::workflow_client(swf.client, domain) { { from_class: "WorkflowClientTestWorkflow" } }
72
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125).to receive(:start_workflow_execution) { |options| options[:workflow_type][:name].should == "WorkflowClientTestWorkflow.workflow_a"; { run_id: "run_id" } }
73
+ expect_any_instance_of(AWS::SimpleWorkflow::Client::V20120125).to receive(:start_workflow_execution) { |options| options[:workflow_type][:name].should == "WorkflowClientTestWorkflow.workflow_b"; { run_id: "run_id" } }
74
+ client.workflow_a
75
+ client.workflow_b
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
82
+
83
+
@@ -13,6 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  ##
15
15
 
16
+ require_relative 'factories'
16
17
 
17
18
  def change_test(options = {})
18
19
  subject { this_bre }
File without changes
File without changes
File without changes
File without changes
@@ -1,51 +1,22 @@
1
- require 'runner'
2
- require 'bundler/setup'
3
- require 'aws/decider'
1
+ require 'spec_helper'
4
2
  require 'logger'
5
3
  require 'socket'
4
+ include Test::Integ
6
5
 
7
6
  describe "Runner" do
8
-
9
- # Copied from the utilities for the samples and recipes
10
- module SharedUtils
11
-
12
- def setup_domain(domain_name)
13
- swf = AWS::SimpleWorkflow.new
14
- domain = swf.domains[domain_name]
15
- unless domain.exists?
16
- swf.domains.create(domain_name, 10)
17
- end
18
- domain
19
- end
20
-
21
- def build_workflow_worker(domain, klass, task_list)
22
- AWS::Flow::WorkflowWorker.new(domain.client, domain, task_list, klass)
23
- end
24
-
25
- def build_generic_activity_worker(domain, task_list)
26
- AWS::Flow::ActivityWorker.new(domain.client, domain, task_list)
27
- end
28
-
29
- def build_activity_worker(domain, klass, task_list)
30
- AWS::Flow::ActivityWorker.new(domain.client, domain, task_list, klass)
31
- end
32
-
33
- def build_workflow_client(domain, options_hash)
34
- AWS::Flow::workflow_client(domain.client, domain) { options_hash }
35
- end
7
+ before(:all) do
8
+ @swf, @domain = setup_swf
36
9
  end
37
10
 
38
11
  class PingUtils
39
- include SharedUtils
40
12
 
41
13
  WF_VERSION = "1.0"
42
14
  ACTIVITY_VERSION = "1.0"
43
15
  WF_TASKLIST = "workflow_tasklist"
44
16
  ACTIVITY_TASKLIST = "activity_tasklist"
45
- DOMAIN = "PingTest"
46
17
 
47
18
  def initialize
48
- @domain = setup_domain(DOMAIN)
19
+ @domain = Test::Integ::get_test_domain
49
20
  end
50
21
 
51
22
  def activity_worker
@@ -91,8 +62,8 @@ describe "Runner" do
91
62
  workflow :ping do
92
63
  {
93
64
  version: PingUtils::WF_VERSION,
94
- task_list: PingUtils::WF_TASKLIST,
95
- execution_start_to_close_timeout: 30,
65
+ default_task_list: PingUtils::WF_TASKLIST,
66
+ default_execution_start_to_close_timeout: 600,
96
67
  }
97
68
  end
98
69
 
@@ -136,10 +107,14 @@ describe "Runner" do
136
107
  it "runs" do
137
108
 
138
109
  runner_config = JSON.parse('{
110
+ "domain":
111
+ {
112
+ "name": ' + "\"#{get_test_domain.name}\"" + ',
113
+ "retention_in_days": 10
114
+ },
139
115
  "workflow_paths": [],
140
116
  "workflow_workers": [
141
117
  {
142
- "domain": ' + "\"#{PingUtils::DOMAIN}\"" + ',
143
118
  "task_list": ' + "\"#{PingUtils::WF_TASKLIST}\"" + ',
144
119
  "workflow_classes": [ ' + "\"PingWorkflow\"" + ' ],
145
120
  "number_of_workers": 1
@@ -148,7 +123,6 @@ describe "Runner" do
148
123
  "activity_paths": [],
149
124
  "activity_workers": [
150
125
  {
151
- "domain": ' + "\"#{PingUtils::DOMAIN}\"" + ',
152
126
  "task_list": ' + "\"#{PingUtils::ACTIVITY_TASKLIST}\"" + ',
153
127
  "activity_classes": [ ' + "\"PingActivity\"" + ' ],
154
128
  "number_of_forks_per_worker": 1,
@@ -162,16 +136,15 @@ describe "Runner" do
162
136
 
163
137
  workers = AWS::Flow::Runner.start_workers("", runner_config)
164
138
 
139
+ sleep 2
165
140
  utils = PingUtils.new
166
141
  wf_client = utils.workflow_client
167
142
 
168
143
  workflow_execution = wf_client.ping()
169
144
 
170
- sleep 3 until [
171
- "WorkflowExecutionCompleted",
172
- "WorkflowExecutionTimedOut",
173
- "WorkflowExecutionFailed"
174
- ].include? workflow_execution.events.to_a.last.event_type
145
+ wait_for_execution(workflow_execution, 3)
146
+
147
+ workflow_execution.events.map(&:event_type).last.should == "WorkflowExecutionCompleted"
175
148
 
176
149
  # kill the workers
177
150
  workers.each { |w| Process.kill("KILL", w) }
@@ -1,8 +1,7 @@
1
- require 'runner'
1
+ require 'spec_helper'
2
2
  require 'tempfile'
3
3
  require 'socket'
4
4
  require 'fileutils'
5
- require_relative '../../spec_helper.rb'
6
5
 
7
6
  describe "Runner" do
8
7
 
@@ -55,7 +54,6 @@ describe "Runner" do
55
54
  "activity_paths": [],
56
55
  "activity_workers": [
57
56
  {
58
- "domain": "foo",
59
57
  "task_list": "bar",
60
58
  "activity_classes": [],
61
59
  "number_of_workers": 3
@@ -79,7 +77,6 @@ describe "Runner" do
79
77
  "activity_paths": [],
80
78
  "activity_workers": [
81
79
  {
82
- "domain": "foo",
83
80
  "task_list": "bar",
84
81
  "number_of_workers": 3
85
82
  }
@@ -102,7 +99,6 @@ describe "Runner" do
102
99
  "workflow_paths": [],
103
100
  "workflow_workers": [
104
101
  {
105
- "domain": "foo",
106
102
  "task_list": "bar",
107
103
  "workflow_classes": [],
108
104
  "number_of_workers": 3
@@ -126,7 +122,6 @@ describe "Runner" do
126
122
  "workflow_paths": [],
127
123
  "workflow_workers": [
128
124
  {
129
- "domain": "foo",
130
125
  "task_list": "bar",
131
126
  "number_of_workers": 3
132
127
  }
@@ -153,7 +148,6 @@ describe "Runner" do
153
148
  "workflow_paths": [],
154
149
  "workflow_workers": [
155
150
  {
156
- "domain": "foo",
157
151
  "task_list": "bar",
158
152
  "workflow_classes": [ "Object", "String" ],
159
153
  "number_of_workers": 3
@@ -168,7 +162,6 @@ describe "Runner" do
168
162
  "activity_paths": [],
169
163
  "activity_workers": [
170
164
  {
171
- "domain": "foo",
172
165
  "task_list": "bar",
173
166
  "activity_classes": [ "Object", "String" ],
174
167
  "number_of_workers": 3
@@ -182,6 +175,8 @@ describe "Runner" do
182
175
  # mock out a few methods to focus on the fact that the workers were created
183
176
  allow_any_instance_of(AWS::Flow::WorkflowWorker).to receive(:add_implementation).and_return(nil)
184
177
  allow_any_instance_of(AWS::Flow::WorkflowWorker).to receive(:start).and_return(nil)
178
+
179
+ AWS::Flow::Runner.stub(:setup_domain)
185
180
  AWS::Flow::Runner.stub(:load_files)
186
181
 
187
182
  # what we are testing:
@@ -197,6 +192,7 @@ describe "Runner" do
197
192
  # mock out a few methods to focus on the fact that the workers were created
198
193
  allow_any_instance_of(AWS::Flow::ActivityWorker).to receive(:add_implementation).and_return(nil)
199
194
  allow_any_instance_of(AWS::Flow::ActivityWorker).to receive(:start).and_return(nil)
195
+ AWS::Flow::Runner.stub(:setup_domain)
200
196
  AWS::Flow::Runner.stub(:load_files)
201
197
 
202
198
  # what we are testing:
@@ -211,6 +207,7 @@ describe "Runner" do
211
207
  allow_any_instance_of(AWS::Flow::WorkflowWorker).to receive(:start).and_return(nil)
212
208
  AWS::Flow::Runner.stub(:fork)
213
209
  AWS::Flow::Runner.stub(:load_files)
210
+ AWS::Flow::Runner.stub(:setup_domain)
214
211
 
215
212
  # stub that we can query later
216
213
  implems = []
@@ -230,6 +227,7 @@ describe "Runner" do
230
227
  allow_any_instance_of(AWS::Flow::ActivityWorker).to receive(:start).and_return(nil)
231
228
  AWS::Flow::Runner.stub(:fork)
232
229
  AWS::Flow::Runner.stub(:load_files)
230
+ AWS::Flow::Runner.stub(:setup_domain)
233
231
 
234
232
  # stub that we can query later
235
233
  implems = []
@@ -249,6 +247,7 @@ describe "Runner" do
249
247
  allow_any_instance_of(AWS::Flow::WorkflowWorker).to receive(:add_implementation).and_return(nil)
250
248
  AWS::Flow::Runner.stub(:fork).and_yield
251
249
  AWS::Flow::Runner.stub(:load_files)
250
+ AWS::Flow::Runner.stub(:setup_domain)
252
251
 
253
252
  # stub that we can query later
254
253
  starts = 0
@@ -268,6 +267,7 @@ describe "Runner" do
268
267
  allow_any_instance_of(AWS::Flow::ActivityWorker).to receive(:add_implementation).and_return(nil)
269
268
  AWS::Flow::Runner.stub(:fork).and_yield
270
269
  AWS::Flow::Runner.stub(:load_files)
270
+ AWS::Flow::Runner.stub(:setup_domain)
271
271
 
272
272
  # stub that we can query later
273
273
  starts = 0
@@ -303,8 +303,8 @@ describe "Runner" do
303
303
  expect(AWS::Flow::Runner).to receive(:require).with(File.join(base, relative))
304
304
 
305
305
  AWS::Flow::Runner.load_files( File.join(base, "blahconfig"), "",
306
- {:config_key => "any_key_name",
307
- :default_file => relative})
306
+ {config_key: "any_key_name",
307
+ default_file: relative})
308
308
  end
309
309
 
310
310
  it "loads the default only if needed" do
@@ -317,8 +317,8 @@ describe "Runner" do
317
317
 
318
318
  AWS::Flow::Runner.load_files( File.join(base, "blahconfig"),
319
319
  JSON.parse('{ "activity_paths": [ "foo", "bar"] }'),
320
- {:config_key => "activity_paths",
321
- :default_file => relative})
320
+ {config_key: "activity_paths",
321
+ default_file: relative})
322
322
  end
323
323
 
324
324
  it "loads the \"flow/activities.rb\" by default for activity worker" do
@@ -326,7 +326,6 @@ describe "Runner" do
326
326
  document = '{
327
327
  "activity_workers": [
328
328
  {
329
- "domain": "foo",
330
329
  "task_list": "bar",
331
330
  "activity_classes": [ "Object", "String" ],
332
331
  "number_of_workers": 3
@@ -336,6 +335,7 @@ describe "Runner" do
336
335
  JSON.parse(document)
337
336
  end
338
337
 
338
+ AWS::Flow::Runner.stub(:setup_domain)
339
339
  expect(AWS::Flow::Runner).to receive(:require).with(File.join(".", "flow", "activities.rb"))
340
340
 
341
341
  AWS::Flow::Runner.start_activity_workers(AWS::SimpleWorkflow.new, ".", activity_js)
@@ -346,7 +346,6 @@ describe "Runner" do
346
346
  document = '{
347
347
  "workflow_workers": [
348
348
  {
349
- "domain": "foo",
350
349
  "task_list": "bar",
351
350
  "workflow_classes": [ "Object", "String" ],
352
351
  "number_of_workers": 3
@@ -356,6 +355,7 @@ describe "Runner" do
356
355
  JSON.parse(document)
357
356
  end
358
357
 
358
+ AWS::Flow::Runner.stub(:setup_domain)
359
359
  expect(AWS::Flow::Runner).to receive(:require).with(File.join(".", "flow", "workflows.rb"))
360
360
 
361
361
  AWS::Flow::Runner.start_workflow_workers(AWS::SimpleWorkflow.new, ".", workflow_js)
@@ -367,7 +367,6 @@ describe "Runner" do
367
367
  "activity_paths": [ "foo", "bar"],
368
368
  "activity_workers": [
369
369
  {
370
- "domain": "foo",
371
370
  "task_list": "bar",
372
371
  "activity_classes": [ "Object", "String" ],
373
372
  "number_of_workers": 3
@@ -377,6 +376,7 @@ describe "Runner" do
377
376
  JSON.parse(document)
378
377
  end
379
378
 
379
+ AWS::Flow::Runner.stub(:setup_domain)
380
380
  expect(AWS::Flow::Runner).to_not receive(:require).with(File.join(".", "flow", "activities.rb"))
381
381
  expect(AWS::Flow::Runner).to receive(:require).with(File.join("foo"))
382
382
  expect(AWS::Flow::Runner).to receive(:require).with(File.join("bar"))
@@ -390,7 +390,6 @@ describe "Runner" do
390
390
  "workflow_paths": [ "foo", "bar"],
391
391
  "workflow_workers": [
392
392
  {
393
- "domain": "foo",
394
393
  "task_list": "bar",
395
394
  "workflow_classes": [ "Object", "String" ],
396
395
  "number_of_workers": 3
@@ -400,6 +399,7 @@ describe "Runner" do
400
399
  JSON.parse(document)
401
400
  end
402
401
 
402
+ AWS::Flow::Runner.stub(:setup_domain)
403
403
  expect(AWS::Flow::Runner).to_not receive(:require).with(File.join(".", "flow", "workflows.rb"))
404
404
  expect(AWS::Flow::Runner).to receive(:require).with(File.join("foo"))
405
405
  expect(AWS::Flow::Runner).to receive(:require).with(File.join("bar"))
@@ -467,7 +467,6 @@ describe "Runner" do
467
467
  document = '{
468
468
  "activity_workers": [
469
469
  {
470
- "domain": "foo",
471
470
  "task_list": "bar",
472
471
  "number_of_workers": 3
473
472
  }
@@ -476,6 +475,7 @@ describe "Runner" do
476
475
  JSON.parse(document)
477
476
  end
478
477
 
478
+ AWS::Flow::Runner.stub(:setup_domain)
479
479
  impls = []
480
480
  AWS::Flow::ActivityWorker.any_instance.stub(:add_implementation) do |impl|
481
481
  impls << impl
@@ -492,7 +492,6 @@ describe "Runner" do
492
492
  document = '{
493
493
  "workflow_workers": [
494
494
  {
495
- "domain": "foo",
496
495
  "task_list": "bar",
497
496
  "number_of_workers": 3
498
497
  }
@@ -501,6 +500,7 @@ describe "Runner" do
501
500
  JSON.parse(document)
502
501
  end
503
502
 
503
+ AWS::Flow::Runner.stub(:setup_domain)
504
504
  impls = []
505
505
  AWS::Flow::WorkflowWorker.any_instance.stub(:add_implementation) do |impl|
506
506
  impls << impl
@@ -13,11 +13,12 @@
13
13
  # permissions and limitations under the License.
14
14
  ##
15
15
 
16
+ require 'bundler/setup'
16
17
  require 'aws/flow'
17
18
  require 'aws/decider'
19
+ require 'runner'
18
20
 
19
- include AWS::Flow::Core
20
-
21
+ include AWS::Flow
21
22
 
22
23
  def constantize(camel_case_word)
23
24
  names = camel_case_word.split('::')
@@ -28,3 +29,264 @@ def constantize(camel_case_word)
28
29
  end
29
30
  constant
30
31
  end
32
+
33
+ module Test
34
+ module Integ
35
+ def setup_domain(domain_name)
36
+ swf = AWS::SimpleWorkflow.new
37
+ domain = swf.domains[domain_name]
38
+ unless domain.exists?
39
+ swf.domains.create(domain_name, 10)
40
+ end
41
+ domain
42
+ end
43
+
44
+ def build_client(from_class)
45
+ domain = get_test_domain
46
+ build_workflow_client(domain, from_class)
47
+ end
48
+
49
+ def build_worker(klass, task_list)
50
+ domain = get_test_domain
51
+ return build_workflow_worker(domain, klass, task_list) if klass.is_a? AWS::Flow::Workflows
52
+ return build_activity_worker(domain, klass, task_list) if klass.is_a? AWS::Flow::Activities
53
+ raise "the class needs to extend AWS::Flow::Workflows or AWS::Flow::Activities"
54
+ end
55
+
56
+ def build_workflow_worker(domain, klass, task_list)
57
+ AWS::Flow::WorkflowWorker.new(domain.client, domain, task_list, klass)
58
+ end
59
+
60
+ def build_generic_activity_worker(domain, task_list)
61
+ AWS::Flow::ActivityWorker.new(domain.client, domain, task_list)
62
+ end
63
+
64
+ def build_activity_worker(domain, klass, task_list)
65
+ AWS::Flow::ActivityWorker.new(domain.client, domain, task_list, klass)
66
+ end
67
+
68
+ def build_workflow_client(domain, options_hash)
69
+ AWS::Flow::workflow_client(domain.client, domain) { options_hash }
70
+ end
71
+ def kill_executors
72
+ return if ForkingExecutor.executors.nil?
73
+ ForkingExecutor.executors.each do |executor|
74
+ executor.shutdown(0) unless executor.is_shutdown rescue StandardError
75
+ end
76
+ #TODO Reinstate this, but it's useful to keep them around for debugging
77
+ #ForkingExecutor.executors = []
78
+ end
79
+
80
+ def setup_swf
81
+ current_date = Time.now.strftime("%d-%m-%Y")
82
+ file_name = "/tmp/" + current_date
83
+ if File.exists?(file_name)
84
+ last_run = File.open(file_name, 'r').read.to_i
85
+ else
86
+ last_run = 0
87
+ end
88
+ last_run += 1
89
+ File.open(file_name, 'w+') {|f| f.write(last_run)}
90
+ current_date = Time.now.strftime("%d-%m-%Y")
91
+ 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
99
+ return swf, domain
100
+ end
101
+
102
+ def get_test_domain
103
+ swf = AWS::SimpleWorkflow.new
104
+ domain = swf.domains[$rubyflow_decider_domain]
105
+ return domain
106
+ end
107
+
108
+ def wait_for_execution(execution, sleep_time=5)
109
+ sleep sleep_time until [
110
+ "WorkflowExecutionCompleted",
111
+ "WorkflowExecutionTimedOut",
112
+ "WorkflowExecutionFailed"
113
+ ].include? execution.events.to_a.last.event_type
114
+ end
115
+
116
+ def wait_for_decision(execution, decision="DecisionTaskScheduled")
117
+ sleep 1 until [
118
+ decision
119
+ ].flatten.include? execution.events.to_a.last.event_type
120
+ end
121
+
122
+ def validate_execution(execution, decision="WorkflowExecutionCompleted")
123
+ execution.events.map(&:event_type).last.should == decision
124
+ end
125
+ def validate_execution_failed(execution)
126
+ validate_execution(execution, "WorkflowExecutionFailed")
127
+ end
128
+ end
129
+
130
+ module Unit
131
+
132
+ class FakeConfig
133
+ def to_h
134
+
135
+ end
136
+ end
137
+ class FakeServiceClient
138
+ attr_accessor :trace
139
+
140
+ def respond_decision_task_completed(task_completed_request)
141
+ @trace ||= []
142
+ @trace << task_completed_request
143
+ end
144
+ def start_workflow_execution(options)
145
+ FakeWorkflowExecution.new(nil, options[:workflow_id])
146
+ end
147
+ def register_activity_type(options)
148
+ end
149
+ def register_workflow_type(options)
150
+ end
151
+ def respond_activity_task_completed(task_token, result)
152
+ end
153
+ def config
154
+ FakeConfig.new
155
+ end
156
+ end
157
+
158
+ class FakeAttribute
159
+ def initialize(data); @data = data; end
160
+ def method_missing(method_name, *args, &block)
161
+ if @data.keys.include? method_name
162
+ return @data[method_name]
163
+ end
164
+ super
165
+ end
166
+ def keys; @data.keys; end
167
+ def [](key); @data[key]; end
168
+ def to_h; @data; end
169
+ def []=(key, val); @data[key] = val; end
170
+ end
171
+ class TestHistoryEvent < AWS::SimpleWorkflow::HistoryEvent
172
+ def initialize(event_type, event_id, attributes)
173
+ @event_type = event_type
174
+ @attributes = attributes
175
+ @event_id = event_id
176
+ @created_at = Time.now
177
+ end
178
+ end
179
+
180
+ class FakeWorkflowType < WorkflowType
181
+ class << self
182
+ attr_accessor :types
183
+ end
184
+ attr_accessor :domain, :name, :version
185
+ def initialize(domain, name, version)
186
+ @domain = domain
187
+ @name = name
188
+ @version = version
189
+ FakeWorkflowType.types ||= {}
190
+ FakeWorkflowType.types["#{name}.#{version}"] = self
191
+ end
192
+ end
193
+
194
+ class TestHistoryWrapper
195
+ attr_accessor :workflow_execution, :workflow_type, :events
196
+ def initialize(workflow_type, workflow_execution, events)
197
+ @workflow_type = workflow_type
198
+ @workflow_execution = workflow_execution
199
+ @events = events
200
+ end
201
+ def task_token
202
+ "1"
203
+ end
204
+ def previous_started_event_id
205
+ 1
206
+ end
207
+ end
208
+
209
+ class FakeEvents
210
+ def initialize(args)
211
+ @events = []
212
+ args.each_with_index do |event, index|
213
+ event, attr = event if event.is_a? Array
214
+ attr ||= {}
215
+ @events << TestHistoryEvent.new(event, index + 1, FakeAttribute.new(attr))
216
+ end
217
+ @events
218
+ end
219
+ def to_a
220
+ @events
221
+ end
222
+ end
223
+ class TrivialConverter
224
+ def dump(x)
225
+ x
226
+ end
227
+ def load(x)
228
+ x
229
+ end
230
+ end
231
+
232
+ class FakeLogger
233
+ attr_accessor :level
234
+ def info(s); end
235
+ def debug(s); end
236
+ def warn(s); end
237
+ def error(s); end
238
+ end
239
+
240
+ class FakePage
241
+ def initialize(object); @object = object; end
242
+ def page; @object; end
243
+ end
244
+
245
+ class FakeWorkflowExecution
246
+ class << self
247
+ attr_accessor :executions
248
+ end
249
+ def initialize(run_id, workflow_id)
250
+ @hash = {}
251
+ @run_id = run_id.nil? ? SecureRandom.uuid : run_id
252
+ @workflow_id = workflow_id.nil? ? SecureRandom.uuid : workflow_id
253
+ @hash = {"runId" => @run_id, "workflowId" => @workflow_id}
254
+ FakeWorkflowExecution.executions ||= {}
255
+ FakeWorkflowExecution.executions[[@run_id, @workflow_id]] = self
256
+ end
257
+ def self.at(workflow_id, run_id)
258
+ FakeWorkflowExecution.executions[[run_id, workflow_id]] unless FakeWorkflowExecution.executions.nil?
259
+ end
260
+ def [](option)
261
+ self.hash[option]
262
+ end
263
+ attr_accessor :run_id, :workflow_id, :task_list, :domain, :hash
264
+ end
265
+
266
+ class FakeDomain
267
+ def initialize(workflow_type_object = nil)
268
+ @workflow_type_object ||= []
269
+ @workflow_type_object << workflow_type_object unless workflow_type_object.nil?
270
+ @name = "fake_domain"
271
+ end
272
+ def register(workflow_type_object)
273
+ @workflow_type_object << workflow_type_object
274
+ end
275
+ def page; FakePage.new(@workflow_type_object); end
276
+ def workflow_executions; FakeWorkflowExecution; end
277
+ attr_accessor :name
278
+ end
279
+
280
+ class SynchronousWorkflowWorker < WorkflowWorker
281
+ def start
282
+ poller = SynchronousWorkflowTaskPoller.new(@service, nil, DecisionTaskHandler.new(@workflow_definition_map), @task_list)
283
+ poller.poll_and_process_single_task
284
+ end
285
+ end
286
+
287
+ class Hash
288
+ def to_h; self; end
289
+ end
290
+ end
291
+
292
+ end