aws-flow 1.0.5 → 1.0.6

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.
@@ -0,0 +1,210 @@
1
+ ##
2
+ # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License").
5
+ # You may not use this file except in compliance with the License.
6
+ # A copy of the License is located at
7
+ #
8
+ # http://aws.amazon.com/apache2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is distributed
11
+ # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
+ # express or implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+ ##
15
+
16
+ describe Future do
17
+ let(:future) { Future.new }
18
+ let(:trace) { [] }
19
+ it "throws an exception when set multiple times" do
20
+ future.set(:foo)
21
+ expect { future.set(:bar) }.to raise_error AlreadySetException
22
+ end
23
+
24
+ it "returns the value which was set" do
25
+ value = :foo
26
+ future.set(value)
27
+ future.get.should == value
28
+ end
29
+
30
+ it "blocks a task until a value is ready" do
31
+ scope = AsyncScope.new do
32
+ task do
33
+ trace << :first
34
+ future.get
35
+ # TODO technically this should only be checked in a TaskContext test;
36
+ # a Future test would just make sure that this comes after :second
37
+ trace << :fourth
38
+ end
39
+
40
+ task do
41
+ trace << :second
42
+ future.set(:foo)
43
+ trace << :third
44
+ end
45
+ end
46
+
47
+ scope.eventLoop
48
+ trace.should == [:first, :second, :third, :fourth]
49
+ end
50
+
51
+ it "blocks multiple Fibers until a value is ready" do
52
+ scope = AsyncScope.new do
53
+ task do
54
+ trace << :first
55
+ future.get
56
+ trace << :fifth
57
+ end
58
+
59
+ task do
60
+ trace << :second
61
+ future.get
62
+ trace << :sixth
63
+ end
64
+
65
+ task do
66
+ trace << :third
67
+ future.set(:foo)
68
+ trace << :fourth
69
+ end
70
+ end
71
+ scope.eventLoop
72
+ trace.should == [:first, :second, :third, :fourth, :fifth, :sixth]
73
+ end
74
+
75
+ it "supports wait_for_any" do
76
+ scope = AsyncScope.new do
77
+ f1 = Future.new
78
+ f2 = Future.new
79
+ f3 = Future.new
80
+ trace << :before_task
81
+ task do
82
+ trace << :before_set
83
+ f2.set("bar")
84
+ trace << :after_set
85
+ end
86
+ trace << :before_wait
87
+
88
+ f = Future.wait_for_any(f1, f2, f3).first
89
+ trace << :after_wait
90
+ f.should == f2
91
+ f.get.should == "bar"
92
+ end
93
+ trace.length.should == 0
94
+ scope.eventLoop
95
+ trace.should == [:before_task, :before_wait, :before_set, :after_set, :after_wait]
96
+ end
97
+
98
+ it "supports wait_for_any with all set" do
99
+ scope = AsyncScope.new do
100
+ f1 = Future.new
101
+ f2 = Future.new
102
+ f3 = Future.new
103
+ trace << :before_task
104
+ task do
105
+ trace << :before_set
106
+ f2.set("bar")
107
+ f1.set("baz")
108
+ f3.set("foo")
109
+ trace << :after_set
110
+ end
111
+ trace << :before_wait
112
+ r1, r2, r3 = Future.wait_for_any(f1, f2, f3)
113
+ trace << :after_wait
114
+ r1.should == f2
115
+ r1.get.should == "bar"
116
+ r2.should == f1
117
+ r2.get.should == "baz"
118
+ r3.should == f3
119
+ r3.get.should == "foo"
120
+ end
121
+ trace.length.should == 0
122
+ scope.eventLoop
123
+ trace.should == [:before_task, :before_wait, :before_set, :after_set, :after_wait]
124
+ end
125
+
126
+ it "supports wait_for_all" do
127
+ scope = AsyncScope.new do
128
+ f1 = Future.new
129
+ f2 = Future.new
130
+ f3 = Future.new
131
+ trace << :before_task
132
+ task do
133
+ trace << :before_f2_set
134
+ f2.set("bar")
135
+ task do
136
+ trace << :before_f1_set
137
+ f1.set("baz")
138
+ task do
139
+ trace << :before_f3_set
140
+ f3.set("foo")
141
+ trace << :after_set
142
+ end
143
+ end
144
+ end
145
+ trace << :before_wait
146
+ r1, r2, r3 = Future.wait_for_all(f1, f2, f3)
147
+ trace << :after_wait
148
+ r1.should == f2
149
+ r1.get.should == "bar"
150
+ r2.should == f1
151
+ r2.get.should == "baz"
152
+ r3.should == f3
153
+ r3.get.should == "foo"
154
+ end
155
+ trace.length.should == 0
156
+ scope.eventLoop
157
+ trace.should == [:before_task, :before_wait, :before_f2_set, :before_f1_set, :before_f3_set, :after_set, :after_wait]
158
+ end
159
+
160
+ it "supports wait_for_all with no futures" do
161
+ scope = AsyncScope.new do
162
+ task do
163
+ wait_for_all
164
+ end
165
+ end
166
+ scope.eventLoop
167
+ scope.is_complete?.should == true
168
+ end
169
+
170
+ it "supports wait_for_any with no futures" do
171
+ scope = AsyncScope.new do
172
+ task do
173
+ wait_for_any
174
+ end
175
+ end
176
+ scope.eventLoop
177
+ scope.is_complete?.should == true
178
+ end
179
+
180
+ it "supports wait_for_all with a set future" do
181
+ scope = AsyncScope.new do
182
+ future = Future.new.set
183
+ wait_for_all(future)
184
+ end
185
+ scope.eventLoop
186
+ scope.is_complete?.should == true
187
+ end
188
+
189
+ it "supports wait_for_any with a set future" do
190
+ scope = AsyncScope.new do
191
+ future = Future.new.set
192
+ wait_for_any(future)
193
+ end
194
+ scope.eventLoop
195
+ scope.is_complete?.should == true
196
+ end
197
+
198
+ it "supports wait_for_all with one set future and one not set" do
199
+ future2 = Future.new
200
+ scope = AsyncScope.new do
201
+ future = Future.new.set
202
+ wait_for_all(future, future2)
203
+ end
204
+ scope.eventLoop
205
+ future2.set
206
+ scope.eventLoop
207
+ scope.is_complete?.should == true
208
+ end
209
+
210
+ end
@@ -274,12 +274,16 @@ describe "RubyFlowDecider" do
274
274
  end
