asynchronic 3.0.3 → 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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +1 -1
  4. data/lib/asynchronic.rb +8 -0
  5. data/lib/asynchronic/data_store/in_memory.rb +17 -15
  6. data/lib/asynchronic/data_store/key.rb +3 -3
  7. data/lib/asynchronic/data_store/lazy_value.rb +5 -3
  8. data/lib/asynchronic/data_store/redis.rb +22 -14
  9. data/lib/asynchronic/data_store/scoped_store.rb +18 -19
  10. data/lib/asynchronic/environment.rb +3 -3
  11. data/lib/asynchronic/error.rb +2 -3
  12. data/lib/asynchronic/job.rb +12 -12
  13. data/lib/asynchronic/notifier/broadcaster.rb +8 -4
  14. data/lib/asynchronic/process.rb +35 -32
  15. data/lib/asynchronic/queue_engine/in_memory.rb +17 -11
  16. data/lib/asynchronic/queue_engine/ost.rb +7 -5
  17. data/lib/asynchronic/queue_engine/synchronic.rb +19 -7
  18. data/lib/asynchronic/version.rb +1 -1
  19. data/lib/asynchronic/worker.rb +7 -10
  20. data/spec/data_store/data_store_examples.rb +17 -9
  21. data/spec/data_store/in_memory_spec.rb +0 -2
  22. data/spec/data_store/key_spec.rb +1 -1
  23. data/spec/data_store/lazy_value_examples.rb +7 -5
  24. data/spec/data_store/redis_spec.rb +4 -10
  25. data/spec/expectations.rb +2 -2
  26. data/spec/facade_spec.rb +3 -3
  27. data/spec/jobs.rb +10 -10
  28. data/spec/minitest_helper.rb +5 -12
  29. data/spec/process/life_cycle_examples.rb +24 -22
  30. data/spec/process/life_cycle_in_memory_spec.rb +0 -1
  31. data/spec/process/life_cycle_redis_spec.rb +0 -1
  32. data/spec/queue_engine/in_memory_spec.rb +1 -3
  33. data/spec/queue_engine/ost_spec.rb +1 -7
  34. data/spec/queue_engine/queue_engine_examples.rb +17 -9
  35. data/spec/queue_engine/synchronic_spec.rb +1 -1
  36. data/spec/worker/in_memory_spec.rb +1 -2
  37. data/spec/worker/redis_spec.rb +0 -6
  38. data/spec/worker/worker_examples.rb +6 -4
  39. metadata +3 -3
@@ -2,27 +2,25 @@ module Asynchronic
2
2
  module QueueEngine
3
3
  class InMemory
4
4
 
5
- attr_reader :default_queue
6
-
7
5
  def initialize(options={})
8
- @default_queue = options[:default_queue]
6
+ @options = options
9
7
  @queues ||= Hash.new { |h,k| h[k] = Queue.new }
10
8
  end
11
9
 
12
10
  def default_queue
13
- @default_queue ||= Asynchronic.default_queue
11
+ @default_queue ||= options.fetch(:default_queue, Asynchronic.default_queue)
14
12
  end
15
13
 
16
14
  def [](name)
17
- @queues[name]
15
+ queues[name]
18
16
  end
19
17
 
20
- def queues
21
- @queues.keys.map(&:to_sym)
18
+ def queue_names
19
+ queues.keys.map(&:to_sym)
22
20
  end
23
21
 
24
22
  def clear
25
- @queues.clear
23
+ queues.clear
26
24
  end
27
25
 
28
26
  def listener
@@ -37,12 +35,16 @@ module Asynchronic
37
35
  [Asynchronic.connection_name]
38
36
  end
39
37
 
38
+ private
39
+
40
+ attr_reader :queues, :options
41
+
40
42
 
41
43
  class Queue
42
44
 
43
45
  extend Forwardable
44
46
 
45
- def_delegators :@queue, :size, :empty?, :to_a
47
+ def_delegators :queue, :size, :empty?, :to_a
46
48
 
47
49
  def initialize
48
50
  @queue = []
@@ -50,13 +52,17 @@ module Asynchronic
50
52
  end
51
53
 
52
54
  def pop
53
- @mutex.synchronize { @queue.shift }
55
+ mutex.synchronize { queue.shift }
54
56
  end
55
57
 
