gb_dispatch 0.0.1 → 0.0.2

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: 2d9b3773249dedae96894b9cc9addb02ca59c1e2
4
- data.tar.gz: c3ee56270eb83c3cf0e68dc0568e450fd718c8c6
3
+ metadata.gz: b286c03ff9e3e0a61a04f57de98ffa2fe7ac351b
4
+ data.tar.gz: 12018509b5949974b22228aa45da2f510842e20d
5
5
  SHA512:
6
- metadata.gz: cf2c44fe50c484e501bd7d89deb51ee47c0349bae1ec9c76f55329600336ea9cddfc5d10456b7ef78a591b7a8e7781465ab9524857ca0c827bf1978ad440a894
7
- data.tar.gz: 796181ec676e815b3c57266d58d6224f9fd20d5033c86b7b1b83f7d8c65c55a370f8bb556418ca68de48ea105c4f081be910bda220a6e203d29ed2f43ad507e2
6
+ metadata.gz: a28e7e5c7fb3e48ebd91b7ee6403eabc298843187b9df271971a9d099a55cc4e21152de0df1a490b30d0466542dab7dd417cdf3c9c728011959ae20688d4d792
7
+ data.tar.gz: 326a1b1f2c0a14c8f82c6348deea13db1881a58a39bfa1174acda2426a465a245ac49c95bd52d983d8d653a18b1c418bd8c7646193a60d276695925983f0313f
data/.gitignore CHANGED
@@ -11,4 +11,5 @@
11
11
  *.so
12
12
  *.o
13
13
  *.a
14
- mkmf.log
14
+ *.gem
15
+ mkmf.log
data/.idea/modules.xml CHANGED
@@ -2,6 +2,7 @@
2
2
  <project version="4">
3
3
  <component name="ProjectModuleManager">
4
4
  <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/gb-dispatch.iml" filepath="$PROJECT_DIR$/.idea/gb-dispatch.iml" />
5
6
  <module fileurl="file://$PROJECT_DIR$/.idea/gb_dispatch.iml" filepath="$PROJECT_DIR$/.idea/gb_dispatch.iml" />
6
7
  </modules>
7
8
  </component>
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in gb_dispatch.gemspec
4
4
  gemspec
5
5
 
6
- gem 'celluloid', '~>0.15.2'
6
+ gem 'celluloid', '<=0.15.2'
7
7
  group :test do
8
8
  gem 'rspec'