275
275
  end
276
276
  class SubsequentWorkflow
277
- extend Decider
277
+ extend Workflows
278
+ workflow :entry_point do
279
+ {
280
+ :version => "1",
281
+ }
282
+ end
278
283
  version "1"
279
284
  activity_client :activity do |options|
280
285
  options.prefix_name = "SubsequentActivity"
281
286
  end
282
- entry_point :entry_point
283
287
  def entry_point
284
288
  activity.run_activity1
285
289
  activity.run_activity2
@@ -294,9 +298,18 @@ describe "RubyFlowDecider" do
294
298
  worker.register
295
299
  activity_worker.register
296
300
  sleep 3
297
- workflow_id = "basic_subsequent_activities"
298
- run_id = @swf.client.start_workflow_execution(:execution_start_to_close_timeout => "3600", :task_list => {:name => task_list}, :task_start_to_close_timeout => "3600", :child_policy => "REQUEST_CANCEL", :workflow_type => {:name => workflow_type_name, :version => "1"}, :workflow_id => workflow_id, :domain => @domain.name.to_s)
299
- workflow_execution = AWS::SimpleWorkflow::WorkflowExecution.new(@domain, workflow_id, run_id["runId"])
301
+
302
+
303
+ my_workflow_client = workflow_client(@swf.client, @domain) do
304
+ {
305
+ :from_class => "SubsequentWorkflow",
306
+ :execution_start_to_close_timeout => "3600",
307
+ :task_list => task_list,
308
+ :task_start_to_close_timeout => "3600",
309
+ :child_policy => "REQUEST_CANCEL",
310
+ }
311
+ end
312
+ workflow_execution = my_workflow_client.start_execution
300
313
  worker.run_once
301
314
  activity_worker.run_once
302
315
  worker.run_once
@@ -510,6 +523,29 @@ describe "RubyFlowDecider" do
510
523
  @my_workflow_client = workflow_client(@swf.client, @domain) { {:from_class => @workflow_class} }
511
524
  end
512
525
 
