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.
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