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.
- checksums.yaml +15 -0
- data/aws-flow.gemspec +1 -0
- data/lib/aws/decider/activity.rb +8 -6
- data/lib/aws/decider/async_decider.rb +1 -0
- data/lib/aws/decider/async_retrying_executor.rb +3 -3
- data/lib/aws/decider/decider.rb +16 -14
- data/lib/aws/decider/executor.rb +35 -22
- data/lib/aws/decider/flow_defaults.rb +28 -14
- data/lib/aws/decider/generic_client.rb +3 -4
- data/lib/aws/decider/options.rb +91 -117
- data/lib/aws/decider/state_machines.rb +1 -0
- data/lib/aws/decider/utilities.rb +15 -0
- data/lib/aws/decider/version.rb +1 -1
- data/lib/aws/decider/worker.rb +14 -8
- data/lib/aws/decider/workflow_client.rb +16 -11
- data/lib/aws/runner.rb +43 -39
- data/spec/aws/decider/integration/activity_spec.rb +345 -0
- data/spec/aws/{integration → decider/integration}/integration_spec.rb +818 -1183
- data/spec/aws/decider/integration/setup.rb +3 -0
- data/spec/aws/decider/unit/activity_spec.rb +233 -0
- data/spec/aws/decider/unit/async_retrying_executor_spec.rb +131 -0
- data/spec/aws/{unit → decider/unit}/decider_spec.rb +171 -718
- data/spec/aws/decider/unit/executor_spec.rb +123 -0
- data/spec/aws/decider/unit/flow_defaults_spec.rb +62 -0
- data/spec/aws/decider/unit/misc_spec.rb +101 -0
- data/spec/aws/decider/unit/options_spec.rb +289 -0
- data/spec/aws/decider/unit/retry_spec.rb +217 -0
- data/spec/aws/{unit → decider/unit}/rubyflow.rb +0 -0
- data/spec/aws/decider/unit/setup.rb +3 -0
- data/spec/aws/decider/unit/worker_spec.rb +325 -0
- data/spec/aws/decider/unit/workflow_client_spec.rb +83 -0
- data/spec/aws/{unit → flow}/async_backtrace_spec.rb +0 -0
- data/spec/aws/{unit → flow}/async_scope_spec.rb +0 -0
- data/spec/aws/{unit → flow}/begin_rescue_ensure_spec.rb +1 -0
- data/spec/aws/{unit → flow}/external_task_spec.rb +0 -0
- data/spec/aws/{unit → flow}/factories.rb +0 -0
- data/spec/aws/{unit → flow}/fiber_condition_variable_spec.rb +0 -0
- data/spec/aws/{unit → flow}/fiber_spec.rb +0 -0
- data/spec/aws/{unit → flow}/flow_spec.rb +0 -0
- data/spec/aws/{unit → flow}/future_spec.rb +0 -0
- data/spec/aws/{unit → flow}/simple_dfa_spec.rb +0 -0
- data/spec/aws/{integration → runner/integration}/runner_integration_spec.rb +16 -43
- data/spec/aws/{unit → runner/unit}/runner_unit_spec.rb +18 -18
- data/spec/spec_helper.rb +264 -2
- metadata +37 -28
- data/spec/aws/unit/executor_spec.rb +0 -49
- data/spec/aws/unit/options_spec.rb +0 -293
- 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
|
+
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,51 +1,22 @@
|
|
1
|
-
require '
|
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
|
-
|
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 =
|
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
|
-
|
95
|
-
|
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
|
-
|
171
|
-
|
172
|
-
|
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 '
|
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
|
-
{:
|
307
|
-
:
|
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
|
-
{:
|
321
|
-
:
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
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
|