526
+ it "ensures that an activity returning more than 32k data fails the activity" do
527
+ general_test(:task_list => "ActivityTaskLargeOutput", :class_name => "ActivityTaskLargeOutput")
528
+ @activity_class.class_eval do
529
+ def run_activity1
530
+ # Make sure we return something that's over 32k. Note this won't
531
+ # necessarily work with all converters, as it's pretty trivially
532
+ # compressible
533
+ return "a" * 33000
534
+ end
535
+ end
536
+ workflow_execution = @my_workflow_client.start_execution
537
+ @worker.run_once
538
+ @activity_worker.run_once
539
+ @worker.run_once
540
+ history_events = workflow_execution.events.map(&:event_type)
541
+ # Previously, it would time out, as the failure would include the original
542
+ # large output that killed the completion call. Thus, we need to check that
543
+ # we fail the ActivityTask correctly.
544
+ history_events.should include "ActivityTaskFailed"
545
+ history_events.last.should == "WorkflowExecutionFailed"
546
+
547
+ end
548
+
513
549
  it "ensures that not filling in details/reason for activity_task_failed is handled correctly" do
514
550
  general_test(:task_list => "ActivityTaskFailedManually", :class_name => "ActivityTaskFailedManually")
515
551
  $task_token = nil
@@ -1274,7 +1310,7 @@ describe "RubyFlowDecider" do
1274
1310
  end
1275
1311
  entry_point :entry_point
1276
1312
  def entry_point(arg)
1277
- my_workflow_factory = workflow_factory($swf.client, $domain) do |options|
1313
+ client = workflow_client do |options|
1278
1314
  options.workflow_name = "OtherChildWorkflow"
1279
1315
  options.execution_method = "entry_point"
1280
1316
  options.execution_start_to_close_timeout = 3600
@@ -1282,7 +1318,7 @@ describe "RubyFlowDecider" do
1282
1318
  options.version = "1"
1283
1319
  options.task_list = "test2"
1284
1320
  end
1285
- client = my_workflow_factory.get_client
1321
+
1286
1322
  client.send_async(:start_execution, 5)
1287
1323
  client.send_async(:start_execution, 5)
1288
1324
  end
@@ -1306,6 +1342,7 @@ describe "RubyFlowDecider" do
1306
1342
 
1307
1343
  # Start, start off the child workflow
1308
1344
  worker.run_once
1345
+
1309
1346
  # Run Both child workflows
1310
1347
  worker2.run_once
1311
1348
  worker2.run_once
@@ -1315,6 +1352,7 @@ describe "RubyFlowDecider" do
1315
1352
  # In order to deal with this, we have the following line below
1316
1353
  worker.run_once if workflow_execution.events.map(&:event_type).last == "DecisionTaskCompleted"
1317
1354
  events = workflow_execution.events.map(&:event_type)
1355
+ workflow_execution.events.to_a.last.attributes.result.should_not =~ /secret_access_key/
1318
1356
  events.should include "ChildWorkflowExecutionStarted"
1319
1357
  events.should include "ChildWorkflowExecutionCompleted"
1320
1358
  events.should include "WorkflowExecutionCompleted"
@@ -1575,9 +1613,9 @@ describe "RubyFlowDecider" do
1575
1613
  activity :run_activity1 do |options|
1576
1614
  options.version = "1"
1577
1615
  options.default_task_list = "exponential_test_return_task_list"
1578
- options.default_task_schedule_to_close_timeout = "5"
1579
- options.default_task_schedule_to_start_timeout = "5"
1580
- options.default_task_start_to_close_timeout = "5"
1616
+ options.default_task_schedule_to_close_timeout = "15"
1617
+ options.default_task_schedule_to_start_timeout = "15"
1618
+ options.default_task_start_to_close_timeout = "15"
1581
1619
  options.default_task_heartbeat_timeout = "3600"
1582
1620
  end
1583
1621
  def run_activity1
@@ -1629,50 +1667,50 @@ describe "RubyFlowDecider" do
1629
1667
  workflow_execution = client.start_execution
1630
1668
  worker.run_once
1631
1669
  activity_worker.run_once
1632
-
1670
+ activity_worker.run_once unless workflow_execution.events.map(&:event_type).include? "ActivityTaskCompleted"
1633
1671
  worker.run_once
1634
1672
  workflow_execution.events.map(&:event_type).count("WorkflowExecutionCompleted").should == 1
1635
-
1636
1673
  end
1637
1674
 
1638
1675
  it "makes sure that signals work correctly" do
1639
1676
  class SignalWorkflow
1640
- class << self
1641
- attr_accessor :task_list, :trace
1677
+ extend Workflows
1678
+ workflow :entry_point do
1679
+ {
1680
+ :version => "1"
1681
+ }
1642
1682
  end
1643
- @trace = []
1644
- extend Decider
1645
- version "1"
1646
- def this_signal
1683
+ def this_signal(input)
1647
1684
  @wait.broadcast
1685
+ @input = input
1648
1686
  end
1649
1687
  signal :this_signal
