qu 0.1.4 → 0.2.0

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 CHANGED
@@ -1,3 +1,24 @@
1
+ 0.2.0 - 2012-06-13
2
+
3
+ Backwards-incompatible Changes:
4
+
5
+ * Remove #requeue from all backends. It was not used internally.
6
+ * Move implicit Rails dependency to it's own Gem, which you must declare now in your Gemfile.
7
+
8
+ gem 'qu-rails'
9
+
10
+ Enhancements
11
+
12
+ * qu-mongo: Add mongolab environment variable for automatic configuration on Heroku.
13
+
14
+ Bug Fixes:
15
+
16
+ * Fixing Immediate backend to satisfy the backend interface
17
+
18
+
19
+ https://github.com/bkeepers/qu/compare/v0.1.4...v0.2.0
20
+
21
+
1
22
  0.1.4 - 2012-01-07
2
23
 
3
24
  Enhancements:
@@ -10,6 +31,7 @@
10
31
 
11
32
  https://github.com/bkeepers/qu/compare/v0.1.3...v0.1.4
12
33
 
34
+
13
35
  0.1.3 - 2011-10-10
14
36
 
15
37
  Bug Fixes:
@@ -28,6 +50,7 @@
28
50
 
29
51
  https://github.com/bkeepers/qu/compare/v0.1.2..v0.1.3
30
52
 
53
+
31
54
  0.1.2 - 2011-10-05
32
55
 
33
56
  Bug Fixes:
@@ -36,6 +59,7 @@
36
59
 
37
60
  https://github.com/bkeepers/qu/compare/v0.1.1...v0.1.2
38
61
 
62
+
39
63
  0.1.1 - 2011-10-02
40
64
 
41
65
  Bug Fixes:
data/Gemfile CHANGED
@@ -3,18 +3,15 @@ gemspec :name => 'qu'
3
3
 
4
4
  Dir['qu-*.gemspec'].each do |gemspec|
5
5
  plugin = gemspec.scan(/qu-(.*)\.gemspec/).flatten.first
6
-
7
- group plugin do
8
- gemspec(:name => "qu-#{plugin}", :development_group => plugin)
9
- end
6
+ gemspec(:name => "qu-#{plugin}", :development_group => plugin)
10
7
  end
11
8
 
12
9
  group :test do
13
10
  gem 'SystemTimer', :platform => :mri_18
14
11
  gem 'ruby-debug', :platform => :mri_18
15
- gem 'ruby-debug19', :platform => :mri_19, :require => 'ruby-debug'
12
+ gem 'debugger', :platform => :mri_19
16
13
  gem 'rake'
17
14
  gem 'rspec', '~> 2.0'
18
15
  gem 'guard-rspec'
19
16
  gem 'guard-bundler'
20
- end
17
+ end
data/README.md CHANGED
@@ -21,6 +21,7 @@ Qu was created to overcome some shortcomings in the existing queuing libraries t
21
21
  Decide which backend you want to use and add the gem to your `Gemfile`.
22
22
 
23
23
  ``` ruby
24
+ gem 'qu-rails'
24
25
  gem 'qu-redis'
25
26
  ```
26
27
 
data/lib/qu.rb CHANGED
@@ -35,11 +35,3 @@ Qu.configure do |c|
35
35
  c.logger.level = Logger::INFO
36
36
  end
37
37
 
38
- if defined?(Rails)
39
- if defined?(Rails::Railtie)
40
- require 'qu/railtie'
41
- else
42
- Qu.logger = Rails.logger
43
- end
44
- end
45
-
@@ -13,6 +13,29 @@ module Qu
13
13
 
14
14
  def failed(payload, error)
15
15
  end
16
+
17
+ def register_worker(*)
18
+ end
19
+
20
+ def unregister_worker(*)
21
+ end
22
+
23
+ def clear(*)
24
+ end
25
+
26
+ def connection=(*)
27
+ end
28
+
29
+ def reserve(*)
30
+ end
31
+
32
+ def length(*)
33
+ 0
34
+ end
35
+
36
+ def queues(*)
37
+ ["default"]
38
+ end
16
39
  end
17
40
  end
