breeder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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