qu 0.1.4 → 0.2.0

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