18
41
  end
@@ -200,44 +200,6 @@ shared_examples_for 'a backend' do
200
200
  end
201
201
  end
202
202
 
203
- describe 'requeue' do
204
- context 'with a failed job' do
205
- before do
206
- subject.enqueue(payload)
207
- subject.reserve(worker).id.should == payload.id
208
- subject.failed(payload, Exception.new)
209
- end
210
-
211
- it 'should add the job back on the queue' do
212
- subject.length(payload.queue).should == 0
213
- subject.requeue(payload.id)
214
- subject.length(payload.queue).should == 1
215
-
216
- p = subject.reserve(worker)
217
- p.should be_instance_of(Qu::Payload)
218
- p.id.should == payload.id
219
- p.klass.should == payload.klass
220
- p.args.should == payload.args
221
- end
222
-
223
- it 'should remove the job from the failed jobs' do
224
- subject.length('failed').should == 1
225
- subject.requeue(payload.id)
226
- subject.length('failed').should == 0
227
- end
228
-
229
- it 'should return the job' do
230
- subject.requeue(payload.id).id.should == payload.id
231
- end
232
- end
233
-
234
- context 'without a failed job' do
235
- it 'should return false' do
236
- subject.requeue('1').should be_false
237
- end
238
- end
239
- end
240
-
241
203
  describe 'register_worker' do
242
204
  it 'should add worker to array of workers' do
243
205
  subject.register_worker(worker)
@@ -1,3 +1,3 @@
1
1
  module Qu
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qu/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qu-airbrake"
7
+ s.version = Qu::VERSION
8
+ s.authors = ["Brandon Keepers", "Scott Ellard"]
9
+ s.email = ["brandon@opensoul.org"]
10
+ s.homepage = "http://github.com/bkeepers/qu"
11
+ s.summary = "Airbrake failure backend for qu"
12
+ s.description = "Airbrake failure backend for qu"
13
+
14
+ s.files = `git ls-files -- lib | grep airbrake`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency 'airbrake'
18
+ s.add_dependency 'i18n'
19
+ s.add_dependency 'qu', Qu::VERSION
20
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qu/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qu-exceptional"
7
+ s.version = Qu::VERSION
8
+ s.authors = ["Brandon Keepers"]
9
+ s.email = ["brandon@opensoul.org"]
10
+ s.homepage = "http://github.com/bkeepers/qu"
11
+ s.summary = "Exceptional failure backend for qu"
12
+ s.description = "Exceptional failure backend for qu"
13
+
14
+ s.files = `git ls-files -- lib | grep exceptional`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency 'exceptional'
18
+ s.add_dependency 'qu', Qu::VERSION
19
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qu/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qu-mongo"
7
+ s.version = Qu::VERSION
8
+ s.authors = ["Brandon Keepers"]
9
+ s.email = ["brandon@opensoul.org"]
10
+ s.homepage = "http://github.com/bkeepers/qu"
11
+ s.summary = "Mongo backend for qu"
12
+ s.description = "Mongo backend for qu"
13
+
14
+ s.files = `git ls-files -- lib | grep mongo`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency 'mongo'
18
+ s.add_dependency 'qu', Qu::VERSION
19
+
20
+ s.add_development_dependency 'bson_ext'
21
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qu/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qu-rails"
7
+ s.version = Qu::VERSION
8
+ s.authors = ["Brandon Keepers"]
9
+ s.email = ["brandon@opensoul.org"]
10
+ s.homepage = "http://github.com/bkeepers/qu"
11
+ s.summary = "Rails integration for qu"
12
+ s.description = "Rails integration for qu"
13
+
14
+ s.files = `git ls-files -- lib | grep rails`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency 'rails', '~>3.0'
18
+ s.add_dependency 'qu', Qu::VERSION
19
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "qu/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "qu-redis"
7
+ s.version = Qu::VERSION
8
+ s.authors = ["Brandon Keepers"]
9
+ s.email = ["brandon@opensoul.org"]
10
+ s.homepage = "http://github.com/bkeepers/qu"
11
+ s.summary = "Redis backend for qu"
12
+ s.description = "Redis backend for qu"
13
+
14
+ s.files = `git ls-files -- lib | grep redis`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency 'redis-namespace'
18
+ s.add_dependency 'simple_uuid'
19
+ s.add_dependency 'qu', Qu::VERSION
20
+ end
data/qu.gemspec CHANGED
@@ -2,7 +2,9 @@
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
3
  require "qu/version"
