breeder 0.0.1

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.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ == 0.0.1 / 2011-10-19
2
+
3
+ * Initial Release
data/LICENSE.txt ADDED
@@ -0,0 +1,17 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2
+ of this software and associated documentation files (the "Software"), to deal
3
+ in the Software without restriction, including without limitation the rights
4
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5
+ copies of the Software, and to permit persons to whom the Software is
6
+ furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in
9
+ all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ h1. Breeder
2
+
3
+ Currently does not spawn or reap.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run all specs"
6
+ RSpec::Core::RakeTask.new(:rspec) do |spec|
7
+ spec.pattern = 'spec/**/*_spec.rb'
8
+ end
9
+
10
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
11
+ spec.pattern = 'spec/**/*_spec.rb'
12
+ spec.rcov = true
13
+ end
14
+
15
+ task :default => :rspec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,83 @@
1
+ module Breeder
2
+ class Core
3
+ # the poll interval in seconds
4
+ attr_accessor :interval
5
+
6
+ # an instance with spawn? and reap? methods to determine when to spawn and reap
7
+ attr_reader :watcher
8
+
9
+ # number of workers to start with
10
+ attr_accessor :initial_workers
11
+
12
+ def initialize
13
+ @workers = []
14
+ @threads = []
15
+ self.interval = 5
16
+ self.initial_workers = 4
17
+ end
18
+
19
+ def watcher=(watcher)
20
+ unless watcher.respond_to?(:spawn?) && watcher.respond_to?(:reap?)
21
+ raise "Watcher must implement spawn? and reap?"
22
+ end
23
+
24
+ @watcher = watcher
25
+ end
26
+
27
+ def worker_factory(&block)
28
+ raise "No block supplied to worker_factory" unless !!block
29
+ @worker_factory = block
30
+ end
31
+
32
+ def task(&block)
33
+ raise ArgumentError("No block supplied") if block.nil?
34
+ worker = Breeder::Worker.new
35
+ worker.__metaclass__.class_eval do
36
+ define_method(:do_work, block)
37
+ end
38
+ worker_factory { worker }
39
+ end
40
+
41
+ def run
42
+ # start the workers
43
+ self.initial_workers.times { spawn! }
44
+
45
+ # catch Ctrl+C and cleanup
46
+ trap('INT') do
47
+ puts 'INTERRUPT caught, killing threads and exiting...'
48
+ @threads.each { |thread| thread.kill }
49
+ end
50
+
51
+ # wait for the workers to finish
52
+ @threads.each { |thread| thread.join }
53
+ end
54
+
55
+ def create_worker
56
+ raise "No worker factory specified" unless !!@worker_factory
57
+ worker = @worker_factory.call
58
+ unless [:run, :stop!, :stop?].all? { |method| worker.respond_to?(method) }
59
+ raise "object from worker factory doesn't quack like a worker"
60
+ end
61
+ worker
62
+ end
63
+
64
+ private
65
+
66
+ def spawn!
67
+ worker = create_worker
68
+ @workers << worker
69
+ @threads << Thread.new { worker.run }
70
+ end
71
+
72
+ def reap!
73
+ if @threads.size >= 1
74
+ thread = @threads.pop
75
+ worker = @workers.pop
76
+ worker.stop!
77
+ sleep 1
78
+ thread.kill
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,16 @@
1
+ module Breeder
2
+
3
+ # A watcher has a spawn? and reap? method that indicate when to
4
+ # spawn and reap more threads
5
+ class Watcher
6
+
7
+ def spawn?(num_workers)
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def reap?(num_workers)
12
+ raise NotImplementedError
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module Breeder
2
+ class Worker
3
+ attr_accessor :should_stop
4
+
5
+ def stop?
6
+ @should_stop
7
+ end
8
+
9
+ def stop!
10
+ @should_stop = true
11
+ end
12
+
13
+ def run
14
+ until stop?
15
+ do_work
16
+ end
17
+ end
18
+
19
+ # User-defined worker should override this
20
+ def do_work
21
+ raise NotImplementedError
22
+ end
23
+
24
+ end
25
+ end
data/lib/breeder.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'metaclass'
4
+ require 'breeder/core'
5
+ require 'breeder/watcher'
6
+ require 'breeder/worker'
7
+
8
+ module Breeder
9
+ # Create a Breeder::Core and take a block to configure it
10
+ def self.create
11
+ core = Breeder::Core.new
12
+ yield core if block_given?
13
+ core
14
+ end
15
+
16
+ # Configure and run a Breeder::Core
17
+ def self.breed(&block)
18
+ core = Breeder::Core.new
19
+ yield core
20
+ core.run
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Breeder do
4
+ describe '.create' do
5
+ it 'returns a Breeder::Core' do
6
+ Breeder.create.should be_a(Breeder::Core)
7
+ end
8
+
9
+ it 'takes a block to configure the Core' do
10
+ @mock_core = mock('core')
11
+ Breeder::Core.stub!(:new).and_return(@mock_core)
12
+ @mock_core.should_receive(:interval=).with(5)
13
+ breeder = Breeder.create do |core|
14
+ core.interval = 5
15
+ end
16
+ breeder.should == @mock_core
17
+ end
18
+ end
19
+
20
+ describe '.breed' do
21
+ before(:each) do
22
+ @mock_core = mock('core')
23
+ Breeder::Core.stub!(:new).and_return(@mock_core)
24
+ end
25
+
26
+ it 'runs the Core after configuration' do
27
+ @mock_core.should_receive(:interval=).with(5).ordered
28
+ @mock_core.should_receive(:run).ordered
29
+ Breeder.breed do |core|
30
+ core.interval = 5
31
+ end
32
+ end
33
+ end
34
+ end
data/spec/core_spec.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ module Breeder
4
+ describe Core do
5
+ before(:each) do
6
+ @core = Breeder.create
7
+ end
8
+
9
+ describe '#watcher=' do
10
+ context 'when the argument is not a valid watcher' do
11
+ it 'raises an exception' do
12
+ lambda { @core.watcher = 42 }.should raise_error
13
+ end
14
+ end
15
+
16
+ context 'when the argument is a valid watcher' do
17
+ it 'sets the watcher' do
18
+ watcher = Breeder::Watcher.new
19
+ @core.watcher = watcher
20
+ @core.watcher.should == watcher
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#worker=' do
26
+ context 'when the argument is not a valid worker' do
27
+ it 'raises an error' do
28
+ lambda { @core.worker= 42 }.should raise_error
29
+ end
30
+ end
31
+
32
+ context 'when the argument is a valid worker' do
33
+ it 'sets the worker' do
34
+ test_worker = Breeder::Worker.new
35
+ @core.worker_factory { test_worker }
36
+ @core.create_worker.should == test_worker
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#task' do
42
+ context 'when no block is supplied' do
43
+ it 'raises an error' do
44
+ lambda { @core.task }.should raise_error
45
+ end
46
+ end
47
+
48
+ context 'when a block of work is supplied' do
49
+ it 'creates a worker with the block as its workload' do
50
+ task_done = false
51
+ @core.task { task_done = true }
52
+ @core.create_worker.do_work
53
+ task_done.should == true
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib/')
3
+ require 'breeder'
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ module Breeder
4
+ describe Worker do
5
+
6
+ let(:worker) { Worker.new }
7
+
8
+ describe '#stop?' do
9
+ context 'if the worker should stop' do
10
+ it 'returns true' do
11
+ worker.stop!
12
+ worker.stop?.should be_true
13
+ end
14
+ end
15
+ context 'if the worker should not stop' do
16
+ it 'returns false' do
17
+ worker.stop?.should be_false
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '#stop!' do
23
+ it 'makes #stop? return true' do
24
+ worker.stop?.should be_false
25
+ worker.stop!
26
+ worker.stop?.should be_true
27
+ end
28
+ end
29
+
30
+ describe '#do_work' do
31
+ context 'when the user has not overridden it' do
32
+ it 'raises an error' do
33
+ expect { worker.do_work }.to raise_error
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#run' do
39
+
40
+ class MyWorker < Worker
41
+ attr_reader :value
42
+ def initialize
43
+ @value = 0
44
+ end
45
+ def do_work
46
+ @value += 1
47
+ stop! if @value >= 3
48
+ end
49
+ end
50
+
51
+ it 'does work until told to stop' do
52
+ worker = MyWorker.new
53
+ worker.run
54
+ worker.value.should == 3
55
+ end
56
+ end
57
+
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: breeder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Kite
9
+ - Scott Reis
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-10-19 00:00:00.000000000Z
14
+ dependencies: []
15
+ description:
16
+ email:
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - README.md
21
+ files:
22
+ - VERSION
23
+ - LICENSE.txt
24
+ - CHANGELOG.rdoc
25
+ - README.md
26
+ - Rakefile
27
+ - lib/breeder.rb
28
+ - lib/breeder/worker.rb
29
+ - lib/breeder/core.rb
30
+ - lib/breeder/watcher.rb
31
+ - spec/worker_spec.rb
32
+ - spec/core_spec.rb
33
+ - spec/breeder_spec.rb
34
+ - spec/spec_helper.rb
35
+ homepage: http://www.github.com/chriskite/breeder
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.6
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Process spawning and reaping
59
+ test_files:
60
+ - spec/worker_spec.rb
61
+ - spec/core_spec.rb
62
+ - spec/breeder_spec.rb
63
+ - spec/spec_helper.rb