asynchronic 2.0.1 → 4.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 +5 -5
- data/.travis.yml +7 -10
- data/README.md +1 -2
- data/asynchronic.gemspec +3 -2
- data/lib/asynchronic.rb +13 -3
- data/lib/asynchronic/data_store/in_memory.rb +17 -15
- data/lib/asynchronic/data_store/key.rb +3 -3
- data/lib/asynchronic/data_store/lazy_value.rb +5 -3
- data/lib/asynchronic/data_store/redis.rb +22 -14
- data/lib/asynchronic/data_store/scoped_store.rb +18 -19
- data/lib/asynchronic/environment.rb +6 -6
- data/lib/asynchronic/error.rb +2 -3
- data/lib/asynchronic/garbage_collector.rb +2 -0
- data/lib/asynchronic/job.rb +12 -12
- data/lib/asynchronic/notifier/broadcaster.rb +34 -0
- data/lib/asynchronic/notifier/in_memory.rb +33 -0
- data/lib/asynchronic/process.rb +52 -38
- data/lib/asynchronic/queue_engine/in_memory.rb +17 -11
- data/lib/asynchronic/queue_engine/ost.rb +15 -12
- data/lib/asynchronic/queue_engine/synchronic.rb +19 -7
- data/lib/asynchronic/version.rb +1 -1
- data/lib/asynchronic/worker.rb +7 -10
- data/spec/data_store/data_store_examples.rb +17 -9
- data/spec/data_store/in_memory_spec.rb +0 -2
- data/spec/data_store/key_spec.rb +1 -1
- data/spec/data_store/lazy_value_examples.rb +7 -6
- data/spec/data_store/redis_spec.rb +4 -10
- data/spec/expectations.rb +2 -2
- data/spec/facade_spec.rb +5 -5
- data/spec/jobs.rb +12 -12
- data/spec/minitest_helper.rb +6 -12
- data/spec/process/life_cycle_examples.rb +111 -64
- data/spec/process/life_cycle_in_memory_spec.rb +1 -1
- data/spec/process/life_cycle_redis_spec.rb +1 -1
- data/spec/queue_engine/in_memory_spec.rb +1 -3
- data/spec/queue_engine/ost_spec.rb +1 -7
- data/spec/queue_engine/queue_engine_examples.rb +17 -9
- data/spec/queue_engine/synchronic_spec.rb +1 -1
- data/spec/worker/in_memory_spec.rb +2 -2
- data/spec/worker/redis_spec.rb +1 -6
- data/spec/worker/worker_examples.rb +7 -5
- metadata +38 -17
data/lib/asynchronic/version.rb
CHANGED
data/lib/asynchronic/worker.rb
CHANGED
@@ -1,24 +1,21 @@
|
|
1
1
|
class Asynchronic::Worker
|
2
2
|
|
3
|
-
attr_reader :queue
|
4
|
-
attr_reader :queue_name
|
5
|
-
attr_reader :env
|
6
|
-
attr_reader :listener
|
3
|
+
attr_reader :queue, :queue_name, :environment, :listener
|
7
4
|
|
8
|
-
def initialize(queue_name,
|
5
|
+
def initialize(queue_name, environment)
|
9
6
|
@queue_name = queue_name
|
10
|
-
@queue =
|
11
|
-
@
|
12
|
-
@listener =
|
7
|
+
@queue = environment.queue_engine[queue_name]
|
8
|
+
@environment = environment
|
9
|
+
@listener = environment.queue_engine.listener
|
13
10
|
end
|
14
11
|
|
15
12
|
def start
|
16
13
|
Asynchronic.logger.info('Asynchronic') { "Starting worker of #{queue_name} (#{Process.pid})" }
|
17
14
|
|
18
15
|
Signal.trap('QUIT') { stop }
|
19
|
-
|
16
|
+
|
20
17
|
listener.listen(queue) do |pid|
|
21
|
-
|
18
|
+
environment.load_process(pid).execute
|
22
19
|
end
|
23
20
|
end
|
24
21
|
|
@@ -1,5 +1,11 @@
|
|
1
1
|
module DataStoreExamples
|
2
|
-
|
2
|
+
|
3
|
+
extend Minitest::Spec::DSL
|
4
|
+
|
5
|
+
after do
|
6
|
+
data_store.clear
|
7
|
+
end
|
8
|
+
|
3
9
|
it 'Get/Set value' do
|
4
10
|
data_store[:key] = 123
|
5
11
|
data_store[:key].must_equal 123
|
@@ -32,8 +38,8 @@ module DataStoreExamples
|
|
32
38
|
data_store.delete_cascade Asynchronic::DataStore::Key[:key_1]
|
33
39
|
|
34
40
|
data_store.keys.sort.must_equal [
|
35
|
-
Asynchronic::DataStore::Key[:key_2],
|
36
|
-
Asynchronic::DataStore::Key[:key_2][:key_2_1],
|
41
|
+
Asynchronic::DataStore::Key[:key_2],
|
42
|
+
Asynchronic::DataStore::Key[:key_2][:key_2_1],
|
37
43
|
Asynchronic::DataStore::Key[:key_2][:key_2_2]
|
38
44
|
]
|
39
45
|
end
|
@@ -110,18 +116,20 @@ module DataStoreExamples
|
|
110
116
|
|
111
117
|
it 'Synchronization' do
|
112
118
|
sum = 0
|
113
|
-
|
119
|
+
|
120
|
+
threads = 10.times.map do
|
114
121
|
Thread.new do
|
115
|
-
data_store.synchronize('
|
122
|
+
data_store.synchronize('lock_key') do
|
116
123
|
temp = sum
|
117
|
-
sleep 0
|
124
|
+
sleep 0.01
|
118
125
|
sum = temp + 1
|
119
126
|
end
|
120
127
|
end
|
121
128
|
end
|
129
|
+
|
122
130
|
threads.each(&:join)
|
123
|
-
|
124
|
-
sum.must_equal
|
131
|
+
|
132
|
+
sum.must_equal threads.count
|
125
133
|
end
|
126
|
-
|
134
|
+
|
127
135
|
end
|
data/spec/data_store/key_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module LazyValueExamples
|
2
2
|
|
3
|
+
extend Minitest::Spec::DSL
|
4
|
+
|
3
5
|
def lazy_value(key)
|
4
6
|
Asynchronic::DataStore::LazyValue.new data_store, key
|
5
7
|
end
|
@@ -7,26 +9,25 @@ module LazyValueExamples
|
|
7
9
|
it 'Get' do
|
8
10
|
value = lazy_value :key
|
9
11
|
value.must_be_nil
|
10
|
-
|
11
|
-
data_store[:key] =
|
12
|
+
|
13
|
+
data_store[:key] = 1
|
12
14
|
value.must_equal 1
|
13
15
|
end
|
14
16
|
|
15
17
|
it 'Reload' do
|
16
18
|
value = lazy_value :key
|
17
19
|
|
18
|
-
data_store[:key] =
|
20
|
+
data_store[:key] = 1
|
19
21
|
value.must_equal 1
|
20
22
|
|
21
|
-
data_store[:key] =
|
23
|
+
data_store[:key] = 2
|
22
24
|
value.must_equal 1
|
23
25
|
value.reload.must_equal 2
|
24
26
|
end
|
25
27
|
|
26
28
|
it 'Transparent proxy' do
|
27
29
|
value = lazy_value :key
|
28
|
-
data_store[:key] =
|
29
|
-
value.must_be_instance_of Fixnum
|
30
|
+
data_store[:key] = 1
|
30
31
|
value.must_equal 1
|
31
32
|
end
|
32
33
|
|
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'minitest_helper'
|
2
|
-
require_relative './data_store_examples'
|
3
|
-
require_relative './lazy_value_examples'
|
4
2
|
|
5
3
|
describe Asynchronic::DataStore::Redis do
|
6
4
|
|
7
5
|
let(:data_store) { Asynchronic::DataStore::Redis.new :asynchronic_test }
|
8
6
|
|
9
|
-
after do
|
10
|
-
data_store.clear
|
11
|
-
end
|
12
|
-
|
13
7
|
include DataStoreExamples
|
14
8
|
|
9
|
+
describe 'LazyValue' do
|
10
|
+
include LazyValueExamples
|
11
|
+
end
|
12
|
+
|
15
13
|
it 'Safe deserialization' do
|
16
14
|
SampleClass = Class.new
|
17
15
|
|
@@ -24,8 +22,4 @@ describe Asynchronic::DataStore::Redis do
|
|
24
22
|
data_store[:instance].must_be_instance_of String
|
25
23
|
end
|
26
24
|
|
27
|
-
describe 'LazyValue' do
|
28
|
-
include LazyValueExamples
|
29
|
-
end
|
30
|
-
|
31
25
|
end
|
data/spec/expectations.rb
CHANGED
@@ -15,10 +15,10 @@ module MiniTest::Assertions
|
|
15
15
|
def assert_be_initialized(process)
|
16
16
|
process.must_be :pending?
|
17
17
|
process.wont_be :finalized?
|
18
|
-
|
18
|
+
|
19
19
|
process.processes.must_be_empty
|
20
20
|
process.error.must_be_nil
|
21
|
-
|
21
|
+
|
22
22
|
process.created_at.must_be_instance_of Time
|
23
23
|
process.queued_at.must_be_nil
|
24
24
|
process.started_at.must_be_nil
|
data/spec/facade_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Asynchronic, 'Facade' do
|
|
6
6
|
Asynchronic.environment.data_store.clear
|
7
7
|
Asynchronic.environment.queue_engine.clear
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
it 'Default queue' do
|
11
11
|
Asynchronic.default_queue.must_equal :asynchronic_test
|
12
12
|
end
|
@@ -40,7 +40,7 @@ describe Asynchronic, 'Facade' do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'List processes' do
|
43
|
-
ids = 3.times.map do
|
43
|
+
ids = 3.times.map do
|
44
44
|
process = Asynchronic.environment.create_process SequentialJob
|
45
45
|
process.id
|
46
46
|
end
|
@@ -51,7 +51,7 @@ describe Asynchronic, 'Facade' do
|
|
51
51
|
|
52
52
|
it 'Enqueue' do
|
53
53
|
id = BasicJob.enqueue input: 100
|
54
|
-
|
54
|
+
|
55
55
|
Asynchronic.environment.tap do |env|
|
56
56
|
process = env.load_process id
|
57
57
|
process.type.must_equal BasicJob
|
@@ -69,11 +69,11 @@ describe Asynchronic, 'Facade' do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'Keep alive timeout' do
|
72
|
-
Asynchronic.keep_alive_timeout.must_equal
|
72
|
+
Asynchronic.keep_alive_timeout.must_equal 1
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'Connection name' do
|
76
|
-
Asynchronic.connection_name.
|
76
|
+
Asynchronic.connection_name.must_match /^HOST=#{Socket.gethostname},PID=#{::Process.pid}/
|
77
77
|
end
|
78
78
|
|
79
79
|
end
|
data/spec/jobs.rb
CHANGED
@@ -9,8 +9,8 @@ class SequentialJob < Asynchronic::Job
|
|
9
9
|
|
10
10
|
def call
|
11
11
|
async Step1, input: params[:input]
|
12
|
-
|
13
|
-
async Step2, dependency: Step1,
|
12
|
+
|
13
|
+
async Step2, dependency: Step1,
|
14
14
|
input: params[:input]
|
15
15
|
|
16
16
|
nil
|
@@ -32,7 +32,7 @@ end
|
|
32
32
|
|
33
33
|
|
34
34
|
class GraphJob < Asynchronic::Job
|
35
|
-
|
35
|
+
|
36
36
|
def call
|
37
37
|
async Sum, input: params[:input]
|
38
38
|
|
@@ -113,13 +113,13 @@ class AliasJob < Asynchronic::Job
|
|
113
113
|
def call
|
114
114
|
async Write, alias: :word_1,
|
115
115
|
text: 'Take'
|
116
|
-
|
117
|
-
async Write, alias: :word_2,
|
118
|
-
text: 'it',
|
116
|
+
|
117
|
+
async Write, alias: :word_2,
|
118
|
+
text: 'it',
|
119
119
|
prefix: result(:word_1)
|
120
|
-
|
121
|
-
async Write, alias: :word_3,
|
122
|
-
text: 'easy',
|
120
|
+
|
121
|
+
async Write, alias: :word_3,
|
122
|
+
text: 'easy',
|
123
123
|
prefix: result(:word_2)
|
124
124
|
|
125
125
|
result :word_3
|
@@ -200,7 +200,7 @@ end
|
|
200
200
|
class WithRetriesJob < Asynchronic::Job
|
201
201
|
def call
|
202
202
|
@counter = 0
|
203
|
-
retry_when [RuntimeError] do
|
203
|
+
retry_when [RuntimeError], 0.1 do
|
204
204
|
@counter += 1
|
205
205
|
raise 'Counter < 3' if @counter < 3
|
206
206
|
@counter
|
@@ -326,7 +326,7 @@ class NestedJobWithErrorInChildJob < Asynchronic::Job
|
|
326
326
|
end
|
327
327
|
|
328
328
|
|
329
|
-
class
|
329
|
+
class AbortQueuedAfterErrorJob < Asynchronic::Job
|
330
330
|
def call
|
331
331
|
async Child_1
|
332
332
|
async Child_2
|
@@ -402,4 +402,4 @@ class BeforeFinalizeExceptionOnAbortedJob < Asynchronic::Job
|
|
402
402
|
def before_finalize
|
403
403
|
raise 'Before finalize error'
|
404
404
|
end
|
405
|
-
end
|
405
|
+
end
|
data/spec/minitest_helper.rb
CHANGED
@@ -3,14 +3,17 @@ require 'asynchronic'
|
|
3
3
|
require 'minitest/autorun'
|
4
4
|
require 'minitest/colorin'
|
5
5
|
require 'minitest/great_expectations'
|
6
|
+
require 'minitest/stub_any_instance'
|
6
7
|
require 'jobs'
|
7
8
|
require 'expectations'
|
8
9
|
require 'timeout'
|
9
10
|
require 'pry-nav'
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
require_relative 'data_store/data_store_examples'
|
13
|
+
require_relative 'data_store/lazy_value_examples'
|
14
|
+
require_relative 'process/life_cycle_examples'
|
15
|
+
require_relative 'queue_engine/queue_engine_examples'
|
16
|
+
require_relative 'worker/worker_examples'
|
14
17
|
|
15
18
|
Asynchronic.logger.level = Logger::FATAL
|
16
19
|
|
@@ -19,13 +22,4 @@ class Minitest::Spec
|
|
19
22
|
Asynchronic.restore_default_configuration
|
20
23
|
Asynchronic.default_queue = :asynchronic_test
|
21
24
|
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module Asynchronic::DataStore::Helper
|
25
|
-
def dump
|
26
|
-
puts 'DataStore:'
|
27
|
-
each do |k,v|
|
28
|
-
puts "#{k}: #{v}"
|
29
|
-
end
|
30
|
-
end
|
31
25
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module LifeCycleExamples
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
extend Minitest::Spec::DSL
|
4
|
+
|
5
|
+
let(:env) { Asynchronic::Environment.new queue_engine, data_store, notifier }
|
4
6
|
|
5
7
|
let(:queue) { env.default_queue }
|
6
8
|
|
7
9
|
after do
|
8
10
|
data_store.clear
|
9
11
|
queue_engine.clear
|
12
|
+
notifier.unsubscribe_all
|
10
13
|
end
|
11
14
|
|
12
15
|
def create(type, params={})
|
@@ -17,10 +20,46 @@ module LifeCycleExamples
|
|
17
20
|
|
18
21
|
def execute(queue)
|
19
22
|
process = env.load_process(queue.pop)
|
23
|
+
|
24
|
+
events = []
|
25
|
+
status_changed_id = notifier.subscribe(process.id, :status_changed) { |status| events << status }
|
26
|
+
|
27
|
+
is_finalized = false
|
28
|
+
finalized_id = notifier.subscribe(process.id, :finalized) { is_finalized = true }
|
29
|
+
|
20
30
|
process.execute
|
31
|
+
|
21
32
|
process.must_have_connection_name
|
22
33
|
process.wont_be :dead?
|
34
|
+
|
23
35
|
process.send(:connected?).must_be_true
|
36
|
+
|
37
|
+
env.queue_engine.stub(:active_connections, ->() { raise 'Forced error' }) do
|
38
|
+
process.send(:connected?).must_be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
with_retries do
|
42
|
+
events.last.must_equal process.status
|
43
|
+
process.finalized?.must_equal is_finalized
|
44
|
+
end
|
45
|
+
|
46
|
+
notifier.unsubscribe status_changed_id
|
47
|
+
notifier.unsubscribe finalized_id
|
48
|
+
|
49
|
+
status = process.status
|
50
|
+
process.abort_if_dead
|
51
|
+
process.status.must_equal status
|
52
|
+
end
|
53
|
+
|
54
|
+
def with_retries(&block)
|
55
|
+
Timeout.timeout(3) do
|
56
|
+
begin
|
57
|
+
block.call
|
58
|
+
rescue Minitest::Assertion
|
59
|
+
sleep 0.001
|
60
|
+
retry
|
61
|
+
end
|
62
|
+
end
|
24
63
|
end
|
25
64
|
|
26
65
|
it 'Basic' do
|
@@ -101,7 +140,7 @@ module LifeCycleExamples
|
|
101
140
|
process[GraphJob::Total].must_be_pending
|
102
141
|
process[GraphJob::Total].must_have_params '10%' => nil, '20%' => nil
|
103
142
|
queue.must_enqueued process[GraphJob::Sum]
|
104
|
-
|
143
|
+
|
105
144
|
execute queue
|
106
145
|
|
107
146
|
process.must_be_waiting
|
@@ -257,7 +296,7 @@ module LifeCycleExamples
|
|
257
296
|
process[:word_3].result.must_equal 'Take it easy'
|
258
297
|
queue.must_be_empty
|
259
298
|
end
|
260
|
-
|
299
|
+
|
261
300
|
it 'Custom queue' do
|
262
301
|
process = create CustomQueueJob, input: 'hello'
|
263
302
|
|
@@ -271,7 +310,7 @@ module LifeCycleExamples
|
|
271
310
|
|
272
311
|
process.must_be_queued
|
273
312
|
process.processes.must_be_empty
|
274
|
-
|
313
|
+
|
275
314
|
env.queue(:queue_1).must_enqueued process
|
276
315
|
env.queue(:queue_2).must_be_empty
|
277
316
|
env.queue(:queue_3).must_be_empty
|
@@ -281,7 +320,7 @@ module LifeCycleExamples
|
|
281
320
|
process.must_be_waiting
|
282
321
|
process[CustomQueueJob::Reverse].must_be_queued
|
283
322
|
process[CustomQueueJob::Reverse].must_have_params input: 'hello'
|
284
|
-
|
323
|
+
|
285
324
|
env.queue(:queue_1).must_be_empty
|
286
325
|
env.queue(:queue_2).must_enqueued process[CustomQueueJob::Reverse]
|
287
326
|
env.queue(:queue_3).must_be_empty
|
@@ -292,7 +331,7 @@ module LifeCycleExamples
|
|
292
331
|
process.result.must_equal 'olleh'
|
293
332
|
process[CustomQueueJob::Reverse].must_be_completed
|
294
333
|
process[CustomQueueJob::Reverse].result.must_equal 'olleh'
|
295
|
-
|
334
|
+
|
296
335
|
env.queue(:queue_1).must_be_empty
|
297
336
|
env.queue(:queue_2).must_be_empty
|
298
337
|
env.queue(:queue_3).must_be_empty
|
@@ -448,7 +487,7 @@ module LifeCycleExamples
|
|
448
487
|
|
449
488
|
it 'Data' do
|
450
489
|
process = create DataJob, input: 1
|
451
|
-
|
490
|
+
|
452
491
|
process.enqueue
|
453
492
|
execute queue
|
454
493
|
|
@@ -460,7 +499,7 @@ module LifeCycleExamples
|
|
460
499
|
it 'Nested job with error in child' do
|
461
500
|
process = create NestedJobWithErrorInChildJob
|
462
501
|
|
463
|
-
process.enqueue
|
502
|
+
process.enqueue
|
464
503
|
|
465
504
|
Timeout.timeout(1) do
|
466
505
|
until process.status == :aborted
|
@@ -474,87 +513,88 @@ module LifeCycleExamples
|
|
474
513
|
it 'Nested job with error in parent' do
|
475
514
|
process = create NestedJobWithErrorInParentJob
|
476
515
|
|
477
|
-
process.enqueue
|
516
|
+
process.enqueue
|
478
517
|
|
479
518
|
execute queue
|
480
|
-
|
519
|
+
|
481
520
|
process.real_error.must_equal "Error in parent"
|
482
521
|
end
|
483
522
|
|
484
|
-
it 'Abort queued
|
485
|
-
process = create
|
523
|
+
it 'Abort queued After error' do
|
524
|
+
process = create AbortQueuedAfterErrorJob
|
486
525
|
|
487
|
-
process.enqueue
|
526
|
+
process.enqueue
|
488
527
|
|
489
528
|
execute queue
|
490
529
|
|
491
|
-
process.full_status.must_equal '
|
492
|
-
'
|
493
|
-
'
|
494
|
-
'
|
495
|
-
'
|
530
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
531
|
+
'AbortQueuedAfterErrorJob::Child_1' => :queued,
|
532
|
+
'AbortQueuedAfterErrorJob::Child_2' => :queued,
|
533
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
534
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
496
535
|
|
497
536
|
execute queue
|
498
537
|
|
499
|
-
process.full_status.must_equal '
|
500
|
-
'
|
538
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
539
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
501
540
|
'Child_1_1' => :queued,
|
502
541
|
'Child_1_2' => :queued,
|
503
|
-
'
|
504
|
-
'
|
505
|
-
'
|
542
|
+
'AbortQueuedAfterErrorJob::Child_2' => :queued,
|
543
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
544
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
506
545
|
|
507
546
|
execute queue
|
508
547
|
|
509
|
-
process.full_status.must_equal '
|
510
|
-
'
|
548
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
549
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
511
550
|
'Child_1_1' => :queued,
|
512
551
|
'Child_1_2' => :queued,
|
513
|
-
'
|
514
|
-
'
|
515
|
-
'
|
552
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
553
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
554
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
516
555
|
|
517
556
|
execute queue
|
518
557
|
|
519
|
-
process.full_status.must_equal '
|
520
|
-
'
|
558
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
559
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
521
560
|
'Child_1_1' => :queued,
|
522
561
|
'Child_1_2' => :queued,
|
523
|
-
'
|
524
|
-
'
|
525
|
-
'
|
562
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
563
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
564
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
526
565
|
|
527
566
|
execute queue
|
528
567
|
|
529
|
-
process.full_status.must_equal '
|
530
|
-
'
|
568
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
569
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
531
570
|
'Child_1_1' => :queued,
|
532
571
|
'Child_1_2' => :queued,
|
533
|
-
'
|
534
|
-
'
|
535
|
-
'
|
572
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
573
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
574
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
536
575
|
|
537
576
|
execute queue
|
538
577
|
|
539
|
-
process.full_status.must_equal '
|
540
|
-
'
|
578
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
579
|
+
'AbortQueuedAfterErrorJob::Child_1' => :aborted,
|
541
580
|
'Child_1_1' => :aborted,
|
542
581
|
'Child_1_2' => :queued,
|
543
|
-
'
|
544
|
-
'
|
545
|
-
'
|
582
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
583
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
584
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
546
585
|
|
547
586
|
execute queue
|
548
587
|
|
549
|
-
process.full_status.must_equal '
|
550
|
-
'
|
588
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
589
|
+
'AbortQueuedAfterErrorJob::Child_1' => :aborted,
|
551
590
|
'Child_1_1' => :aborted,
|
552
591
|
'Child_1_2' => :aborted,
|
553
|
-
'
|
554
|
-
'
|
555
|
-
'
|
592
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
593
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
594
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
556
595
|
|
557
596
|
process.real_error.must_equal 'Forced error'
|
597
|
+
process.processes[0].processes[1].error.message.must_equal Asynchronic::Process::AUTOMATIC_ABORTED_ERROR_MESSAGE
|
558
598
|
end
|
559
599
|
|
560
600
|
it 'Manual abort' do
|
@@ -564,27 +604,27 @@ module LifeCycleExamples
|
|
564
604
|
|
565
605
|
execute queue
|
566
606
|
|
567
|
-
process.full_status.must_equal 'NestedJob' => :waiting,
|
607
|
+
process.full_status.must_equal 'NestedJob' => :waiting,
|
568
608
|
'NestedJob::Level1' => :queued
|
569
609
|
|
570
610
|
execute queue
|
571
611
|
|
572
|
-
process.full_status.must_equal 'NestedJob' => :waiting,
|
573
|
-
'NestedJob::Level1' => :waiting,
|
612
|
+
process.full_status.must_equal 'NestedJob' => :waiting,
|
613
|
+
'NestedJob::Level1' => :waiting,
|
574
614
|
'NestedJob::Level1::Level2' => :queued
|
575
615
|
|
576
616
|
process.cancel!
|
577
617
|
|
578
618
|
process.real_error.must_equal Asynchronic::Process::CANCELED_ERROR_MESSAGE
|
579
619
|
|
580
|
-
process.full_status.must_equal 'NestedJob' => :aborted,
|
581
|
-
'NestedJob::Level1' => :waiting,
|
620
|
+
process.full_status.must_equal 'NestedJob' => :aborted,
|
621
|
+
'NestedJob::Level1' => :waiting,
|
582
622
|
'NestedJob::Level1::Level2' => :queued
|
583
623
|
|
584
624
|
execute queue
|
585
625
|
|
586
|
-
process.full_status.must_equal 'NestedJob' => :aborted,
|
587
|
-
'NestedJob::Level1' => :aborted,
|
626
|
+
process.full_status.must_equal 'NestedJob' => :aborted,
|
627
|
+
'NestedJob::Level1' => :aborted,
|
588
628
|
'NestedJob::Level1::Level2' => :aborted
|
589
629
|
end
|
590
630
|
|
@@ -612,41 +652,49 @@ module LifeCycleExamples
|
|
612
652
|
process_1 = create AliasJob
|
613
653
|
process_1.enqueue
|
614
654
|
4.times { execute queue }
|
615
|
-
|
655
|
+
|
616
656
|
process_2 = create AliasJob
|
617
657
|
process_2.enqueue
|
618
658
|
execute queue
|
619
659
|
|
660
|
+
process_3 = create BasicJob
|
661
|
+
|
620
662
|
pid_1 = process_1.id
|
621
663
|
pid_2 = process_2.id
|
664
|
+
pid_3 = process_3.id
|
622
665
|
|
623
666
|
process_1.must_be_completed
|
624
667
|
process_2.must_be_waiting
|
668
|
+
process_3.must_be_pending
|
625
669
|
|
626
670
|
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal 53
|
627
671
|
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal 38
|
672
|
+
data_store.keys.select { |k| k.start_with? pid_3 }.count.must_equal 7
|
628
673
|
|
629
674
|
gc = Asynchronic::GarbageCollector.new env, 0.001
|
630
|
-
|
631
|
-
gc.add_condition('
|
675
|
+
|
676
|
+
gc.add_condition('Finalized', &:finalized?)
|
632
677
|
gc.add_condition('Waiting', &:waiting?)
|
633
678
|
gc.add_condition('Exception') { raise 'Invalid condition' }
|
634
679
|
|
635
|
-
gc.conditions_names.must_equal ['
|
680
|
+
gc.conditions_names.must_equal ['Finalized', 'Waiting', 'Exception']
|
636
681
|
|
637
682
|
gc.remove_condition 'Waiting'
|
638
|
-
|
639
|
-
gc.conditions_names.must_equal ['
|
683
|
+
|
684
|
+
gc.conditions_names.must_equal ['Finalized', 'Exception']
|
640
685
|
|
641
686
|
Thread.new do
|
642
687
|
sleep 0.01
|
643
688
|
gc.stop
|
644
689
|
end
|
645
690
|
|
646
|
-
|
691
|
+
Asynchronic::Process.stub_any_instance(:dead?, -> { id == pid_3 }) do
|
692
|
+
gc.start
|
693
|
+
end
|
647
694
|
|
648
695
|
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal 0
|
649
696
|
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal 38
|
697
|
+
data_store.keys.select { |k| k.start_with? pid_3 }.count.must_equal 0
|
650
698
|
end
|
651
699
|
|
652
700
|
it 'Before finalize hook when completed' do
|
@@ -717,5 +765,4 @@ module LifeCycleExamples
|
|
717
765
|
queue.must_be_empty
|
718
766
|
end
|
719
767
|
|
720
|
-
|
721
768
|
end
|