4
4
 
5
- plugins = Dir['qu-*.gemspec'].map {|gemspec| gemspec.scan(/qu-(.*)\.gemspec/).flatten.first }.join('\|')
5
+ plugin_files = Dir['qu-*.gemspec'].map { |gemspec|
6
+ eval(File.read(gemspec)).files
7
+ }.flatten.uniq
6
8
 
7
9
  Gem::Specification.new do |s|
8
10
  s.name = "qu"
@@ -10,11 +12,11 @@ Gem::Specification.new do |s|
10
12
  s.authors = ["Brandon Keepers"]
11
13
  s.email = ["brandon@opensoul.org"]
12
14
  s.homepage = "http://github.com/bkeepers/qu"
13
- s.summary = %q{}
14
- s.description = %q{}
15
+ s.summary = %q{a Ruby library for queuing and processing background jobs.}
16
+ s.description = %q{a Ruby library for queuing and processing background jobs with configurable backends.}
15
17
 
16
- s.files = `git ls-files | grep -v '#{plugins}'`.split("\n")
17
- s.test_files = `git ls-files -- spec | grep -v '#{plugins}'`.split("\n")
18
+ s.files = `git ls-files`.split("\n") - plugin_files
19
+ s.test_files = `git ls-files -- spec`.split("\n")
18
20
  s.executables = `git ls-files -- bin`.split("\n").map{ |f| File.basename(f) }
19
21
  s.require_paths = ["lib"]
