asynchronic 2.0.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +7 -10
  3. data/README.md +1 -2
  4. data/asynchronic.gemspec +3 -2
  5. data/lib/asynchronic.rb +13 -3
  6. data/lib/asynchronic/data_store/in_memory.rb +17 -15
  7. data/lib/asynchronic/data_store/key.rb +3 -3
  8. data/lib/asynchronic/data_store/lazy_value.rb +5 -3
  9. data/lib/asynchronic/data_store/redis.rb +22 -14
  10. data/lib/asynchronic/data_store/scoped_store.rb +18 -19
  11. data/lib/asynchronic/environment.rb +6 -6
  12. data/lib/asynchronic/error.rb +2 -3
  13. data/lib/asynchronic/garbage_collector.rb +2 -0
  14. data/lib/asynchronic/job.rb +12 -12
  15. data/lib/asynchronic/notifier/broadcaster.rb +34 -0
  16. data/lib/asynchronic/notifier/in_memory.rb +33 -0
  17. data/lib/asynchronic/process.rb +52 -38
  18. data/lib/asynchronic/queue_engine/in_memory.rb +17 -11
  19. data/lib/asynchronic/queue_engine/ost.rb +15 -12
  20. data/lib/asynchronic/queue_engine/synchronic.rb +19 -7
  21. data/lib/asynchronic/version.rb +1 -1
  22. data/lib/asynchronic/worker.rb +7 -10
  23. data/spec/data_store/data_store_examples.rb +17 -9
  24. data/spec/data_store/in_memory_spec.rb +0 -2
  25. data/spec/data_store/key_spec.rb +1 -1
  26. data/spec/data_store/lazy_value_examples.rb +7 -6
  27. data/spec/data_store/redis_spec.rb +4 -10
  28. data/spec/expectations.rb +2 -2
  29. data/spec/facade_spec.rb +5 -5
  30. data/spec/jobs.rb +12 -12
  31. data/spec/minitest_helper.rb +6 -12
  32. data/spec/process/life_cycle_examples.rb +111 -64
  33. data/spec/process/life_cycle_in_memory_spec.rb +1 -1
  34. data/spec/process/life_cycle_redis_spec.rb +1 -1
  35. data/spec/queue_engine/in_memory_spec.rb +1 -3
  36. data/spec/queue_engine/ost_spec.rb +1 -7
  37. data/spec/queue_engine/queue_engine_examples.rb +17 -9
  38. data/spec/queue_engine/synchronic_spec.rb +1 -1
  39. data/spec/worker/in_memory_spec.rb +2 -2
  40. data/spec/worker/redis_spec.rb +1 -6
  41. data/spec/worker/worker_examples.rb +7 -5
  42. metadata +38 -17
@@ -1,3 +1,3 @@
1
1
  module Asynchronic
2
- VERSION = '2.0.1'
2
+ VERSION = '4.0.0'
3
3
  end
@@ -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, env)
5
+ def initialize(queue_name, environment)
9
6
  @queue_name = queue_name
10
- @queue = env.queue_engine[queue_name]
11
- @env = env
12
- @listener = env.queue_engine.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
- env.load_process(pid).execute
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
- threads = 1.upto(100).map do |i|
119
+
120
+ threads = 10.times.map do
114
121
  Thread.new do
115
- data_store.synchronize('xxx') do
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 100
131
+
132
+ sum.must_equal threads.count
125
133
  end
126
-
134
+
127
135
  end
@@ -1,6 +1,4 @@
1
1
  require 'minitest_helper'
2
- require_relative './data_store_examples'
3
- require_relative './lazy_value_examples'
4
2
 
5
3
  describe Asynchronic::DataStore::InMemory do
6
4
 
@@ -56,5 +56,5 @@ describe Asynchronic::DataStore::Key do
56
56
  key.remove_last.must_equal 'foo|bar'
57
57
  key.remove_last(2).must_equal 'foo'
58
58
  end
59
-
59
+
60
60
  end
@@ -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] = 1
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] = 1
20
+ data_store[:key] = 1
19
21
  value.must_equal 1
20
22
 
21
- data_store[:key] = 2
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] = 1
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 0.1
72
+ Asynchronic.keep_alive_timeout.must_equal 1
73
73
  end
74
74
 
75
75
  it 'Connection name' do
76
- Asynchronic.connection_name.must_equal "HOST=#{Socket.gethostname},PID=#{::Process.pid}"
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 AbortQueuedAfertErrorJob < Asynchronic::Job
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
@@ -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
- class Module
12
- include Minitest::Spec::DSL
13
- end
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
- let(:env) { Asynchronic::Environment.new queue_engine, data_store }
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 afert error' do
485
- process = create AbortQueuedAfertErrorJob
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 'AbortQueuedAfertErrorJob' => :waiting,
492
- 'AbortQueuedAfertErrorJob::Child_1' => :queued,
493
- 'AbortQueuedAfertErrorJob::Child_2' => :queued,
494
- 'AbortQueuedAfertErrorJob::Child_3' => :queued,
495
- 'AbortQueuedAfertErrorJob::Child_4' => :queued
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 'AbortQueuedAfertErrorJob' => :waiting,
500
- 'AbortQueuedAfertErrorJob::Child_1' => :waiting,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :queued,
504
- 'AbortQueuedAfertErrorJob::Child_3' => :queued,
505
- 'AbortQueuedAfertErrorJob::Child_4' => :queued
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 'AbortQueuedAfertErrorJob' => :waiting,
510
- 'AbortQueuedAfertErrorJob::Child_1' => :waiting,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :completed,
514
- 'AbortQueuedAfertErrorJob::Child_3' => :queued,
515
- 'AbortQueuedAfertErrorJob::Child_4' => :queued
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 'AbortQueuedAfertErrorJob' => :aborted,
520
- 'AbortQueuedAfertErrorJob::Child_1' => :waiting,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :completed,
524
- 'AbortQueuedAfertErrorJob::Child_3' => :aborted,
525
- 'AbortQueuedAfertErrorJob::Child_4' => :queued
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 'AbortQueuedAfertErrorJob' => :aborted,
530
- 'AbortQueuedAfertErrorJob::Child_1' => :waiting,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :completed,
534
- 'AbortQueuedAfertErrorJob::Child_3' => :aborted,
535
- 'AbortQueuedAfertErrorJob::Child_4' => :aborted
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 'AbortQueuedAfertErrorJob' => :aborted,
540
- 'AbortQueuedAfertErrorJob::Child_1' => :aborted,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :completed,
544
- 'AbortQueuedAfertErrorJob::Child_3' => :aborted,
545
- 'AbortQueuedAfertErrorJob::Child_4' => :aborted
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 'AbortQueuedAfertErrorJob' => :aborted,
550
- 'AbortQueuedAfertErrorJob::Child_1' => :aborted,
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
- 'AbortQueuedAfertErrorJob::Child_2' => :completed,
554
- 'AbortQueuedAfertErrorJob::Child_3' => :aborted,
555
- 'AbortQueuedAfertErrorJob::Child_4' => :aborted
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('Completed', &:completed?)
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 ['Completed', 'Waiting', 'Exception']
680
+ gc.conditions_names.must_equal ['Finalized', 'Waiting', 'Exception']
636
681
 
637
682
  gc.remove_condition 'Waiting'
638
-
639
- gc.conditions_names.must_equal ['Completed', 'Exception']
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
- gc.start
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