gb_dispatch 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd041feeb927183160d8026c38344e6613eb2732
4
- data.tar.gz: 64288309c1cace61a076ab1adee82d2a9ef41912
3
+ metadata.gz: e680d48b7567d1f4aff1ac5fd621da86bd4f333b
4
+ data.tar.gz: 557546149b930191018e5ccdb9c1096962690a26
5
5
  SHA512:
6
- metadata.gz: 768ca64392814c1b0a72a9bef66e0114242f4fcb08d5b412e8665aa8bc8e26771d299909bcaf388e8e1717e36a92afb6025f667cd6728010713e117d2ed68554
7
- data.tar.gz: 5f412a4ae3d9cdd91f3c3cf50130b206049adf6e426736700ec58ab6cfe0c79b3867008d905bc24fb7e93fb349f1babeafb72af4b3a7ddf074c69fe42dbcf4f5
6
+ metadata.gz: 99b9194f55c7b6ce44bed5b1989fa4bb327780d83fdd5641fbba6a240be9dee3a5e075708b580dd67512ee85c10e7ce7575f0164094e7403e9c1e184284cac17
7
+ data.tar.gz: 97549f375b24e1b98d36de93903a8b128d850dce68ffd1c0c7751863130e900074491d7685684911c33071b9b325c855974ce636be5aac5fcccea6e1fde3c5c0
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in gb_dispatch.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'concurrent-ruby-ext'
6
7
 
7
8
  group :test do
8
9
  gem 'rspec'