1650
- entry_point :entry_point
1651
1688
  def entry_point
1689
+ @input = "bad_input"
1652
1690
  @wait ||= FiberConditionVariable.new
1653
1691
  @wait.wait
1692
+ @input.should =~ /new input!/
1654
1693
  end
1655
1694
  end
1656
1695
  task_list = "SignalWorkflow_tasklist"
1657
1696
  worker = WorkflowWorker.new(@swf.client, @domain, task_list)
1658
1697
  worker.add_workflow_implementation(SignalWorkflow)
1659
1698
  worker.register
1660
- my_workflow_factory = workflow_factory(@swf.client, @domain) do |options|
1699
+ my_workflow_client = workflow_client(@swf.client, @domain) do |options|
1661
1700
  options.workflow_name = "SignalWorkflow"
1662
1701
  options.execution_start_to_close_timeout = 3600
1663
1702
  options.task_list = task_list
1664
1703
  options.task_start_to_close_timeout = 10
1665
1704
  options.child_policy = :request_cancel
1666
1705
  end
1667
- my_workflow = my_workflow_factory.get_client
1668
1706
  sleep 3
1669
- workflow_execution = my_workflow.start_execution
1707
+ workflow_execution = my_workflow_client.start_execution
1670
1708
  forking_executor = ForkingExecutor.new(:max_workers => 2)
1671
1709
  worker.run_once
1672
- my_workflow.signal_workflow_execution("this_signal", workflow_execution)
1710
+
1711
+ my_workflow_client.signal_workflow_execution("this_signal", workflow_execution) { {:input => "new input!"}}
1673
1712
  worker.run_once
1674
1713
  forking_executor.shutdown(1)
1675
-
1676
1714
  workflow_execution.events.map(&:event_type).count("WorkflowExecutionCompleted").should == 1
1677
1715
  end
1678
1716
 
@@ -1931,7 +1969,6 @@ describe "RubyFlowDecider" do
1931
1969
  options.default_task_start_to_close_timeout = "3600"
1932
1970
  end
1933
1971
  def run_activity1(arg)
1934
- arg.should == 5
1935
1972
  arg + 1
1936
1973
  end
1937
1974
  def run_activity2(arg)
@@ -1942,7 +1979,7 @@ describe "RubyFlowDecider" do
1942
1979
  end
1943
1980
  end
1944
1981
  # Definition of the workflow logic
1945
- class MyWorkflow
1982
+ class ParallelWorkflow
1946
1983
  extend Decider
1947
1984
  version "1"
1948
1985
  activity_client :activity do |options|
@@ -1983,15 +2020,15 @@ describe "RubyFlowDecider" do
1983
2020
  task_list = "parallel_split_task_list"
1984
2021
  # @swf and @domain are set beforehand with the aws ruby sdk
1985
2022
  worker = WorkflowWorker.new(@swf.client, @domain, task_list)
1986
- worker.add_workflow_implementation(MyWorkflow)
1987
- activity_worker = ActivityWorker.new(@swf.client, @domain, task_list)
2023
+ worker.add_workflow_implementation(ParallelWorkflow)
2024
+ activity_worker = ActivityWorker.new(@swf.client, @domain, task_list) { {:use_forking => false}}
1988
2025
  activity_worker.add_activities_implementation(ParallelSplitActivity)
1989
2026
  worker.register
1990
2027
  activity_worker.register
1991
2028
 
1992
2029
  # Get a workflow client to start the workflow
1993
2030
  my_workflow_factory = workflow_factory @swf.client, @domain do |options|
1994
- options.workflow_name = "MyWorkflow"
2031
+ options.workflow_name = "ParallelWorkflow"
1995
2032
  options.execution_start_to_close_timeout = 3600
1996
2033
  options.task_list = task_list
1997
2034
  options.task_start_to_close_timeout = 10
@@ -2019,6 +2056,7 @@ describe "RubyFlowDecider" do
2019
2056
  # Sleep to give the threads some time to compute, as we'll run right out of
2020
2057
  # the test before they can run otherwise
2021
2058
  sleep 50
2059
+ p workflow_execution.events.to_a
2022
2060
  workflow_execution.events.map(&:event_type).count("WorkflowExecutionCompleted").should == 1
2023
2061
  end
2024
2062
 
@@ -2159,10 +2197,15 @@ describe "RubyFlowDecider" do
2159
2197
 
2160
2198
  it "ensures you cannot schedule more than 99 things in one decision" do
2161
2199
  general_test(:task_list => "schedule_more_than_100", :class_name => "Above100TasksScheduled")