9
9
  gem 'simplecov', :require => false
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gb_dispatch (0.0.1)
5
- celluloid (~> 0.15.2)
4
+ gb_dispatch (0.0.2)
5
+ celluloid (>= 0.15.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -12,7 +12,7 @@ GEM
12
12
  diff-lcs (1.2.5)
13
13
  docile (1.1.5)
14
14
  json (1.8.3)
15
- rake (10.3.2)
15
+ rake (10.5.0)
16
16
  rspec (3.4.0)
17
17
  rspec-core (~> 3.4.0)
18
18
  rspec-expectations (~> 3.4.0)
@@ -26,7 +26,7 @@ GEM
26
26
  diff-lcs (>= 1.2.0, < 2.0)
27
27
  rspec-support (~> 3.4.0)
28
28
  rspec-support (3.4.1)
29
- simplecov (0.10.0)
29
+ simplecov (0.11.1)
30
30
  docile (~> 1.1.0)
31
31
  json (~> 1.8)
32
32
  simplecov-html (~> 0.10.0)
@@ -38,8 +38,11 @@ PLATFORMS
38
38
 
39
39
  DEPENDENCIES
40
40
  bundler (~> 1.6)
41
- celluloid (~> 0.15.2)
41
+ celluloid (<= 0.15.2)
42
42
  gb_dispatch!
43
43
  rake (~> 10.0)
44
44
  rspec
45
45
  simplecov
46
+
47
+ BUNDLED WITH
48
+ 1.11.2
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- # GbDispatch
1
+ # GBDispatch
2
2
 
3
- Library allows easy to dispatch block of code for queues.
3
+ Library allows to easily dispatch block of code for queues.
4
+ It is inspired by Grand Central Dispatch behaviour.
4
5
 
5
6
  ## Installation
6
7
 
@@ -18,12 +19,18 @@ Or install it yourself as:
18
19
 
19
20
  $ gem install gb_dispatch
20
21
 
22
+ Then in your script
23
+
24
+ ```ruby
25
+ require 'gb_dispatch'
26
+ ```
27
+
21
28
  ## Usage
22
29
 
23
30
  To dispatch asynchronously
24
31
 
25
32
  ```ruby
26
- GBDispatch.dispatch_async_on_queue :my_queue do
33
+ GBDispatch.dispatch_async :my_queue do
27
34
  puts 'my code here'
28
35
  end
29
36
  ```
@@ -31,14 +38,51 @@ end
31
38
  for synchronous execution
32
39
 
33
40
  ```ruby
34
- GBDispatch.dispatch_sync_on_queue :my_queue do
41
+ my_result = GBDispatch.dispatch_sync :my_queue do
42
+ puts 'my code here'
43
+ end
44
+ ```
45
+
46
+ for delay execution
47
+
48
+ ```ruby
49
+ delay = 4.5 #seconds
50
+ GBDispatch.dispatch_after delay, :my_queue do
35
51
  puts 'my code here'
36
52
  end
37
53
  ```
38
54
 
55
+ ### Using with Rails
56
+
57
+ If you are using Rails, all blocks are wrapped in connection pool,
58
+ so you don't need to worry about creating and removing new connections.
59
+ Only thing you need to do, is to increase connection pool size
60
+ by number of cores of your machine.
61
+
62
+ ## How it works
63
+
64
+ ### Queues
65
+
66
+ For each created queue there is a new thread created. However this threads
67
+ are used only for scheduling purpose. All code execution happens on execution pool.
68
+
69
+ Queues ensure order of execution, but they don't guarantee that all blocks from one queue
70
+ will be executed on the same thread.
71
+
72
+ ### Execution pool
73
+
74
+ This is pool of thread where your code will be executed.
75
+ Amount of threads in the pool match the amount of cores of your machine
76
+ (except if you have only one core, there will be 2 threads).
77
+
78
+ ### Exceptions
79
+
80
+ GBDispatch is designed in the way, that if there is exception thrown it will not crash the whole app/script.
81
+ All exceptions will be logged. If you use +#dispatch_sync+ method, thrown exception will be returned as a result of your block.
82
+
39
83
  ## Contributing
40
84
 
41
- 1. Fork it ( https://github.com/[my-github-username]/gb_dispatch/fork )
85
+ 1. Fork it ( https://github.com/GenieBelt/gb_dispatch/fork )
42
86
  2. Create your feature branch (`git checkout -b my-new-feature`)
43
87
  3. Commit your changes (`git commit -am 'Add some feature'`)
44
88
  4. Push to the branch (`git push origin my-new-feature`)
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ task :build => :spec do
11
11
  sh 'gem build ./gb_dispatch.gemspec'
12
12
  end
13
13
 
14
- task :release do
14
+ task :release_local do
15
15
  require './lib/gb_dispatch/version'
16
16
  sh "gem push gb_dispatch-#{GBDispatch::VERSION}.gem --host http://tools.bobisdead.com/gems"
17
17
  end
data/gb_dispatch.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Kacper Kawecki']
10
10
  spec.email = ['kacper@geniebelt.com']
11
11
  spec.summary = %q{GCD emulation for ruby}
12
- spec.description = %q{Allows to dispatch block of code for queues}
12
+ spec.description = %q{Grand central dispatch emulation for ruby. It allows to easily run asynchronous code. }
13
13
  spec.homepage = 'https://github.com/GenieBelt/gb-dispatch'
14
14
  spec.license = 'MIT'
15
15
 
@@ -18,7 +18,8 @@ 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.15.2'
21
+ spec.add_dependency 'celluloid', '>= 0.15.2'
22
22
  spec.add_development_dependency 'bundler', '~> 1.6'
23
23
  spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec', '~> 3.4.0'
24
25
  end
@@ -16,5 +16,4 @@ class CentralDispatch
16
16
  end
17
17
  end
18
18
  end
19
-
20
19
  end
@@ -1,12 +1,22 @@
1
1
  require 'singleton'
2
2
  require 'gb_dispatch/runner'
3
3
  require 'gb_dispatch/queue'
4
+ # Queue manager for simulating Grand Central Dispatch behaviour.
5
+ #
6
+ # It is singleton class, so all calls should be invoked through +GBDispatch::Manager.instance+
4
7
  module GBDispatch
5
8
  class Manager
6
9
  include Singleton
7
10
 
11
+ # Returns queue of given name.
12
+ #
13
+ # If queue doesn't exists it will create you a new one.
14
+ # Remember that for each allocated queue, there is new thread allocated.
15
+ # @param name [String, Symbol] if not passed, default queue will be returned.
16
+ # @return [GBDispatch::Queue]
8
17
  def get_queue(name=:default)
9
- queue = Celluloid::Actor[name.to_sym]
18
+ name = name.to_sym
19
+ queue = Celluloid::Actor[name]
10
20
  unless queue
11
21
  supervisor = Queue.supervise_as name, name, @pool
12
22
  queue = supervisor.actors.first
@@ -14,19 +24,64 @@ module GBDispatch
14
24
  queue
15
25
  end
16
26
 
17
- # @param queue [GBDispatch::Queue]
27
+ # Run asynchronously given block of code on given queue.
28
+ #
29
+ # This is a proxy for {GBDispatch::Queue#perform} method.
30
+ # @param queue [GBDispatch::Queue] queue on which block will be executed
31
+ # @return [nil]
32
+ # @example
33
+ # my_queue = GBDispatch::Manager.instance.get_queue :my_queue
34
+ # GBDispatch::Manager.instance.run_async_on_queue my_queue do
35
+ # #my delayed code here - probably slow one :)
36
+ # puts 'Delayed Hello World!'
37
+ # end
18
38
  def run_async_on_queue(queue)
19
39
  queue.async.perform ->() { yield }
20
40
  end
21
41
 
22
- # @param queue [GBDispatch::Queue]
42
+ # Run given block of code on given queue and wait for result.
43
+ #
44
+ # This method use {GBDispatch::Queue#perform} and wait for result.
45
+ # @param queue [GBDispatch::Queue] queue on which block will be executed
46
+ # @example sets +my_result+ to 42
47
+ # my_queue = GBDispatch::Manager.instance.get_queue :my_queue
48
+ # my_result = GBDispatch::Manager.instance.run_sync_on_queue my_queue do
49
+ # # my complicated code here
50
+ # puts 'Delayed Hello World!'
51
+ # # return value
52
+ # 42
53
+ # end
23
54
  def run_sync_on_queue(queue)
24
55
  future = queue.future.perform ->() { yield }
25
56
  future.value
26
57
  end
27
58
 
59
+ # Run given block of code on given queue with delay.
60
+ # @param time [Fixnum, Float] delay in seconds
61
+ # @param queue [GBDispatch::Queue] queue on which block will be executed
62
+ # @return [nil]
63
+ # @example Will print 'Hello word!' after 5 seconds.
64
+ # my_queue = GBDispatch::Manager.instance.get_queue :my_queue
65
+ # my_result = GBDispatch::Manager.instance.run_after_on_queue 5, my_queue do
66
+ # puts 'Hello World!'
67
+ # end
68
+ #
69
+ def run_after_on_queue(time, queue)
70
+ queue.perform_after time, ->(){ yield }
71
+ end
72
+
73
+
74
+ # :nodoc:
75
+ def exit
76
+ @pool.terminate
77
+ Celluloid::Actor.all.each do |actor|
78
+ actor.terminate if actor.alive?
79
+ end
80
+ end
81
+
28
82
  private
29
83
 
84
+ # :nodoc:
30
85
  def initialize
31
86
  @pool = Runner.pool
32
87
  end
@@ -13,9 +13,12 @@ module GBDispatch
13
13
  @thread_pool = thread_pool
14
14
  end
15
15
 
16
+ # Perform given block
16
17
  #
18
+ # If used with rails it will wrap block with connection pool.
17
19
  # @param block [Proc]
18
20
  # @yield if there is no block given it yield without param.
21
+ # @return [Object, Exception] returns value of executed block or exception if block execution failed.
19
22
  def perform(block=nil)
20
23
  Thread.current[:name] ||= name
21
24
  if defined?(Rails) && defined?(ActiveRecord::Base)
@@ -39,5 +42,16 @@ module GBDispatch
39
42
  end
40
43
  end
41
44
  end
45
+
46
+ # Perform block after given period
47
+ # @param time [Fixnum]
48
+ # @param block [Proc]
49
+ # @yield if there is no block given it yield without param.
50
+ def perform_after(time, block=nil)
51
+ after(time) do
52
+ block = ->(){ yield } unless block
53
+ self.async.perform block
54
+ end
55
+ end
42
56
  end
43
57
  end
@@ -1,3 +1,3 @@
1
1
  module GBDispatch
2
- VERSION = "0.0.1"
2
+ VERSION = '0.0.2'
3
3
  end
data/lib/gb_dispatch.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'gb_dispatch/version'
2
2
  require 'gb_dispatch/manager'
3
+ require 'celluloid'
3
4
 
4
5
  # Library to dispatch block on queues.
5
6
  # It is inspired by GCD but implementation is based on Celluloid.
@@ -12,36 +13,59 @@ require 'gb_dispatch/manager'
12
13
  # of the machine.
13
14
  #
14
15
  module GBDispatch
16
+ # Get queue of given name
17
+ # @return [GBDispatch:Queue]
18
+ # @param name [#to_sym]
19
+ def self.get_queue(name)
20
+ GBDispatch::Manager.instance.get_queue(name)
21
+ end
22
+
15
23
  # Dispatch asynchronously on queue
16
24
  # @param queue [Symbol, GBDispatch::Queue] queue object or name
17
25
  # @yield block to execute
18
- def self.dispatch_async_on_queue(queue)
26
+ def self.dispatch_async(queue)
19
27
  queue = GBDispatch::Manager.instance.get_queue(queue) unless queue.is_a? GBDispatch::Queue
20
28
  GBDispatch::Manager.instance.run_async_on_queue queue do
21
29
  yield
22
30
  end
23
31
  end
24
32
 
25
- # Get queue of given name
26
- # @return [GBDispatch:Queue]
27
- # @param name [#to_sym]
28
- def self.get_queue(name)
29
- GBDispatch::Manager.instance.get_queue(name)
33
+ # Dispatch synchronously on queue and return result
34
+ # @param queue [Symbol, GBDispatch::Queue] queue object or name
35
+ # @yield block to execute
36
+ def self.dispatch_sync(queue)
37
+ queue = GBDispatch::Manager.instance.get_queue(queue) unless queue.is_a? GBDispatch::Queue
38
+ GBDispatch::Manager.instance.run_sync_on_queue queue do
39
+ yield
40
+ end
30
41
  end
31
42
 
32
- # Dispatch synchronously on queue and return result
43
+
44
+ # Dispatch on queue with delay.
45
+ # @param delay [Fixnum, Float] delay in seconds
33
46
  # @param queue [Symbol, GBDispatch::Queue] queue object or name
34
47
  # @yield block to execute
35
- def self.dispatch_sync_on_queue(queue)
48
+ def self.dispatch_after(delay, queue)
36
49
  queue = GBDispatch::Manager.instance.get_queue(queue) unless queue.is_a? GBDispatch::Queue
37
50
  GBDispatch::Manager.instance.run_async_on_queue queue do
38
51
  yield
39
52
  end
40
53
  end
41
54
 
55
+
42
56
  # Setup logger. By default it use Celluloid logger
43
57
  # @param logger [Logger]
44
58
  def self.logger=(logger)
45
59
  Celluloid.logger = logger
46
60
  end
61
+
62
+ class << self
63
+ alias_method :dispatch_sync_on_queue, :dispatch_sync
64
+ alias_method :dispatch_async_on_queue, :dispatch_async
65
+ alias_method :dispatch_after_on_queue, :dispatch_after
66
+ end
67
+
68
+ at_exit do
69
+ GBDispatch::Manager.instance.exit
70
+ end
47
71
  end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+ require 'gb_dispatch'
3
+
4
+ describe GBDispatch do
5
+
6
+ it 'should run dispatch_async' do
7
+ a = []
8
+ GBDispatch.dispatch_async :test do
9
+ sleep(0.01)
10
+ a << 1
11
+ end
12
+ GBDispatch.dispatch_async :test do
13
+ a << 2
14
+ end
15
+ expect(a.empty?).to be_truthy
16
+ sleep(0.02)
17
+ expect(a).to eq [1, 2]
18
+ end
19
+
20
+ it 'should run dispatch_async_on_queue' do
21
+ a = []
22
+ GBDispatch.dispatch_async_on_queue :test do
23
+ sleep(0.01)
24
+ a << 1
25
+ end
26
+ GBDispatch.dispatch_async_on_queue :test do
27
+ a << 2
28
+ end
29
+ expect(a.empty?).to be_truthy
30
+ sleep(0.02)
31
+ expect(a).to eq [1, 2]
32
+ end
33
+
34
+ it 'should run dispatch_sync' do
35
+ a = []
36
+ GBDispatch.dispatch_async :test do
37
+ sleep(0.02)
38
+ a << 1
39
+ end
40
+ result = GBDispatch.dispatch_sync :test do
41
+ a << 2
42
+ a
43
+ end
44
+ expect(result).to eq [1,2]
45
+ end
46
+
47
+ it 'should run dispatch_sync_on_queue' do
48
+ a = []
49
+ GBDispatch.dispatch_async :test do
50
+ sleep(0.02)
51
+ a << 1
52
+ end
53
+ result = GBDispatch.dispatch_sync_on_queue :test do
54
+ a << 2
55
+ a
56
+ end
57
+ expect(result).to eq [1,2]
58
+ end
59
+
60
+ it 'should run dispatch_after' do
61
+ a = []
62
+ GBDispatch.dispatch_after 0.1, :test do
63
+ a << 1
64
+ end
65
+ expect(a.empty?).to be_truthy
66
+ sleep(0.15)
67
+ expect(a).to eq [1]
68
+ end
69
+
70
+ it 'should run dispatch_after_on_queue' do
71
+ a = []
72
+ GBDispatch.dispatch_after_on_queue 0.1, :test do
73
+ a << 1
74
+ end
75
+ expect(a.empty?).to be_truthy
76
+ sleep(0.15)
77
+ expect(a).to eq [1]
78
+ end
79
+
80
+ it 'should return proper queue' do
81
+ queue = GBDispatch.get_queue :test
82
+ expect(queue.name).to eq :test
83
+ expect(queue).to be_a GBDispatch::Queue
84
+ end
85
+ end
data/spec/queue_spec.rb CHANGED
@@ -55,7 +55,7 @@ describe GBDispatch::Queue do
55
55
  queue.async.perform ->() do
56
56
  (11..20).each { |x| a << x }
57
57
  end
58
- sleep(0.06)
58
+ sleep(0.08)
59
59
  expect(a).to eq (0..20).to_a
60
60
  queue.terminate
61
61
  end
@@ -75,6 +75,22 @@ describe GBDispatch::Queue do
75
75
  end
76
76
  end
77
77
 
78
+ context 'after' do
79
+ it 'should bea bale to run block of code after specified time' do
80
+ a = []
81
+ queue = GBDispatch::Queue.new(:test, @pool)
82
+ queue.perform_after 0.5, ->() { a << rand() }
83
+ queue.perform_after 0.7, ->() { a << rand() }
84
+ sleep 0.4
85
+ expect(a.count).to eq 0
86
+ sleep 0.2
87
+ expect(a.count).to eq 1
88
+ sleep 0.2
89
+ expect(a.count).to eq 2
90
+ queue.terminate
91
+ end
92
+ end
93
+
78
94
  context 'rails' do
79
95
  before(:each) do
80
96
  class Rails
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gb_dispatch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
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-01-12 00:00:00.000000000 Z
11
+ date: 2016-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.15.2
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
26
  version: 0.15.2
27
27
  - !ruby/object:Gem::Dependency
@@ -52,7 +52,22 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
- description: Allows to dispatch block of code for queues
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.4.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.4.0
69
+ description: 'Grand central dispatch emulation for ruby. It allows to easily run asynchronous
70
+ code. '
56
71
  email:
57
72
  - kacper@geniebelt.com
58
73
  executables: []
@@ -78,6 +93,7 @@ files:
78
93
  - lib/gb_dispatch/queue.rb
79
94
  - lib/gb_dispatch/runner.rb
80
95
  - lib/gb_dispatch/version.rb
96
+ - spec/dispatch_spec.rb
81
97
  - spec/queue_spec.rb
82
98
  - spec/runner_spec.rb
83
99
  - spec/spec_helper.rb
@@ -101,11 +117,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
117
  version: '0'
102
118
  requirements: []
103
119
  rubyforge_project:
104
- rubygems_version: 2.4.8
120
+ rubygems_version: 2.5.1
105
121
  signing_key:
106
122
  specification_version: 4
107
123
  summary: GCD emulation for ruby
108
124
  test_files:
125
+ - spec/dispatch_spec.rb
109
126
  - spec/queue_spec.rb
110
127
  - spec/runner_spec.rb
111
128
  - spec/spec_helper.rb