woodhouse 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.travis.yml +5 -0
- data/Gemfile +7 -0
- data/Guardfile +4 -0
- data/MIT-LICENSE +21 -0
- data/PROGRESS-NOTES.txt +5 -0
- data/README.markdown +152 -0
- data/Rakefile +35 -0
- data/THOUGHTS +84 -0
- data/doc/example/script-woodhouse +9 -0
- data/doc/example/woodhouse-initializer.rb +12 -0
- data/lib/generators/woodhouse_generator.rb +38 -0
- data/lib/woodhouse/dispatcher.rb +37 -0
- data/lib/woodhouse/dispatchers/bunny_dispatcher.rb +48 -0
- data/lib/woodhouse/dispatchers/common_amqp_dispatcher.rb +28 -0
- data/lib/woodhouse/dispatchers/hot_bunnies_dispatcher.rb +48 -0
- data/lib/woodhouse/dispatchers/local_dispatcher.rb +13 -0
- data/lib/woodhouse/dispatchers/local_pool_dispatcher.rb +25 -0
- data/lib/woodhouse/dispatchers.rb +19 -0
- data/lib/woodhouse/extension.rb +24 -0
- data/lib/woodhouse/extensions/new_relic/instrumentation_middleware.rb +10 -0
- data/lib/woodhouse/extensions/new_relic.rb +23 -0
- data/lib/woodhouse/extensions/progress.rb +165 -0
- data/lib/woodhouse/job.rb +76 -0
- data/lib/woodhouse/job_execution.rb +60 -0
- data/lib/woodhouse/layout.rb +290 -0
- data/lib/woodhouse/layout_builder.rb +55 -0
- data/lib/woodhouse/layout_serializer.rb +82 -0
- data/lib/woodhouse/middleware/airbrake_exceptions.rb +12 -0
- data/lib/woodhouse/middleware/assign_logger.rb +10 -0
- data/lib/woodhouse/middleware/log_dispatch.rb +21 -0
- data/lib/woodhouse/middleware/log_jobs.rb +22 -0
- data/lib/woodhouse/middleware.rb +16 -0
- data/lib/woodhouse/middleware_stack.rb +35 -0
- data/lib/woodhouse/mixin_registry.rb +27 -0
- data/lib/woodhouse/node_configuration.rb +80 -0
- data/lib/woodhouse/process.rb +41 -0
- data/lib/woodhouse/queue_criteria.rb +52 -0
- data/lib/woodhouse/rails.rb +46 -0
- data/lib/woodhouse/rails2.rb +21 -0
- data/lib/woodhouse/registry.rb +12 -0
- data/lib/woodhouse/runner.rb +60 -0
- data/lib/woodhouse/runners/bunny_runner.rb +60 -0
- data/lib/woodhouse/runners/dummy_runner.rb +11 -0
- data/lib/woodhouse/runners/hot_bunnies_runner.rb +79 -0
- data/lib/woodhouse/runners.rb +16 -0
- data/lib/woodhouse/scheduler.rb +113 -0
- data/lib/woodhouse/server.rb +80 -0
- data/lib/woodhouse/trigger_set.rb +19 -0
- data/lib/woodhouse/version.rb +3 -0
- data/lib/woodhouse/worker.rb +86 -0
- data/lib/woodhouse.rb +99 -0
- data/spec/integration/bunny_worker_process_spec.rb +32 -0
- data/spec/layout_builder_spec.rb +55 -0
- data/spec/layout_spec.rb +143 -0
- data/spec/middleware_stack_spec.rb +56 -0
- data/spec/mixin_registry_spec.rb +15 -0
- data/spec/node_configuration_spec.rb +22 -0
- data/spec/progress_spec.rb +40 -0
- data/spec/queue_criteria_spec.rb +11 -0
- data/spec/scheduler_spec.rb +41 -0
- data/spec/server_spec.rb +72 -0
- data/spec/shared_contexts.rb +70 -0
- data/spec/worker_spec.rb +28 -0
- data/woodhouse.gemspec +37 -0
- metadata +285 -0
data/spec/layout_spec.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::Layout do
|
5
|
+
|
6
|
+
context "#add_node" do
|
7
|
+
|
8
|
+
it "should only accept Woodhouse::Node objects"
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
context "#frozen_clone" do
|
13
|
+
|
14
|
+
it "should return a frozen copy where all sub-objects are also frozen copies"
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
context "#changes_from" do
|
19
|
+
|
20
|
+
it "should return a Woodhouse::Layout::Changes object where this layout is the new one"
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Woodhouse::Layout::Node do
|
27
|
+
it_should_behave_like "common"
|
28
|
+
|
29
|
+
context "#add_node" do
|
30
|
+
|
31
|
+
it "should take a string or a symbol and create a node with that name" do
|
32
|
+
empty_layout.add_node :orz
|
33
|
+
empty_layout.add_node 'vux'
|
34
|
+
empty_layout.add_node Woodhouse::Layout::Node.new(:androsynth)
|
35
|
+
empty_layout.node(:orz).should be_kind_of(Woodhouse::Layout::Node)
|
36
|
+
empty_layout.node(:vux).should be_kind_of(Woodhouse::Layout::Node)
|
37
|
+
empty_layout.node(:androsynth).should be_kind_of(Woodhouse::Layout::Node)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
context "#default_configuration!" do
|
43
|
+
|
44
|
+
it "should configure one worker thread for every job available" do
|
45
|
+
layout = empty_layout
|
46
|
+
config = common_config
|
47
|
+
config.registry = {
|
48
|
+
:FooBarWorker => FakeWorker,
|
49
|
+
:BarBazWorker => FakeWorker,
|
50
|
+
:BazBatWorker => FakeWorker
|
51
|
+
}
|
52
|
+
layout.add_node Woodhouse::Layout::Node.new(:default)
|
53
|
+
layout.node(:default).default_configuration! config
|
54
|
+
layout.node(:default).workers.should have(6).workers
|
55
|
+
# FooBar#foo, FooBar#bar, BarBaz#foo...
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should pay attention to the config's default_threads" do
|
59
|
+
layout = empty_layout
|
60
|
+
config = common_config
|
61
|
+
config.default_threads = 10
|
62
|
+
config.registry = {
|
63
|
+
:OrzWorker => FakeWorker
|
64
|
+
}
|
65
|
+
layout.add_node :default
|
66
|
+
layout.node(:default).default_configuration! config
|
67
|
+
layout.node(:default).workers.should have(2).workers
|
68
|
+
layout.node(:default).workers.first.threads.should == 10
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe Woodhouse::Layout::Worker do
|
76
|
+
|
77
|
+
it "should default to 1 thread"
|
78
|
+
|
79
|
+
it "should default to a wide-open criteria"
|
80
|
+
|
81
|
+
it "should automatically convert the :only key to a Woodhouse::QueueCriteria"
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe Woodhouse::Layout::Changes do
|
86
|
+
it_should_behave_like "common"
|
87
|
+
|
88
|
+
context "when the new layout is empty" do
|
89
|
+
|
90
|
+
subject { Woodhouse::Layout::Changes.new(empty_layout, populated_layout, :default) }
|
91
|
+
|
92
|
+
it "should drop all workers and add none" do
|
93
|
+
subject.adds.should be_empty
|
94
|
+
subject.drops.should have(3).dropped_workers
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when the old layout is empty" do
|
100
|
+
|
101
|
+
subject { Woodhouse::Layout::Changes.new(populated_layout, empty_layout, :default) }
|
102
|
+
|
103
|
+
it "should add all workers and drop none" do
|
104
|
+
subject.drops.should be_empty
|
105
|
+
subject.adds.should have(3).added_workers
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when the new layout is nil" do
|
111
|
+
|
112
|
+
subject { Woodhouse::Layout::Changes.new(nil, populated_layout, :default) }
|
113
|
+
|
114
|
+
it "should drop all workers and add none" do
|
115
|
+
subject.adds.should be_empty
|
116
|
+
subject.drops.should have(3).dropped_workers
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when the old layout is nil" do
|
122
|
+
|
123
|
+
subject { Woodhouse::Layout::Changes.new(populated_layout, nil, :default) }
|
124
|
+
|
125
|
+
it "should add all workers and drop none" do
|
126
|
+
subject.drops.should be_empty
|
127
|
+
subject.adds.should have(3).added_workers
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when both layouts are specified and they overlap" do
|
133
|
+
|
134
|
+
subject { Woodhouse::Layout::Changes.new(overlapping_layout, populated_layout, :default) }
|
135
|
+
|
136
|
+
it "should add some workers, drop some, and leave some alone" do
|
137
|
+
subject.drops.should have(1).dropped_worker
|
138
|
+
subject.adds.should have(1).added_worker
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::MiddlewareStack do
|
5
|
+
it_should_behave_like "common"
|
6
|
+
|
7
|
+
subject { Woodhouse::MiddlewareStack.new(common_config) }
|
8
|
+
let(:dummy) { MiddlewareDummy.new }
|
9
|
+
|
10
|
+
class MiddlewareDummy
|
11
|
+
attr_reader :was_called, :sent_item
|
12
|
+
def initialize
|
13
|
+
@was_called = false
|
14
|
+
@sent_item = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(job)
|
18
|
+
@was_called = true
|
19
|
+
@sent_item = job
|
20
|
+
yield job
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should work if empty" do
|
26
|
+
called = :not_called
|
27
|
+
subject.call("LANAAAA!") {|object|
|
28
|
+
object.should == "LANAAAA!"
|
29
|
+
called = :called
|
30
|
+
}
|
31
|
+
called.should == :called
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should send #call to stack items which respond to that" do
|
35
|
+
subject << dummy
|
36
|
+
subject.call("is it not?") {|object| }
|
37
|
+
dummy.was_called.should be_true
|
38
|
+
dummy.sent_item.should == "is it not?"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should send #new to stack items which respond to that" do
|
42
|
+
fake_class = stub('mware item', :new => dummy)
|
43
|
+
subject << fake_class
|
44
|
+
subject.call("danger zone") {|object| }
|
45
|
+
dummy.was_called.should be_true
|
46
|
+
dummy.sent_item.should == "danger zone"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should complain with ArgumentError if entries respond to neither #call nor #new" do
|
50
|
+
subject << nil
|
51
|
+
expect do
|
52
|
+
subject.call("danger zone") {|object| }
|
53
|
+
end.to raise_error(ArgumentError)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::MixinRegistry do
|
5
|
+
|
6
|
+
subject { Woodhouse::MixinRegistry.new }
|
7
|
+
|
8
|
+
it "should include all classes that include Woodhouse::Worker" do
|
9
|
+
::SomeFakeNewClass = Class.new
|
10
|
+
SomeFakeNewClass.send(:include, Woodhouse::Worker)
|
11
|
+
subject[:SomeFakeNewClass].should be SomeFakeNewClass
|
12
|
+
Object.send :remove_const, :SomeFakeNewClass
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::NodeConfiguration do
|
5
|
+
it_should_behave_like "common"
|
6
|
+
|
7
|
+
subject { Woodhouse::NodeConfiguration.new }
|
8
|
+
|
9
|
+
describe "server_info" do
|
10
|
+
|
11
|
+
it "should default to an empty hash" do
|
12
|
+
subject.server_info.should == {}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should convert keys into symbols" do
|
16
|
+
subject.server_info = { "lana" => "LANAAAA" }
|
17
|
+
subject.server_info.should have_key(:lana)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'woodhouse/extensions/progress'
|
2
|
+
|
3
|
+
describe Woodhouse::Progress do
|
4
|
+
|
5
|
+
describe "JobWithProgress" do
|
6
|
+
subject { Object.new.tap do |obj| obj.extend Woodhouse::Progress::JobWithProgress end }
|
7
|
+
|
8
|
+
it "should provide a method for creating a StatusTicker" do
|
9
|
+
subject.status_ticker("orz").should be_kind_of(Woodhouse::Progress::StatusTicker)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "StatusTicker" do
|
15
|
+
let(:sink) { double("progress sink") }
|
16
|
+
let(:job) {
|
17
|
+
Object.new.tap do |obj|
|
18
|
+
obj.extend Woodhouse::Progress::JobWithProgress
|
19
|
+
obj.progress_sink = sink
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
it "should take initial status and tick arguments" do
|
24
|
+
ticker = job.status_ticker("orz", :top => 100, :start => 10, :status => "working")
|
25
|
+
ticker.to_hash.should == { "orz" => { "top" => 100, "current" => 10, "status" => "working" } }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "#tick" do
|
29
|
+
|
30
|
+
it "should send progress updates" do
|
31
|
+
ticker = job.status_ticker("orz")
|
32
|
+
sink.should_receive(:update_job).with(job, { "orz" => { "status" => "funky", "current" => 1 } })
|
33
|
+
ticker.tick(:status => "funky").value
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::QueueCriteria do
|
5
|
+
it_should_behave_like "common"
|
6
|
+
|
7
|
+
it "should stringify keys and values" do
|
8
|
+
criteria = Woodhouse::QueueCriteria.new("abc" => :def, :fed => 1)
|
9
|
+
criteria.criteria.should == { "abc" => "def", "fed" => "1" }
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::Scheduler do
|
5
|
+
it_should_behave_like "common"
|
6
|
+
|
7
|
+
subject { Woodhouse::Scheduler.new(common_config) }
|
8
|
+
|
9
|
+
let(:worker) {
|
10
|
+
Woodhouse::Layout::Worker.new(:FooBarWorker, :foo)
|
11
|
+
}
|
12
|
+
|
13
|
+
let(:worker_2) {
|
14
|
+
Woodhouse::Layout::Worker.new(:FooBarWorker, :foo, :only => { :job => "big" })
|
15
|
+
}
|
16
|
+
|
17
|
+
it "should create a new worker set when a new worker is sent to #start_worker" do
|
18
|
+
subject.start_worker worker
|
19
|
+
subject.should be_running_worker(worker)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not create a new worker set when an existing worker is sent to #start_worker" do
|
23
|
+
subject.start_worker(worker).should be_true
|
24
|
+
subject.start_worker(worker).should be_false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should spin down and remove a worker set when a worker is sent to #stop_worker" do
|
28
|
+
subject.start_worker worker
|
29
|
+
subject.stop_worker worker, true
|
30
|
+
subject.should_not be_running_worker(worker)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should spin down and remove all worker sets when #spin_down is called" do
|
34
|
+
subject.start_worker worker
|
35
|
+
subject.start_worker worker_2
|
36
|
+
subject.spin_down
|
37
|
+
subject.should_not be_running_worker(worker)
|
38
|
+
subject.should_not be_running_worker(worker_2)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/server_spec.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::Server do
|
5
|
+
it_should_behave_like "common"
|
6
|
+
|
7
|
+
subject { Woodhouse::Server.new }
|
8
|
+
|
9
|
+
it "should default to the :default node" do
|
10
|
+
subject.node.should == :default
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should expect the value to #layout= to be nil or a Layout" do
|
14
|
+
subject.layout = Woodhouse::Layout.new
|
15
|
+
subject.layout.should be_kind_of Woodhouse::Layout
|
16
|
+
subject.layout = nil
|
17
|
+
subject.layout.should be_nil
|
18
|
+
if false # this craps out on JRuby
|
19
|
+
begin
|
20
|
+
oldlogger = Celluloid.logger
|
21
|
+
Celluloid.logger = nil # It's going to crash
|
22
|
+
expect do
|
23
|
+
subject.layout = "foo"
|
24
|
+
end.to raise_error
|
25
|
+
ensure
|
26
|
+
Celluloid.logger = oldlogger
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should take a frozen clone of the layout" do
|
32
|
+
layout = Woodhouse::Layout.new
|
33
|
+
subject.layout = layout
|
34
|
+
subject.layout.should_not be layout
|
35
|
+
subject.layout.should be_frozen
|
36
|
+
end
|
37
|
+
|
38
|
+
context "#start" do
|
39
|
+
|
40
|
+
it "should return false if a layout is not configured" do
|
41
|
+
subject.start.should be_false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return false if the set node doesn't exist in the layout" do
|
45
|
+
subject.layout = populated_layout
|
46
|
+
subject.node = :foo_bar_baz
|
47
|
+
subject.start.should be_false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return true and spin up workers if the node is valid" do
|
51
|
+
subject.layout = populated_layout
|
52
|
+
subject.start.should be_true
|
53
|
+
# TODO: test for workers starting up
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context "#reload" do
|
59
|
+
|
60
|
+
it "should shut down the server if a layout is not configured"
|
61
|
+
|
62
|
+
it "should shut down the server if the set node doesn't exist in the layout"
|
63
|
+
|
64
|
+
it "should shut down the server if the set node has no workers"
|
65
|
+
|
66
|
+
it "should spin up new workers if they have been added to the node"
|
67
|
+
|
68
|
+
it "should spin down workers if they have been removed from the node"
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#Celluloid.logger = nil
|
2
|
+
|
3
|
+
class FakeWorker
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :last_worker
|
7
|
+
attr_accessor :jobs
|
8
|
+
end
|
9
|
+
|
10
|
+
self.jobs ||= []
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
FakeWorker.last_worker = self
|
14
|
+
FakeWorker.jobs ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def foo(args)
|
18
|
+
FakeWorker.jobs << args
|
19
|
+
end
|
20
|
+
|
21
|
+
def bar(args)
|
22
|
+
FakeWorker.jobs << args
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
Woodhouse.configure do |config|
|
28
|
+
config.registry = { :FooBarWorker => FakeWorker }
|
29
|
+
config.runner_type = :dummy
|
30
|
+
config.dispatcher_type = :local
|
31
|
+
config.logger = Logger.new("/dev/null")
|
32
|
+
end
|
33
|
+
|
34
|
+
shared_examples_for "common" do
|
35
|
+
|
36
|
+
let(:empty_layout) {
|
37
|
+
Woodhouse::Layout.new
|
38
|
+
}
|
39
|
+
|
40
|
+
let(:populated_layout) {
|
41
|
+
Woodhouse::Layout.new.tap do |layout|
|
42
|
+
layout.add_node Woodhouse::Layout::Node.new(:default)
|
43
|
+
layout.node(:default).tap do |default|
|
44
|
+
default.add_worker Woodhouse::Layout::Worker.new(:FooWorker, :foo)
|
45
|
+
default.add_worker Woodhouse::Layout::Worker.new(:FooWorker, :foo, :only => { :size => "huge" })
|
46
|
+
default.add_worker Woodhouse::Layout::Worker.new(:FooWorker, :bar, :threads => 3)
|
47
|
+
end
|
48
|
+
layout.add_node Woodhouse::Layout::Node.new(:other)
|
49
|
+
layout.node(:other).tap do |default|
|
50
|
+
default.add_worker Woodhouse::Layout::Worker.new(:OtherWorker, :bat)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
}
|
54
|
+
|
55
|
+
let(:overlapping_layout) {
|
56
|
+
Woodhouse::Layout.new.tap do |layout|
|
57
|
+
layout.add_node Woodhouse::Layout::Node.new(:default)
|
58
|
+
layout.node(:default).tap do |default|
|
59
|
+
default.add_worker Woodhouse::Layout::Worker.new(:FooWorker, :foo)
|
60
|
+
default.add_worker Woodhouse::Layout::Worker.new(:FooWorker, :bar, :threads => 3)
|
61
|
+
default.add_worker Woodhouse::Layout::Worker.new(:BarWorker, :baz)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
let!(:common_config) {
|
67
|
+
Woodhouse.global_configuration
|
68
|
+
}
|
69
|
+
|
70
|
+
end
|
data/spec/worker_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'woodhouse'
|
2
|
+
require File.dirname(File.expand_path(__FILE__)) + '/shared_contexts'
|
3
|
+
|
4
|
+
describe Woodhouse::Worker do
|
5
|
+
|
6
|
+
subject {
|
7
|
+
Class.new do
|
8
|
+
include Woodhouse::Worker
|
9
|
+
def fake_job(*); end
|
10
|
+
end
|
11
|
+
}
|
12
|
+
|
13
|
+
it "should provide class-level async_ convenience methods" do
|
14
|
+
lambda do
|
15
|
+
subject.async_fake_job
|
16
|
+
end.should_not raise_error(NoMethodError)
|
17
|
+
lambda do
|
18
|
+
subject.async_something_else
|
19
|
+
end.should raise_error(NoMethodError)
|
20
|
+
lambda do
|
21
|
+
subject.blah_blah_blah
|
22
|
+
end.should raise_error(NoMethodError)
|
23
|
+
lambda do
|
24
|
+
subject.async_method # Don't want inherited methods to work
|
25
|
+
end.should raise_error(NoMethodError)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/woodhouse.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "woodhouse/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "woodhouse"
|
7
|
+
s.version = Woodhouse::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Matthew Boeh"]
|
10
|
+
s.email = ["matt@crowdcompass.com", "matthew.boeh@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/mboeh/woodhouse"
|
12
|
+
s.summary = %q{An AMQP-based background worker system for Ruby 1.8 and 1.9}
|
13
|
+
s.description = %q{An AMQP-based background worker system for Ruby 1.8 and 1.9 designed to make managing heterogenous tasks relatively easy.
|
14
|
+
|
15
|
+
The use case for Woodhouse is for reliable and sane performance in situations where jobs on a single queue may vary significantly in length. The goal is to permit large numbers of quick jobs to be serviced even when many slow jobs are in the queue. A secondary goal is to provide a sane way for jobs on a given queue to be given special priority or dispatched to a server more suited to them.
|
16
|
+
|
17
|
+
Clients (i.e., your application) may be using either Ruby 1.8 or 1.9 in any VM. Worker processes currently only support JRuby in 1.8 or 1.9 mode efficiently. MRI 1.9 and Rubinius support is planned.}
|
18
|
+
|
19
|
+
s.rubyforge_project = "woodhouse"
|
20
|
+
|
21
|
+
s.add_dependency 'fiber18', '>= 1.0.1'
|
22
|
+
s.add_dependency 'celluloid'
|
23
|
+
s.add_dependency 'bunny', "~> 0.9.0.pre4"
|
24
|
+
s.add_dependency 'connection_pool'
|
25
|
+
s.add_dependency 'json'
|
26
|
+
|
27
|
+
s.add_development_dependency 'rspec', '~> 1.3.1'
|
28
|
+
s.add_development_dependency 'rake'
|
29
|
+
s.add_development_dependency 'guard'
|
30
|
+
s.add_development_dependency 'guard-rspec'
|
31
|
+
s.add_development_dependency 'mocha'
|
32
|
+
|
33
|
+
s.files = `git ls-files`.split("\n")
|
34
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
35
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
end
|