data/Gemfile.lock CHANGED
@@ -1,32 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gb_dispatch (0.0.4)
5
- celluloid (~> 0.17.3)
4
+ gb_dispatch (0.0.5)
5
+ concurrent-ruby (~> 1.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- celluloid (0.17.3)
11
- celluloid-essentials
12
- celluloid-extras
13
- celluloid-fsm
14
- celluloid-pool
15
- celluloid-supervision
16
- timers (>= 4.1.1)
17
- celluloid-essentials (0.20.5)
18
- timers (>= 4.1.1)
19
- celluloid-extras (0.20.5)
20
- timers (>= 4.1.1)
21
- celluloid-fsm (0.20.5)
22
- timers (>= 4.1.1)
23
- celluloid-pool (0.20.5)
24
- timers (>= 4.1.1)
25
- celluloid-supervision (0.20.5)
26
- timers (>= 4.1.1)
10
+ concurrent-ruby (1.0.0)
11
+ concurrent-ruby-ext (1.0.0)
12
+ concurrent-ruby (~> 1.0.0)
27
13
  diff-lcs (1.2.5)
28
14
  docile (1.1.5)
29
- hitimes (1.2.3)
30
15
  json (1.8.3)
31
16
  rake (10.5.0)
32
17
  rspec (3.4.0)
@@ -47,18 +32,14 @@ GEM
47
32
  json (~> 1.8)
48
33
  simplecov-html (~> 0.10.0)
49
34
  simplecov-html (0.10.0)
50
- timers (4.1.1)
51
- hitimes
52
35
 
53
36
  PLATFORMS
54
37
  ruby
55
38
 
56
39
  DEPENDENCIES
57
40
  bundler (~> 1.6)
41
+ concurrent-ruby-ext
58
42
  gb_dispatch!
59
43
  rake (~> 10.0)
60
44
  rspec
61
45
  simplecov
62
-
63
- BUNDLED WITH
64
- 1.11.2
data/gb_dispatch.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'celluloid', '~> 0.17.3'
21
+ spec.add_dependency 'concurrent-ruby', '~> 1.0'
22
22
  spec.add_development_dependency 'bundler', '~> 1.6'
23
23
  spec.add_development_dependency 'rake', '~> 10.0'
24
24
  spec.add_development_dependency 'rspec', '~> 3.4'
@@ -16,17 +16,17 @@ module GBDispatch
16
16
  # @return [GBDispatch::Queue]
17
17
  def get_queue(name=:default_queue)
18
18
  name = name.to_sym
19
- queue = Celluloid::Actor[name]
19
+ queue = @queues[name]
20
20
  unless queue
21
- Queue.supervise as: name, args: [name, @pool]
22
- queue = Celluloid::Actor[name]
21
+ @queues[name] = GBDispatch::Queue.new(name)
22
+ queue = @queues[name]
23
23
  end
24
24
  queue
25
25
  end
26
26
 
27
27
  # Run asynchronously given block of code on given queue.
28
28
  #
29
- # This is a proxy for {GBDispatch::Queue#perform} method.
29
+ # This is a proxy for {GBDispatch::Queue#perform_now} method.
30
30
  # @param queue [GBDispatch::Queue] queue on which block will be executed
31
31
  # @return [nil]
32
32
  # @example
@@ -37,12 +37,12 @@ module GBDispatch
37
37
  # end
38
38
  def run_async_on_queue(queue)
39
39
  raise ArgumentError.new 'Queue must be GBDispatch::Queue' unless queue.is_a? GBDispatch::Queue
40
- queue.async.perform ->() { yield }
40
+ queue.async.perform_now ->() { yield }
41
41
  end
42
42
 
43
43
  # Run given block of code on given queue and wait for result.
44
44
  #
45
- # This method use {GBDispatch::Queue#perform} and wait for result.
45
+ # This method use {GBDispatch::Queue#perform_now} and wait for result.
46
46
  # @param queue [GBDispatch::Queue] queue on which block will be executed
47
47
  # @example sets +my_result+ to 42
48
48
  # my_queue = GBDispatch::Manager.instance.get_queue :my_queue
@@ -54,7 +54,7 @@ module GBDispatch
54
54
  # end
55
55
  def run_sync_on_queue(queue)
56
56
  raise ArgumentError.new 'Queue must be GBDispatch::Queue' unless queue.is_a? GBDispatch::Queue
57
- future = queue.future.perform ->() { yield }
57
+ future = queue.await.perform_now ->() { yield }
58
58
  future.value
59
59
  end
60
60
 
@@ -76,17 +76,18 @@ module GBDispatch
76
76
 
77
77
  # :nodoc:
78
78
  def exit
79
- @pool.terminate
80
- Celluloid::Actor.all.each do |actor|
81
- actor.terminate if actor.alive?
79
+ @queues.each_key do |name|
80
+ @queues[name] = nil
82
81
  end
82
+ Runner.pool.shutdown
83
+ Runner.pool.wait_for_termination
83
84
  end
84
85
 
85
86
  private
86
87
 
87
88
  # :nodoc:
88
89
  def initialize
89
- @pool = Runner.pool
90
+ @queues = Concurrent::Map.new
90
91
  end
91
92
  end
92
93
  end
@@ -1,17 +1,15 @@
1
- require 'celluloid/current'
1
+ require 'concurrent'
2
2
  module GBDispatch
3
3
  class Queue
4
- include Celluloid
4
+ include Concurrent::Async
5
5
 
6
6
  # @return [String] queue name
7
7
  attr_reader :name
8
8
 
9
9
  # @param name [String] queue name, should be the same as is register in Celluloid
10
- # @param thread_pool [Celluloid::Pool] pool of runners for executing code.
11
- def initialize(name, thread_pool)
10
+ def initialize(name)
11
+ super()
12
12
  @name = name
13
- @thread_pool = thread_pool
14
- @executing = false
15
13
  end
16
14
 
17
15
  # Perform given block
@@ -20,7 +18,7 @@ module GBDispatch
20
18
  # @param block [Proc]
21
19
  # @yield if there is no block given it yield without param.
22
20
  # @return [Object, Exception] returns value of executed block or exception if block execution failed.
23
- def perform(block=nil)
21
+ def perform_now(block=nil)
24
22
  Thread.current[:name] ||= name
25
23
  if defined?(Rails) && defined?(ActiveRecord::Base)
26
24
  thread_block = ->() do
@@ -35,30 +33,25 @@ module GBDispatch
35
33
  else
36
34
  thread_block = block ? block : ->() { yield }
37
35
  end
38
- while @executing
39
- sleep(0.0001)
36
+ begin
37
+ Runner.execute thread_block, name: name
38
+ rescue Exception => e
39
+ return e
40
40
  end
41
- #exclusive do
42
- begin
43
- @executing = true
44
- @thread_pool.execute thread_block, name: name
45
- rescue Exception => e
46
- return e
47
- ensure
48
- @executing = false
49
- end
50
- #end
51
41
  end
52
42
 
53
43
  # Perform block after given period
54
44
  # @param time [Fixnum]
55
45
  # @param block [Proc]
56
46
  # @yield if there is no block given it yield without param.
47
+ # @return [Concurrent::ScheduledTask]
57
48
  def perform_after(time, block=nil)
58
- after(time) do
49
+ task = Concurrent::ScheduledTask.new(time) do
59
50
  block = ->(){ yield } unless block
60
- self.async.perform block
51
+ self.async.perform_now block
61
52
  end
53
+ task.execute
54
+ task
62
55
  end
63
56
 
64
57
  def to_s
@@ -1,30 +1,55 @@
1
- require 'celluloid/current'
1
+ require 'concurrent'
2
2
  module GBDispatch
3
3
  class Runner
4
- include Celluloid
4
+ class << self
5
+ attr_accessor :pool_size
5
6
 
6
- # Execute given block.
7
- # If there is an exception thrown, it log it and crash actor.
8
- # For more information about error handling, check Celluloid documentation.
9
- # @param block [Proc]
10
- # @param options [Hash]
11
- # @option options [Proc] :condition celluloid condition block called on finish with result
12
- # @option options [String] :name queue name used for debugging and better logging.
13
- def execute(block, options=Hash.new)
14
- begin
15
- condition = options[:condition]
16
- result = block.call
17
- condition.call(result) if condition
18
- result
19
- rescue Exception => e
20
- name = options[:name]
21
- if defined?(Opbeat)
22
- Opbeat.set_context extra: {queue: name} if name
23
- Opbeat.capture_exception(e)
7
+ # Thread pool for async execution.
8
+ # Pool size is set by default to core numbers or at least 2.
9
+ # You can increase size of pool by setting :pool_size variable before using pool.
10
+ # @return [Concurrent::ThreadPoolExecutor]
11
+ def pool
12
+ unless @pool
13
+ self.pool_size ||=2
14
+ threads = [self.pool_size, 2, Concurrent.processor_count].max
15
+ @pool = Concurrent::ThreadPoolExecutor.new(
16
+ min_threads: 2,
17
+ max_threads: threads,
18
+ max_queue: 10*threads,
19
+ fallback_policy: :caller_runs
20
+ )
24
21
  end
25
- Celluloid.logger.error "Failed execution of queue #{name} with error #{e.message}"
26
- condition.call(e) if condition
27
- raise e
22
+ @pool
23
+ end
24
+
25
+ # Execute given block.
26
+ # If there is an exception thrown, it log it and crash actor.
27
+ # For more information about error handling, check Celluloid documentation.
28
+ # @param block [Proc]
29
+ # @param options [Hash]
30
+ # @option options [String] :name queue name used for debugging and better logging.
31
+ def execute(block, options=Hash.new)
32
+ future = Concurrent::Future.new(:executor => self.pool) do
33
+ begin
34
+ name = options[:name]
35
+ Thread.current[:name] ||= name if name
36
+ result = block.call
37
+ result
38
+ rescue Exception => e
39
+ if defined?(Opbeat)
40
+ Opbeat.set_context extra: {queue: name} if name
41
+ Opbeat.capture_exception(e)
42
+ end
43
+ GBDispatch.logger.error "Failed execution of queue #{name} with error #{e.message}" if GBDispatch.logger
44
+ raise e
45
+ end
46
+ end
47
+ future.execute
48
+ future.value
49
+ if future.rejected?
50
+ raise future.reason
51
+ end
52
+ future.value
28
53
  end
29
54
  end
30
55
  end
@@ -1,3 +1,3 @@
1
1
  module GBDispatch
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
@@ -26,9 +26,12 @@ describe GBDispatch do
26
26
  GBDispatch.dispatch_async_on_queue :test do
27
27
  a << 2
28
28
  end
29
+ GBDispatch.dispatch_async_on_queue :test do
30
+ a << 3
31
+ end
29
32
  expect(a.empty?).to be_truthy
30
33
  sleep(0.02)
31
- expect(a).to eq [1, 2]
34
+ expect(a).to eq [1, 2, 3]
32
35
  end
33
36
 
34
37
  it 'should run dispatch_sync' do
@@ -81,5 +84,6 @@ describe GBDispatch do
81
84
  queue = GBDispatch.get_queue :test
82
85
  expect(queue).to be_a GBDispatch::Queue
83
86
  expect(queue.name).to eq :test
87
+ expect(GBDispatch.get_queue :test).to equal queue
84
88
  end
85
89
  end
data/spec/queue_spec.rb CHANGED
@@ -4,81 +4,73 @@ require 'gb_dispatch/runner'
4
4
 
5
5
 
6
6
  describe GBDispatch::Queue do
7
- before(:all) { @pool = GBDispatch::Runner.pool }
8
- after(:all) { @pool.terminate }
9
7
 
10
8
  context 'synchronous' do
11
9
  it 'should execute lambda' do
12
10
  a = :foo
13
- queue = GBDispatch::Queue.new(:test, @pool)
14
- queue.perform ->() { a = :bar }
11
+ queue = GBDispatch::Queue.new(:test)
12
+ queue.await.perform_now ->() { a = :bar }
15
13
  expect(a).to eq :bar
16
- queue.terminate
17
14
  end
18
15
 
19
16
  it 'should execute block' do
20
17
  a = :foo
21
- queue = GBDispatch::Queue.new(:test, @pool)
22
- queue.perform do
18
+ queue = GBDispatch::Queue.new(:test)
19
+ queue.perform_now do
23
20
  a = :bar
24
21
  end
25
22
  expect(a).to eq :bar
26
- queue.terminate
27
23
  end
28
24
 
29
25
  it 'should return value of the block' do
30
- queue = GBDispatch::Queue.new(:test, @pool)
31
- a = queue.perform do
26
+ queue = GBDispatch::Queue.new(:test)
27
+ a = queue.perform_now do
32
28
  :bar
33
29
  end
34
30
  expect(a).to eq :bar
35
- queue.terminate
36
31
  end
37
32
 
38
33
  it 'should return exception object on failure' do
39
- queue = GBDispatch::Queue.new(:test, @pool)
40
- a = queue.perform ->() do
34
+ queue = GBDispatch::Queue.new(:test)
35
+ a = queue.perform_now ->() do
41
36
  raise StandardError.new 'Test error'
42
37
  end
43
38
  expect(a).to be_kind_of StandardError
44
- queue.terminate
45
39
  end
46
40
  end
47
41
 
48
42
  context 'asynchronous' do
49
43
  it 'should execute in proper order - one after each other' do
50
44
  a = []
51
- queue = GBDispatch::Queue.new(:test, @pool)
52
- queue.async.perform ->() do
45
+ queue = GBDispatch::Queue.new(:test)
46
+ queue.async.perform_now ->() do
53
47
  (0..10).each { |x| (a << x) && sleep(0.005) }
54
48
  end
55
- queue.async.perform ->() do
49
+ queue.async.perform_now ->() do
56
50
  (11..20).each { |x| a << x }
57
51
  end
58
52
  sleep(0.08)
59
53
  expect(a).to eq (0..20).to_a
60
- queue.terminate
61
54
  end
62
55
 
63
56
  it 'should handle failures nicely' do
64
- queue = GBDispatch::Queue.new(:test, @pool)
57
+ queue = GBDispatch::Queue.new(:test)
65
58
  a = :foo
66
- queue.async.perform ->() do
59
+ queue.async.perform_now ->() do
67
60
  raise StandardError.new 'Test error'
68
61
  end
69
- queue.async.perform ->() do
62
+ queue.async.perform_now ->() do
70
63
  a = :bar
71
64
  end
72
65
  sleep(0.05)
73
66
  expect(a).to eq :bar
74
- queue.terminate
75
67
  end
76
68
  end
77
69
 
78
70
  context 'after' do
79
71
  it 'should bea bale to run block of code after specified time' do
80
72
  a = []
81
- queue = GBDispatch::Queue.new(:test, @pool)
73
+ queue = GBDispatch::Queue.new(:test)
82
74
  queue.perform_after 0.5, ->() { a << rand() }
83
75
  queue.perform_after 0.7, ->() { a << rand() }
84
76
  sleep 0.4
@@ -87,7 +79,6 @@ describe GBDispatch::Queue do
87
79
  expect(a.count).to eq 1
88
80
  sleep 0.2
89
81
  expect(a.count).to eq 2
90
- queue.terminate
91
82
  end
92
83
  end
93
84
 
@@ -138,14 +129,13 @@ describe GBDispatch::Queue do
138
129
 
139
130
  it 'should wrap execution with connection pool' do
140
131
  a = :foo
141
- queue = GBDispatch::Queue.new(:test, @pool)
132
+ queue = GBDispatch::Queue.new(:test)
142
133
  expect(ActiveRecord::Base.connection_pool).to receive(:with_connection).and_call_original
143
134
  expect(ActiveRecord::Base).to receive(:clear_active_connections!)
144
- queue.perform do
135
+ queue.await.perform_now do
145
136
  a = :bar
146
137
  end
147
138
  expect(a).to eq :bar
148
- queue.terminate
149
139
  end
150
140
  end
151
141
  end
data/spec/runner_spec.rb CHANGED
@@ -5,49 +5,28 @@ describe GBDispatch::Runner do
5
5
 
6
6
  it 'should execute synchronously' do
7
7
  a = :foo
8
- actor = GBDispatch::Runner.new
9
- actor.execute ->() { a=:bar }
8
+ GBDispatch::Runner.execute ->() { a=:bar }
10
9
  expect(a).to eq :bar
11
- actor.terminate
12
10
  end
13
11
 
14
12
  it 'should return result of passed block' do
15
- actor = GBDispatch::Runner.new
16
- a = actor.execute ->() { :bar }
13
+ a = GBDispatch::Runner.execute ->() { :bar }
17
14
  expect(a).to eq :bar
18
- actor.terminate
19
15
  end
20
16
 
21
- it 'should execute async' do
17
+ it 'should execute on different thread' do
18
+ Thread.current[:name] = :foo
22
19
  a = :foo
23
- actor = GBDispatch::Runner.new
24
- actor.async.execute ->() do
25
- sleep(0.01)
26
- a = :bar
27
- end
28
- expect(a).to eq :foo
29
- sleep(0.015)
30
- expect(a).to eq :bar
31
- actor.terminate
20
+ GBDispatch::Runner.execute ->() do
21
+ a = Thread.current[:name]
22
+ end, name: :bar
23
+ expect(a).not_to eq :foo
32
24
  end
33
25
 
34
- it 'should support Celluloid Conditions' do
35
- a = :foo
36
- actor = GBDispatch::Runner.new
37
- actor.async.execute ->() { 5+5 }, :condition => ->(result) { a = result }
38
- sleep(0.01)
39
- expect(a).to eq 10
40
- actor.terminate
41
- end
42
26
 
43
27
  context 'error handling' do
44
28
  it 'should call Celluloid Conditions with exception' do
45
- a = :foo
46
- actor = GBDispatch::Runner.new
47
- actor.async.execute ->() { raise StandardError.new 'Test' }, :condition => ->(result) { a = result }, name: :fail_test
48
- sleep(0.01)
49
- expect(a).to be_kind_of StandardError
50
- expect(actor.alive?).to be_falsey
29
+ expect { GBDispatch::Runner.execute ->() { raise StandardError.new 'Test' }, name: :fail_test }.to raise_error StandardError
51
30
  end
52
31
  end
53
32
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gb_dispatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kacper Kawecki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-16 00:00:00.000000000 Z
11
+ date: 2016-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: celluloid
14
+ name: concurrent-ruby
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.17.3
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.17.3
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -132,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  version: '0'
133
133
  requirements: []
134
134
  rubyforge_project:
135
- rubygems_version: 2.5.1
135
+ rubygems_version: 2.4.8
136
136
  signing_key:
137
137
  specification_version: 4
138
138
  summary: GCD emulation for ruby
@@ -141,3 +141,4 @@ test_files:
141
141
  - spec/queue_spec.rb
142
142
  - spec/runner_spec.rb
143
143
  - spec/spec_helper.rb
144
+ has_rdoc: