backburner 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.
@@ -0,0 +1,61 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ $backburner_sum = 0
4
+ $backburner_numbers = []
5
+
6
+ class TestBackburnerJob
7
+ include Backburner::Queue
8
+ queue "test.jobber"
9
+
10
+ def self.perform(value, number)
11
+ $backburner_sum += value
12
+ $backburner_numbers << number
13
+ end
14
+ end
15
+
16
+ describe "Backburner module" do
17
+ before { Backburner.default_queues.clear }
18
+
19
+ describe "for enqueue method" do
20
+ before do
21
+ Backburner.enqueue TestBackburnerJob, 5, 6
22
+ Backburner.enqueue TestBackburnerJob, 15, 10
23
+ silenced(2) do
24
+ worker = Backburner::Worker.new('test.jobber')
25
+ worker.prepare
26
+ 2.times { worker.work_one_job }
27
+ end
28
+ end
29
+
30
+ it "can run jobs using #run method" do
31
+ assert_equal 20, $backburner_sum
32
+ assert_same_elements [6, 10], $backburner_numbers
33
+ end
34
+ end # enqueue
35
+
36
+ describe "for work method" do
37
+ it "invokes worker start" do
38
+ Backburner::Worker.expects(:start).with(["foo", "bar"])
39
+ Backburner.work("foo", "bar")
40
+ end
41
+
42
+ it "invokes worker start with no args" do
43
+ Backburner::Worker.expects(:start).with([])
44
+ Backburner.work
45
+ end
46
+ end # work!
47
+
48
+ describe "for configuration" do
49
+ it "remembers the tube_namespace" do
50
+ assert_equal "demo.test", Backburner.configuration.tube_namespace
51
+ end
52
+ end # configuration
53
+
54
+ describe "for default_queues" do
55
+ it "supports assignment" do
56
+ Backburner.default_queues << "foo"
57
+ Backburner.default_queues << "bar"
58
+ assert_same_elements ["foo", "bar"], Backburner.default_queues
59
+ end
60
+ end
61
+ end # Backburner
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Connection class" do
4
+ describe "for initialize" do
5
+ before do
6
+ @connection = Backburner::Connection.new("beanstalk://localhost")
7
+ end
8
+
9
+ it "should store url in accessor" do
10
+ assert_equal "beanstalk://localhost", @connection.url
11
+ end
12
+
13
+ it "should setup beanstalk connection" do
14
+ assert_kind_of Beanstalk::Pool, @connection.beanstalk
15
+ end
16
+ end # initialize
17
+
18
+ describe "for bad uri" do
19
+ it "should raise a BadUrl" do
20
+ assert_raises(Backburner::Connection::BadURL) {
21
+ @connection = Backburner::Connection.new("fake://foo")
22
+ }
23
+ end
24
+ end
25
+
26
+ describe "for delegated methods" do
27
+ before do
28
+ @connection = Backburner::Connection.new("beanstalk://localhost")
29
+ end
30
+
31
+ it "delegate methods to beanstalk connection" do
32
+ assert_equal "localhost:11300", @connection.list_tubes.keys.first
33
+ end
34
+ end # delegator
35
+ end # Connection
@@ -0,0 +1,79 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Helpers module" do
4
+ include Backburner::Helpers
5
+
6
+ describe "for classify method" do
7
+ it "should support simple classify" do
8
+ assert_equal "FooBarBaz", classify("foo-bar-baz")
9
+ end
10
+
11
+ it "should not affect existing classified strings" do
12
+ assert_equal "Foo::BarBaz", classify("Foo::BarBaz")
13
+ end
14
+ end # classify
15
+
16
+ describe "for constantize method" do
17
+ it "should constantize known constant" do
18
+ assert_equal Backburner, constantize("Backburner")
19
+ end
20
+
21
+ it "should properly report when constant is undefined" do
22
+ assert_raises(NameError) { constantize("FakeObject") }
23
+ end
24
+ end # constantize
25
+
26
+ describe "for dasherize method" do
27
+ it "should not harm existing dashed names" do
28
+ assert_equal "foo/bar-baz", dasherize("foo/bar-baz")
29
+ end
30
+
31
+ it "should properly convert simple names to dashes" do
32
+ assert_equal "foo-bar", dasherize("FooBar")
33
+ end
34
+
35
+ it "should properly convert class to dash with namespace" do
36
+ assert_equal "foo/bar-baz", dasherize("Foo::BarBaz")
37
+ end
38
+ end # dasherize
39
+
40
+ describe "for exception_message method" do
41
+ it "prints out message about failure" do
42
+ output = exception_message(RuntimeError.new("test"))
43
+ assert_match /Exception RuntimeError/, output
44
+ end
45
+ end # exception_message
46
+
47
+ describe "for tube_namespace" do
48
+ before { Backburner.expects(:configuration).returns(stub(:tube_namespace => "test.foo.job")) }
49
+
50
+ it "accesses correct value" do
51
+ assert_equal "test.foo.job", tube_namespace
52
+ end
53
+ end # tube_namespace
54
+
55
+ describe "for expand_tube_name method" do
56
+ before { Backburner.expects(:configuration).returns(stub(:tube_namespace => "test.foo.job.")) }
57
+
58
+ it "supports base strings" do
59
+ assert_equal "test.foo.job.email/send-news", expand_tube_name("email/send_news")
60
+ end # simple string
61
+
62
+ it "supports qualified strings" do
63
+ assert_equal "test.foo.job.email/send-news", expand_tube_name("test.foo.job.email/send_news")
64
+ end # qualified string
65
+
66
+ it "supports base symbols" do
67
+ assert_equal "test.foo.job.email/send-news", expand_tube_name(:"email/send_news")
68
+ end # symbols
69
+
70
+ it "supports queue names" do
71
+ test = stub(:queue => "email/send_news")
72
+ assert_equal "test.foo.job.email/send-news", expand_tube_name(test)
73
+ end # queue names
74
+
75
+ it "supports class names" do
76
+ assert_equal "test.foo.job.runtime-error", expand_tube_name(RuntimeError)
77
+ end # class names
78
+ end # expand_tube_name
79
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Logger module" do
4
+ include Backburner::Logger
5
+
6
+ describe "for log method" do
7
+ it "prints out to std out" do
8
+ output = capture_stdout { log("foo") }
9
+ assert_equal "foo\n", output
10
+ end
11
+ end # log
12
+
13
+ describe "for log_error method" do
14
+ it "prints out to std err" do
15
+ output = capture_stdout { log_error("bar") }
16
+ assert_equal "bar\n", output
17
+ end
18
+ end # log_error
19
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class TestObj
4
+ include Backburner::Performable
5
+ ID = 56
6
+ def id; ID; end
7
+ def self.find(id); TestObj.new if id == ID; end
8
+ def foo(state, state2); "bar #{state} #{state2}"; end
9
+ def self.bar(state, state2); "baz #{state} #{state2}"; end
10
+ end
11
+
12
+ describe "Backburner::Performable module" do
13
+ after { ENV["TEST"] = nil }
14
+
15
+ describe "for async instance method" do
16
+ it "should invoke worker enqueue" do
17
+ Backburner::Worker.expects(:enqueue).with(TestObj, [56, :foo, true, false], has_entries(:pri => 5000, :queue => "foo"))
18
+ TestObj.new.async(:pri => 5000, :queue => "foo").foo(true, false)
19
+ end
20
+ end # async instance
21
+
22
+ describe "for async class method" do
23
+ it "should invoke worker enqueue" do
24
+ Backburner::Worker.expects(:enqueue).with(TestObj, [nil, :bar, true, false], has_entries(:pri => 5000, :queue => "foo"))
25
+ TestObj.async(:pri => 5000, :queue => "foo").bar(true, false)
26
+ end
27
+ end # async class
28
+
29
+ describe "for perform class method" do
30
+ it "should work for instance" do
31
+ assert_equal "bar true false", TestObj.perform(TestObj::ID, :foo, true, false)
32
+ end # instance
33
+
34
+ it "should work for class level" do
35
+ assert_equal "baz false true", TestObj.perform(nil, :bar, false, true)
36
+ end # class
37
+ end # perform
38
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module NestedDemo
4
+ class TestJobA; include Backburner::Queue; end
5
+ class TestJobB; include Backburner::Queue; end
6
+ end
7
+
8
+ describe "Backburner::Queue module" do
9
+ describe "contains known_queue_classes" do
10
+ it "has all defined known queues" do
11
+ assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobA
12
+ assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobB
13
+ end
14
+ end
15
+
16
+ describe "for queue method accessor" do
17
+ it "should return the queue name" do
18
+ assert_equal "nested-demo/test-job-a", NestedDemo::TestJobA.queue
19
+ end
20
+ end # queue_name
21
+
22
+ describe "for queue assignment method" do
23
+ it "should allow queue name to be assigned" do
24
+ NestedDemo::TestJobB.queue("nested/job")
25
+ assert_equal "nested/job", NestedDemo::TestJobB.queue
26
+ end
27
+ end # queue
28
+ end # Backburner::Queue
@@ -0,0 +1,93 @@
1
+ require 'rubygems'
2
+ require 'tempfile'
3
+ require 'minitest/autorun'
4
+ require 'mocha'
5
+ $:.unshift File.expand_path("../../lib")
6
+ require 'backburner'
7
+
8
+ # Configure Backburner
9
+ Backburner.configure do |config|
10
+ config.beanstalk_url = "beanstalk://localhost"
11
+ config.tube_namespace = "demo.test"
12
+ end
13
+
14
+ ## Kernel Extensions
15
+ require 'stringio'
16
+
17
+ module Kernel
18
+ # Redirect standard out, standard error and the buffered logger for sprinkle to StringIO
19
+ # capture_stdout { any_commands; you_want } => "all output from the commands"
20
+ def capture_stdout
21
+ return yield if ENV['DEBUG'] # Skip if debug mode
22
+
23
+ out = StringIO.new
24
+ $stdout = out
25
+ $stderr = out
26
+ yield
27
+ return out.string
28
+ ensure
29
+ $stdout = STDOUT
30
+ $stderr = STDERR
31
+ end
32
+ end
33
+
34
+ class User
35
+ attr_accessor :id, :name
36
+
37
+ def initialize(id, name)
38
+ @id, @name = id, name
39
+ end
40
+ end
41
+
42
+ class MiniTest::Spec
43
+ class << self
44
+ alias :should :it
45
+ alias :context :describe
46
+ end
47
+ alias :assert_no_match :refute_match
48
+ alias :assert_not_nil :refute_nil
49
+ alias :assert_not_equal :refute_equal
50
+
51
+ # assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
52
+ def assert_same_elements(a1, a2, msg = nil)
53
+ [:select, :inject, :size].each do |m|
54
+ [a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
55
+ end
56
+
57
+ assert a1h = a1.inject({}) { |h,e| h[e] ||= a1.select { |i| i == e }.size; h }
58
+ assert a2h = a2.inject({}) { |h,e| h[e] ||= a2.select { |i| i == e }.size; h }
59
+
60
+ assert_equal(a1h, a2h, msg)
61
+ end
62
+
63
+ # assert_contains(['a', '1'], /\d/) => passes
64
+ # assert_contains(['a', '1'], 'a') => passes
65
+ # assert_contains(['a', '1'], /not there/) => fails
66
+ def assert_contains(collection, x, extra_msg = "")
67
+ collection = [collection] unless collection.is_a?(Array)
68
+ msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
69
+ case x
70
+ when Regexp
71
+ assert(collection.detect { |e| e =~ x }, msg)
72
+ else
73
+ assert(collection.include?(x), msg)
74
+ end
75
+ end
76
+
77
+ # silenced(5) { ... }
78
+ def silenced(time=3, &block)
79
+ Timeout::timeout(time) { capture_stdout(&block) }
80
+ end
81
+
82
+ # pop_one_job(tube_name)
83
+ def pop_one_job(tube_name)
84
+ connection = Backburner::Worker.connection
85
+ tube_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
86
+ connection.watch(tube_name)
87
+ connection.list_tubes_watched.each do |server, tubes|
88
+ tubes.each { |tube| connection.ignore(tube) unless tube == tube_name }
89
+ end
90
+ silenced(3) { @res = connection.reserve }
91
+ return @res, JSON.parse(@res.body)
92
+ end
93
+ end # MiniTest::Spec
@@ -0,0 +1,163 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ $worker_test_count = 0
4
+
5
+ class TestJob
6
+ include Backburner::Queue
7
+ def self.perform(x, y); $worker_test_count += x + y; end
8
+ end
9
+
10
+ class TestAsyncJob
11
+ include Backburner::Performable
12
+ def self.foo(x, y); $worker_test_count = x * y; end
13
+ end
14
+
15
+ describe "Backburner::Worker module" do
16
+ before { Backburner.default_queues.clear }
17
+
18
+ describe "for enqueue class method" do
19
+ it "should support enqueuing job" do
20
+ Backburner::Worker.enqueue TestJob, [3, 4], :ttr => 100
21
+ job, body = pop_one_job("test-job")
22
+ assert_equal "TestJob", body["class"]
23
+ assert_equal [3, 4], body["args"]
24
+ assert_equal 100, job.ttr
25
+ assert_equal Backburner.configuration.default_priority, job.pri
26
+ end # simple
27
+
28
+ it "should support enqueuing job with custom queue" do
29
+ Backburner::Worker.enqueue TestJob, [6, 7], :queue => "test.bar", :pri => 5000
30
+ job, body = pop_one_job("test.bar")
31
+ assert_equal "TestJob", body["class"]
32
+ assert_equal [6, 7], body["args"]
33
+ assert_equal 0, job.delay
34
+ assert_equal 5000, job.pri
35
+ assert_equal Backburner.configuration.respond_timeout, job.ttr
36
+ end # custom
37
+
38
+ it "should support async job" do
39
+ TestAsyncJob.async(:ttr => 100, :queue => "bar.baz.foo").foo(10, 5)
40
+ job, body = pop_one_job("bar.baz.foo")
41
+ assert_equal "TestAsyncJob", body["class"]
42
+ assert_equal [nil, "foo", 10, 5], body["args"]
43
+ assert_equal 100, job.ttr
44
+ assert_equal Backburner.configuration.default_priority, job.pri
45
+ end # async
46
+ end # enqueue
47
+
48
+ describe "for start class method" do
49
+ it "should initialize and start the worker instance" do
50
+ ech = stub
51
+ Backburner::Worker.expects(:new).with("foo").returns(ech)
52
+ ech.expects(:start)
53
+ Backburner::Worker.start("foo")
54
+ end
55
+ end # start
56
+
57
+ describe "for connection class method" do
58
+ it "should return the beanstalk connection" do
59
+ assert_equal "beanstalk://localhost", Backburner::Worker.connection.url
60
+ assert_kind_of Beanstalk::Pool, Backburner::Worker.connection.beanstalk
61
+ end
62
+ end # connection
63
+
64
+ describe "for tube_names accessor" do
65
+ it "supports retrieving tubes" do
66
+ worker = Backburner::Worker.new(["foo", "bar"])
67
+ assert_equal ["foo", "bar"], worker.tube_names
68
+ end
69
+
70
+ it "supports single tube array arg" do
71
+ worker = Backburner::Worker.new([["foo", "bar"]])
72
+ assert_equal ["foo", "bar"], worker.tube_names
73
+ end
74
+
75
+ it "supports empty nil array arg" do
76
+ worker = Backburner::Worker.new([nil])
77
+ assert_equal nil, worker.tube_names
78
+ end
79
+
80
+ it "supports single tube arg" do
81
+ worker = Backburner::Worker.new("foo")
82
+ assert_equal ["foo"], worker.tube_names
83
+ end
84
+
85
+ it "supports empty array arg" do
86
+ worker = Backburner::Worker.new([])
87
+ assert_equal nil, worker.tube_names
88
+ end
89
+
90
+ it "supports nil arg" do
91
+ worker = Backburner::Worker.new(nil)
92
+ assert_equal nil, worker.tube_names
93
+ end
94
+ end # tube_names
95
+
96
+ describe "for prepare method" do
97
+ it "should watch specified tubes" do
98
+ worker = Backburner::Worker.new(["foo", "bar"])
99
+ out = capture_stdout { worker.prepare }
100
+ assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
101
+ assert_same_elements ["demo.test.foo", "demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
102
+ assert_match /demo\.test\.foo/, out
103
+ end # multiple
104
+
105
+ it "should watch single tube" do
106
+ worker = Backburner::Worker.new("foo")
107
+ out = capture_stdout { worker.prepare }
108
+ assert_equal ["demo.test.foo"], worker.tube_names
109
+ assert_same_elements ["demo.test.foo"], Backburner::Worker.connection.list_tubes_watched.values.first
110
+ assert_match /demo\.test\.foo/, out
111
+ end # single
112
+
113
+ it "should respect default_queues settings" do
114
+ Backburner.default_queues.concat(["foo", "bar"])
115
+ worker = Backburner::Worker.new
116
+ out = capture_stdout { worker.prepare }
117
+ assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
118
+ assert_same_elements ["demo.test.foo", "demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
119
+ assert_match /demo\.test\.foo/, out
120
+ end
121
+
122
+ it "should assign based on all tubes" do
123
+ Backburner::Worker.any_instance.expects(:all_existing_queues).once.returns("bar")
124
+ worker = Backburner::Worker.new
125
+ out = capture_stdout { worker.prepare }
126
+ assert_equal ["demo.test.bar"], worker.tube_names
127
+ assert_same_elements ["demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
128
+ assert_match /demo\.test\.bar/, out
129
+ end # all assign
130
+
131
+ it "should properly retrieve all tubes" do
132
+ worker = Backburner::Worker.new
133
+ out = capture_stdout { worker.prepare }
134
+ assert_contains worker.tube_names, "demo.test.test-job"
135
+ assert_contains Backburner::Worker.connection.list_tubes_watched.values.first, "demo.test.test-job"
136
+ assert_match /demo\.test\.test-job/, out
137
+ end # all read
138
+ end # prepare
139
+
140
+ describe "for work_one_job method" do
141
+ it "should work an enqueued job" do
142
+ $worker_test_count = 0
143
+ Backburner::Worker.enqueue TestJob, [1, 2], :queue => "foo.bar"
144
+ silenced(2) do
145
+ worker = Backburner::Worker.new('foo.bar')
146
+ worker.prepare
147
+ worker.work_one_job
148
+ end
149
+ assert_equal 3, $worker_test_count
150
+ end
151
+
152
+ it "should work for an async job" do
153
+ $worker_test_count = 0
154
+ TestAsyncJob.async(:queue => "bar.baz").foo(3, 5)
155
+ silenced(2) do
156
+ worker = Backburner::Worker.new('bar.baz')
157
+ worker.prepare
158
+ worker.work_one_job
159
+ end
160
+ assert_equal 15, $worker_test_count
161
+ end
162
+ end # work_one_job
163
+ end # Backburner::Worker