2200
+ @activity_class.class_eval do
2201
+ def run_activity1(arg)
2202
+ arg
2203
+ end
2204
+ end
2162
2205
  @workflow_class.class_eval do
2163
2206
  def entry_point
2164
- 101.times do
2165
- activity.send_async(:run_activity1)
2207
+ 101.times do |i|
2208
+ activity.send_async(:run_activity1, i)
2166
2209
  end
2167
2210
  end
2168
2211
  end
@@ -2223,7 +2266,7 @@ describe "RubyFlowDecider" do
2223
2266
  "did some work in run_activity1"
2224
2267
  end
2225
2268
  end
2226
- class MyWorkflow
2269
+ class TimeoutWorkflow
2227
2270
  extend Decider
2228
2271
  version "1"
2229
2272
  activity_client :activity do |options|
@@ -2234,17 +2277,18 @@ describe "RubyFlowDecider" do
2234
2277
  activity.run_activity1
2235
2278
  end
2236
2279
  end
2237
- worker = WorkflowWorker.new(@swf.client, @domain, "timeout_test", MyWorkflow)
2280
+ worker = WorkflowWorker.new(@swf.client, @domain, "timeout_test", TimeoutWorkflow)
2238
2281
  activity_worker = ActivityWorker.new(@swf.client, @domain, "timeout_test", TimeoutActivity)
2239
2282
  worker.register
2240
2283
  activity_worker.register
2241
2284
  my_workflow_factory = workflow_factory @swf.client, @domain do |options|
2242
- options.workflow_name = "MyWorkflow"
2285
+ options.workflow_name = "TimeoutWorkflow"
2243
2286
  options.execution_start_to_close_timeout = 3600
2287
+ options.task_start_to_close_timeout = 5
2244
2288
  options.task_list = "timeout_test"
2245
2289
  end
2246
2290
  my_workflow_client = my_workflow_factory.get_client
2247
- num_tests = 50
2291
+ num_tests = 30
2248
2292
  workflow_executions = []
2249
2293
  1.upto(num_tests) { |i| workflow_executions << my_workflow_client.entry_point }
2250
2294
  forking_executor = ForkingExecutor.new(:max_workers => 3)
@@ -2252,6 +2296,7 @@ describe "RubyFlowDecider" do
2252
2296
  forking_executor.execute { activity_worker.start }
2253
2297
  sleep 60
2254
2298
  failed_executions = workflow_executions.each{|x| x.events.to_a.last.event_type.should == "WorkflowExecutionCompleted" }
2299
+
2255
2300
  end
2256
2301
  end
2257
2302
 
@@ -2273,7 +2318,7 @@ describe "RubyFlowDecider" do
2273
2318
  version "1"
2274
2319
  entry_point :entry_point
2275
2320
  def entry_point(arg)
2276
- my_workflow_factory = workflow_factory($swf_client, $domain) do |options|
2321
+ client = workflow_client(@swf_client, @domain) do |options|
2277
2322
  options.workflow_name = "SendAsyncWorkflow"
2278
2323
  options.execution_method = "entry_point"
2279
2324
  options.execution_start_to_close_timeout = 3600
@@ -2281,7 +2326,6 @@ describe "RubyFlowDecider" do
2281
2326
  options.version = "1"
2282
2327
  options.task_list = "client_test_async2"
2283
2328
  end
2284
- client = my_workflow_factory.get_client
2285
2329
  client.send_async(:start_execution, arg) { {:task_start_to_close_timeout => 35 } }
2286
2330
  client.send_async(:start_execution, arg)
2287
2331
  end
@@ -2297,8 +2341,8 @@ describe "RubyFlowDecider" do
2297
2341
  end
2298
2342
  my_workflow_client = my_workflow_factory.get_client
2299
2343
  workflow_execution = my_workflow_client.entry_point(5)
2300
-
2301
2344
  worker.run_once
2345
+
2302
2346
  internal_worker.run_once
2303
2347
  internal_worker.run_once
2304
2348
  worker.run_once
@@ -2407,7 +2451,7 @@ describe "RubyFlowDecider" do
2407
2451
  end
2408
2452
 
2409
2453
  it "ensures that with_retry does asynchronous blocking correctly" do
2410
- general_test(:task_list => "with_retry_synch", :class_name => "WithRetrySynchronous")
2454
+ general_test(:task_list => "with_retry_synch", :class_name => "WithRetryAsynchronous")
2411
2455
  @workflow_class.class_eval do
2412
2456
  def entry_point
2413
2457
  with_retry do