56
58
  def push(message)
57
- @mutex.synchronize { @queue.push message }
59
+ mutex.synchronize { queue.push message }
58
60
  end
59
61
 
62
+ private
63
+
64
+ attr_reader :queue, :mutex
65
+
60
66
  end
61
67
 
62
68
 
@@ -5,22 +5,22 @@ module Asynchronic
5
5
  attr_reader :redis, :default_queue
6
6
 
7
7
  def initialize(options={})
8
- @redis = Redic.new(*Array(options[:redis]))
8
+ @redis = Asynchronic.establish_redis_connection options
9
9
  @default_queue = options.fetch(:default_queue, Asynchronic.default_queue)
10
10
  @queues ||= Hash.new { |h,k| h[k] = Queue.new k, redis }
11
11
  @keep_alive_thread = notify_keep_alive
12
12
  end
13
13
 
14
14
  def [](name)
15
- @queues[name]
15
+ queues[name]
16
16
  end
17
17
 
18
- def queues
19
- (@queues.values.map(&:key) | redis.call!('KEYS', 'ost:*')).map { |q| q.to_s[4..-1].to_sym }
18
+ def queue_names
19
+ (queues.values.map(&:key) | redis.call!('KEYS', 'ost:*')).map { |q| q.to_s[4..-1].to_sym }
20
20
  end
21
21
 
22
22
  def clear
23
- @queues.clear
23
+ queues.clear
24
24
  redis.call!('KEYS', 'ost:*').each { |k| redis.call!('DEL', k) }
25
25
  end
26
26
 
@@ -41,6 +41,8 @@ module Asynchronic
41
41
 
42
42
  private
43
43
 
44
+ attr_reader :queues
45
+
44
46
  def notify_keep_alive
45
47
  Thread.new do
46
48
  loop do
@@ -5,7 +5,7 @@ module Asynchronic
5
5
  attr_reader :stubs
6
6
 
7
7
  def initialize(options={})
8
- @environment = options[:environment]
8
+ @options = options
9
9
  @stubs = {}
10
10
  end
11
11
 
@@ -14,7 +14,7 @@ module Asynchronic
14
14
  end
15
15
 
16
16
  def environment
17
- @environment ||= Asynchronic.environment
17
+ @environment ||= options.fetch(:environment, Asynchronic.environment)
18
18
  end
19
19
 
20
20
  def [](name)
@@ -22,7 +22,7 @@ module Asynchronic
22
22
  end
23
23
 
24
24
  def stub(job, &block)
25
- @stubs[job] = block
25
+ stubs[job] = block
26
26
  end
27
27
 
28
28
  def asynchronic?
@@ -33,6 +33,10 @@ module Asynchronic
33
33
  [Asynchronic.connection_name]
34
34
  end
35
35
 
36
+ private
37
+
38
+ attr_reader :options
39
+
36
40
 
37
41
  class Queue
38
42
 
@@ -41,11 +45,11 @@ module Asynchronic
41
45
  end
42
46
 
43
47
  def push(message)
44
- process = @engine.environment.load_process(message)
48
+ process = engine.environment.load_process(message)
45
49
 
46
- if @engine.stubs[process.type]
50
+ if engine.stubs[process.type]
47
51
  job = process.job
48
- block = @engine.stubs[process.type]
52
+ block = engine.stubs[process.type]
49
53
  process.define_singleton_method :job do
50
54
  MockJob.new job, process, &block
51
55
  end
@@ -54,6 +58,10 @@ module Asynchronic
54
58
  process.execute
55
59
  end
56
60
 
61
+ private
62
+
63
+ attr_reader :engine
64
+
57
65
  end
58
66
 
59
67
 
@@ -66,12 +74,16 @@ module Asynchronic
66
74
  end
67
75
 
68
76
  def call
69
- @block.call @process
77
+ block.call process
70
78
  end
71
79
 
72
80
  def before_finalize
73
81
  end
74
82
 
83
+ private
84
+
85
+ attr_reader :process, :block
86
+
75
87
  end
76
88
 
77
89
  end
@@ -1,3 +1,3 @@
1
1
  module Asynchronic
2
- VERSION = '3.0.3'
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,25 +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
30
+ data_store[:key] = 1
29
31
  value.must_equal 1
30
32
  end
31
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
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
@@ -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