20
22
 
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'qu-mongo'
3
+
4
+ describe Qu::Backend::Mongo do
5
+ it_should_behave_like 'a backend'
6
+
7
+ before do
8
+ ENV.delete('MONGOHQ_URL')
9
+ end
10
+
11
+ describe 'connection' do
12
+ it 'should default the qu database' do
13
+ subject.connection.should be_instance_of(Mongo::DB)
14
+ subject.connection.name.should == 'qu'
15
+ end
16
+
17
+ it 'should use MONGOHQ_URL from heroku' do
18
+ Mongo::Connection.any_instance.stub(:connect)
19
+ ENV['MONGOHQ_URL'] = 'mongodb://user:pw@host:10060/quspec'
20
+ subject.connection.name.should == 'quspec'
21
+ # debugger
22
+ subject.connection.connection.host_to_try.should == ['host', 10060]
23
+ subject.connection.connection.auths.should == [{'db_name' => 'quspec', 'username' => 'user', 'password' => 'pw'}]
24
+ end
25
+
26
+ context "Connection Failure" do
27
+ let(:retries_number) { 3 }
28
+ let(:retries_frequency) { 5 }
29
+
30
+ before do
31
+ subject.max_retries = retries_number
32
+ subject.retry_frequency = retries_frequency
33
+
34
+ Mongo::DB.any_instance.stub(:[]).and_raise(Mongo::ConnectionFailure)
35
+ subject.stub(:sleep)
36
+ end
37
+
38
+ it "raise error" do
39
+ expect { subject.queues }.to raise_error(Mongo::ConnectionFailure)
40
+ end
41
+
42
+ it "trying to reconect" do
43
+ subject.database.should_receive(:[]).exactly(4).times.and_raise(Mongo::ConnectionFailure)
44
+ expect { subject.queues }.to raise_error
45
+ end
46
+
47
+ it "sleep between tries" do
48
+ subject.should_receive(:sleep).with(5).ordered
49
+ subject.should_receive(:sleep).with(10).ordered
50
+ subject.should_receive(:sleep).with(15).ordered
51
+
52
+ expect { subject.queues }.to raise_error
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ describe 'reserve' do
59
+ let(:worker) { Qu::Worker.new }
60
+
61
+ describe "on mongo >=2" do
62
+ it 'should return nil when no jobs exist' do
63
+ subject.clear
64
+ Mongo::Collection.any_instance.should_receive(:find_and_modify).and_return(nil)
65
+ lambda { subject.reserve(worker, :block => false).should be_nil }.should_not raise_error
66
+ end
67
+ end
68
+
69
+ describe 'on mongo <2' do
70
+ it 'should return nil when no jobs exist' do
71
+ subject.clear
72
+ Mongo::Collection.any_instance.should_receive(:find_and_modify).and_raise(Mongo::OperationFailure)
73
+ lambda { subject.reserve(worker, :block => false).should be_nil }.should_not raise_error
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'qu-redis'
3
+
4
+ describe Qu::Backend::Redis do
5
+ it_should_behave_like 'a backend'
6
+
7
+ let(:worker) { Qu::Worker.new('default') }
8
+
9
+ before do
10
+ ENV.delete('REDISTOGO_URL')
11
+ end
12
+
13
+ describe 'completed' do
14
+ it 'should delete job' do
15
+ subject.enqueue(Qu::Payload.new(:klass => SimpleJob))
16
+ job = subject.reserve(worker)
17
+ subject.redis.exists("job:#{job.id}").should be_true
18
+ subject.completed(job)
19
+ subject.redis.exists("job:#{job.id}").should be_false
20
+ end
21
+ end
22
+
23
+ describe 'clear_workers' do
24
+ before { subject.register_worker worker }
25
+
26
+ it 'should delete worker key' do
27
+ subject.redis.get("worker:#{worker.id}").should_not be_nil
28
+ subject.clear_workers
29
+ subject.redis.get("worker:#{worker.id}").should be_nil
30
+ end
31
+ end
32
+
33
+ describe 'connection' do
34
+ it 'should create default connection if one not provided' do
35
+ subject.connection.client.host.should == '127.0.0.1'
36
+ subject.connection.client.port.should == 6379
37
+ subject.connection.namespace.should == :qu
38
+ end
39
+
40
+ it 'should use REDISTOGO_URL from heroku with namespace' do
41
+ ENV['REDISTOGO_URL'] = 'redis://0.0.0.0:9876'
42
+ subject.connection.client.host.should == '0.0.0.0'
43
+ subject.connection.client.port.should == 9876
44
+ subject.connection.namespace.should == :qu
45
+ end
46
+
47
+ it 'should allow customizing the namespace' do
48
+ subject.namespace = :foobar
49
+ subject.connection.namespace.should == :foobar
50
+ end
51
+ end
52
+
53
+ describe 'clear' do
54
+ it 'should delete jobs' do
55
+ job = subject.enqueue(Qu::Payload.new(:klass => SimpleJob))
56
+ subject.redis.exists("job:#{job.id}").should be_true
57
+ subject.clear
58
+ subject.redis.exists("job:#{job.id}").should be_false
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ require 'qu-airbrake'
4
+
5
+ describe Qu::Failure::Airbrake do
6
+
7
+ let(:job) { Qu::Payload.new(:id => '123', :klass => SimpleJob, :args => ['987']) }
8
+
9
+ describe ".extra_stuff" do
10
+ it 'should return job data' do
11
+ described_class.extra_stuff(job).should == {
12
+ :parameters => {
13
+ :id => '123',
14
+ :queue => 'default',
15
+ :args => ['987'],
16
+ :class => 'SimpleJob'
17
+ }
18
+ }
19
+ end
20
+ end
21
+
22
+ describe '.create' do
23
+ let(:exception) { Exception.new }
24
+
25
+ it 'should send error' do
26
+ ::Airbrake.should_receive(:notify_or_ignore).with(exception, described_class.extra_stuff(job))
27
+ described_class.create(job, exception)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'qu-exceptional'
3
+
4
+ describe Qu::Failure::Exceptional do
5
+ let(:job) { Qu::Payload.new(:id => '123', :klass => SimpleJob, :args => ['987']) }
6
+
7
+ describe Qu::Failure::Exceptional::ExceptionData do
8
+ subject { Qu::Failure::Exceptional::ExceptionData.new(job, Exception.new) }
9
+
10
+ it 'should include job data in the request' do
11
+ subject.extra_stuff.should == {
12
+ 'request' => {
13
+ 'parameters' => {
14
+ 'id' => '123',
15
+ 'queue' => 'default',
16
+ 'args' => ['987'],
17
+ 'class' => 'SimpleJob'
18
+ }
19
+ },
20
+ 'rescue_block' => {
21
+ 'name' => 'SimpleJob'
22
+ }
23
+ }
24
+ end
25
+ end
26
+
27
+ describe 'create' do
28
+ context 'with exceptional enabled' do
29
+ before do
30
+ Exceptional::Config.enabled = true
31
+ end
32
+
33
+ it 'should send error' do
34
+ Exceptional::Remote.should_receive(:error).with(instance_of(Qu::Failure::Exceptional::ExceptionData))
35
+ described_class.create(job, Exception.new)
36
+ end
37
+ end
38
+
39
+ context 'with exceptional disabled' do
40
+ before do
41
+ Exceptional::Config.enabled = false
42
+ end
43
+
44
+ it 'should not send error' do
45
+ Exceptional::Remote.should_not_receive(:error)
46
+ described_class.create(job, Exception.new)
47
+ end
48
+ end
49
+ end
50
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 4
10
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brandon Keepers
@@ -15,8 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-07 00:00:00 -05:00
19
- default_executable:
18
+ date: 2012-06-13 00:00:00 Z
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: multi_json
@@ -32,7 +31,7 @@ dependencies:
32
31
  version: "0"
33
32
  type: :runtime
34
33
  version_requirements: *id001
35
- description: ""
34
+ description: a Ruby library for queuing and processing background jobs with configurable backends.
36
35
  email:
37
36
  - brandon@opensoul.org
38
37
  executables: []
@@ -56,17 +55,24 @@ files:
56
55
  - lib/qu/failure.rb
57
56
  - lib/qu/logger.rb
58
57
  - lib/qu/payload.rb
59
- - lib/qu/railtie.rb
60
58
  - lib/qu/tasks.rb
61
59
  - lib/qu/version.rb
62
60
  - lib/qu/worker.rb
61
+ - qu-airbrake.gemspec
62
+ - qu-exceptional.gemspec
63
+ - qu-mongo.gemspec
64
+ - qu-rails.gemspec
65
+ - qu-redis.gemspec
63
66
  - qu.gemspec
64
67
  - spec/qu/backend/immediate_spec.rb
68
+ - spec/qu/backend/mongo_spec.rb
69
+ - spec/qu/backend/redis_spec.rb
70
+ - spec/qu/failure/airbrake_spec.rb
71
+ - spec/qu/failure/exceptional_spec.rb
65
72
  - spec/qu/payload_spec.rb
66
73
  - spec/qu/worker_spec.rb
67
74
  - spec/qu_spec.rb
68
75
  - spec/spec_helper.rb
69
- has_rdoc: true
70
76
  homepage: http://github.com/bkeepers/qu
71
77
  licenses: []
72
78
 
@@ -96,12 +102,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
102
  requirements: []
97
103
 
98
104
  rubyforge_project:
99
- rubygems_version: 1.6.1
105
+ rubygems_version: 1.8.15
100
106
  signing_key:
101
107
  specification_version: 3
102
- summary: ""
108
+ summary: a Ruby library for queuing and processing background jobs.
103
109
  test_files:
104
110
  - spec/qu/backend/immediate_spec.rb
111
+ - spec/qu/backend/mongo_spec.rb
112
+ - spec/qu/backend/redis_spec.rb
113
+ - spec/qu/failure/airbrake_spec.rb
114
+ - spec/qu/failure/exceptional_spec.rb
105
115
  - spec/qu/payload_spec.rb
106
116
  - spec/qu/worker_spec.rb
107
117
  - spec/qu_spec.rb
@@ -1,13 +0,0 @@
1
- require 'qu'
2
-
3
- module Qu
4
- class Railtie < Rails::Railtie
5
- rake_tasks do
6
- load "qu/tasks.rb"
7
- end
8
-
9
- initializer "qu.logger" do |app|
10
- Qu.logger = Rails.logger
11
- end
12
- end
13
- end