resque-loner 1.2.1 → 1.3.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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +92 -0
- data/.simplecov +1 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.markdown +11 -0
- data/Gemfile +4 -5
- data/README.markdown +4 -1
- data/Rakefile +13 -41
- data/lib/resque-ext/job.rb +9 -9
- data/lib/resque-ext/resque.rb +4 -9
- data/lib/resque-loner.rb +2 -1
- data/lib/resque-loner/helpers.rb +22 -9
- data/lib/resque-loner/legacy_helpers.rb +91 -0
- data/lib/resque-loner/unique_job.rb +23 -14
- data/lib/resque-loner/version.rb +1 -1
- data/resque-loner.gemspec +41 -32
- data/spec/loner_spec.rb +73 -51
- data/spec/spec_helper.rb +19 -3
- data/spec/support/redis_instance.rb +133 -0
- data/test/airbrake_test.rb +27 -0
- data/test/dump.rdb +0 -0
- data/test/job_hooks_test.rb +191 -52
- data/test/job_plugins_test.rb +33 -31
- data/test/plugin_test.rb +38 -26
- data/{spec/redis-test.conf → test/redis-test-cluster.conf} +4 -4
- data/test/resque-web_test.rb +23 -17
- data/test/resque_failure_redis_test.rb +23 -0
- data/test/resque_test.rb +56 -37
- data/test/test_helper.rb +58 -29
- data/test/worker_test.rb +311 -55
- metadata +157 -58
- data/init.rb +0 -1
- data/rails/init.rb +0 -1
- data/test/hoptoad_test.rb +0 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: de3cf9ac86e6b7d373f9f281805f3a0fe4da5548
|
4
|
+
data.tar.gz: daf48d9aa6bc0a2f9a0afdeac093ab55fc04f1b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f25db5e2368a0b32d8cc5aaf363ee5b63eaa68dd78ef204b705434df500b376bf7c3cfe50f8819df1d99fdecdf685e42b540fed5e9c8f193a02978a4c587275b
|
7
|
+
data.tar.gz: d6be67b0d07ae6c98d167edca1cf6537d84458137f89c968af4db5f9b8e445974cfd2bf87bb3ea36d5fde29e81143792843cbbc80845e77e0a70b4a2944e6e63
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-03-20 16:42:32 -0400 using RuboCop version 0.19.1.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 1
|
9
|
+
AmbiguousOperator:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# Offense count: 1
|
13
|
+
AmbiguousRegexpLiteral:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
# Offense count: 36
|
17
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
18
|
+
ClassAndModuleChildren:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
# Offense count: 5
|
22
|
+
ClassVars:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
# Offense count: 75
|
26
|
+
Documentation:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
# Offense count: 20
|
30
|
+
Encoding:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
# Offense count: 1
|
34
|
+
Eval:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
# Offense count: 1
|
38
|
+
FavorUnlessOverNegatedIf:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
# Offense count: 2
|
42
|
+
# Configuration parameters: Exclude.
|
43
|
+
FileName:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
# Offense count: 27
|
47
|
+
# Configuration parameters: AllowedVariables.
|
48
|
+
GlobalVars:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
# Offense count: 1
|
52
|
+
HandleExceptions:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
# Offense count: 75
|
56
|
+
LineLength:
|
57
|
+
Max: 161
|
58
|
+
|
59
|
+
# Offense count: 1
|
60
|
+
# Configuration parameters: CountComments.
|
61
|
+
MethodLength:
|
62
|
+
Max: 17
|
63
|
+
|
64
|
+
# Offense count: 1
|
65
|
+
ModuleFunction:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
# Offense count: 2
|
69
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
70
|
+
RaiseArgs:
|
71
|
+
Enabled: false
|
72
|
+
|
73
|
+
# Offense count: 3
|
74
|
+
RedundantBegin:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
# Offense count: 1
|
78
|
+
UnlessElse:
|
79
|
+
Enabled: false
|
80
|
+
|
81
|
+
# Offense count: 1
|
82
|
+
UnreachableCode:
|
83
|
+
Enabled: false
|
84
|
+
|
85
|
+
# Offense count: 5
|
86
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
87
|
+
VariableName:
|
88
|
+
Enabled: false
|
89
|
+
|
90
|
+
# Offense count: 11
|
91
|
+
Void:
|
92
|
+
Enabled: false
|
data/.simplecov
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
SimpleCov.start { add_filter '/spec/' } if ENV['COVERAGE']
|
data/.travis.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
---
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 1.9.3
|
5
|
+
- 2.1.1
|
6
|
+
env:
|
7
|
+
global:
|
8
|
+
- RESQUE_LONER_DISABLE_TEST_REDIS_SERVER=1
|
9
|
+
- COVERAGE=1
|
10
|
+
- secure: c9PvRm9w0ewSsS1QDogwPCvSXO+xgHm0mcVA+iiUknezitNjDwaTuBqGtLJ/PjMnQ16QfG0ApDvSqqOw9rSjwM7meCqiQZlJRqqyd547PNhbP6J56mtuXvxMM7wvulK/aLeIYwDeON0Do52FSY4l2/oN2QvA2hIvX8RTDyrfdaA=
|
11
|
+
services:
|
12
|
+
- redis-server
|
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
1.3.0
|
2
|
+
--------------------------------
|
3
|
+
Enhancements and bug fixes from @mateusdelbianco. Not allowing a job to
|
4
|
+
be executed immediately after execution, another from @mateusdelbianco!
|
5
|
+
Merged @andrejj's fix which removes an unused `#first` from a redis
|
6
|
+
multi call. @kforsman created an internal helpers module to remove the
|
7
|
+
dependency on the deprecated `Resque::Helpers` module. Added RuboCop,
|
8
|
+
SimpleCov, and CodeClimate, plus tweaked some stuff in Travis
|
9
|
+
configuration.
|
10
|
+
|
11
|
+
|
1
12
|
1.2.1
|
2
13
|
--------------------------------
|
3
14
|
Merged @aerodynamik's pull request. Enqueuing and marking as
|
data/Gemfile
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
source 'http://rubygems.org'
|
3
|
+
|
2
4
|
gemspec
|
3
5
|
|
4
|
-
group :development
|
5
|
-
|
6
|
-
gem 'ruby-debug', :platform => :mri_18
|
7
|
-
gem 'ruby-debug19', :platform => :mri_19
|
8
|
-
end
|
6
|
+
gem 'debugger', group: :development, platform: :mri_19
|
7
|
+
gem 'codeclimate-test-reporter', group: :test, require: nil
|
data/README.markdown
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
Resque-Loner
|
2
2
|
======
|
3
3
|
|
4
|
+
[](https://travis-ci.org/resque/resque-loner)
|
5
|
+
[](https://codeclimate.com/github/resque/resque-loner)
|
6
|
+
|
4
7
|
Resque-Loner is a plugin for defunkt/resque which adds unique jobs to resque: Only one job with the same payload per queue.
|
5
8
|
|
6
9
|
|
@@ -20,7 +23,7 @@ Tests
|
|
20
23
|
-----------
|
21
24
|
To make sure this plugin works on your installation, you should run the tests. resque-loner is tested in RSpec, but it also includes resque's original testsuite. You can run all tests specific to resque-loner with `rake spec`.
|
22
25
|
|
23
|
-
To make sure the plugin did not break resque, you can run `rake test` (the standard resque test suite). This runs all tests from the 1.
|
26
|
+
To make sure the plugin did not break resque, you can run `rake test` (the standard resque test suite). This runs all tests from the 1.22.0 version of resque, so make sure you have that version of resque installed, when you run the resque-tests.
|
24
27
|
|
25
28
|
Example
|
26
29
|
--------
|
data/Rakefile
CHANGED
@@ -1,49 +1,32 @@
|
|
1
|
-
#
|
2
|
-
# Setup
|
3
|
-
#
|
4
|
-
|
5
1
|
$LOAD_PATH.unshift 'lib'
|
6
2
|
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
9
5
|
Bundler.setup
|
10
6
|
|
11
7
|
require 'rspec/core/rake_task'
|
12
|
-
|
13
8
|
load 'tasks/redis.rake'
|
14
9
|
require 'rake/testtask'
|
15
|
-
|
16
10
|
require 'resque/tasks'
|
17
|
-
|
18
11
|
require 'bundler/gem_tasks'
|
12
|
+
require 'rubocop/rake_task'
|
19
13
|
|
20
14
|
def command?(command)
|
21
15
|
system("type #{command} > /dev/null 2>&1")
|
22
16
|
end
|
23
17
|
|
18
|
+
task default: [:rubocop, :spec]
|
24
19
|
|
25
|
-
|
26
|
-
# Tests
|
27
|
-
#
|
28
|
-
|
29
|
-
task :default => :spec
|
20
|
+
Rubocop::RakeTask.new
|
30
21
|
|
31
|
-
desc
|
22
|
+
desc 'Run specs for resque-loner'
|
32
23
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
33
|
-
t.pattern =
|
24
|
+
t.pattern = 'spec/**/*_spec.rb'
|
34
25
|
t.rspec_opts = %w(-fd -c)
|
35
26
|
end
|
36
27
|
|
37
|
-
# desc "Run resque's test suite to make sure we did not break anything"
|
38
|
-
# task :test do
|
39
|
-
# rg = command?(:rg)
|
40
|
-
# Dir['test/**/*_test.rb'].each do |f|
|
41
|
-
# rg ? sh("rg #{f}") : ruby(f)
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
|
45
28
|
if command?(:rg)
|
46
|
-
desc
|
29
|
+
desc 'Run the test suite with rg'
|
47
30
|
task :test do
|
48
31
|
Dir['test/**/*_test.rb'].each do |f|
|
49
32
|
sh("rg #{f}")
|
@@ -51,33 +34,22 @@ if command?(:rg)
|
|
51
34
|
end
|
52
35
|
else
|
53
36
|
Rake::TestTask.new do |test|
|
54
|
-
test.libs <<
|
37
|
+
test.libs << 'test'
|
55
38
|
test.test_files = FileList['test/**/*_test.rb']
|
56
39
|
end
|
57
40
|
end
|
58
41
|
|
59
42
|
if command? :kicker
|
60
|
-
desc
|
43
|
+
desc 'Launch Kicker (like autotest)'
|
61
44
|
task :kicker do
|
62
|
-
puts
|
63
|
-
exec
|
45
|
+
puts 'Kicking... (ctrl+c to cancel)'
|
46
|
+
exec 'kicker -e rake test lib examples'
|
64
47
|
end
|
65
48
|
end
|
66
49
|
|
67
|
-
|
68
|
-
#
|
69
|
-
# Install
|
70
|
-
#
|
71
|
-
|
72
|
-
task :install => [ 'redis:install', 'dtach:install' ]
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
# Documentation
|
77
|
-
#
|
50
|
+
task :install => ['redis:install', 'dtach:install']
|
78
51
|
|
79
52
|
begin
|
80
53
|
require 'sdoc_helpers'
|
81
54
|
rescue LoadError
|
82
55
|
end
|
83
|
-
|
data/lib/resque-ext/job.rb
CHANGED
@@ -2,24 +2,24 @@
|
|
2
2
|
# Since there were not enough hooks to hook into, I have to overwrite
|
3
3
|
# 3 methods of Resque::Job - the rest of the implementation is in the
|
4
4
|
# proper Plugin namespace.
|
5
|
-
#
|
5
|
+
#
|
6
6
|
module Resque
|
7
7
|
class Job
|
8
|
-
|
9
|
-
|
10
8
|
#
|
11
9
|
# Overwriting original create method to mark an item as queued
|
12
10
|
# after Resque::Job.create has called Resque.push
|
13
11
|
#
|
14
12
|
def self.create_with_loner(queue, klass, *args)
|
15
13
|
return create_without_loner(queue, klass, *args) if Resque.inline?
|
16
|
-
item = { :
|
17
|
-
return
|
14
|
+
item = { class: klass.to_s, args: args }
|
15
|
+
return 'EXISTED' if Resque::Plugins::Loner::Helpers.loner_queued?(queue, item)
|
18
16
|
# multi block returns array of keys
|
17
|
+
create_return_value = false
|
19
18
|
Resque.redis.multi do
|
20
|
-
create_without_loner(queue, klass, *args)
|
19
|
+
create_return_value = create_without_loner(queue, klass, *args)
|
21
20
|
Resque::Plugins::Loner::Helpers.mark_loner_as_queued(queue, item)
|
22
|
-
end
|
21
|
+
end
|
22
|
+
create_return_value
|
23
23
|
end
|
24
24
|
|
25
25
|
#
|
@@ -27,13 +27,13 @@ module Resque
|
|
27
27
|
#
|
28
28
|
def self.reserve_with_loner(queue)
|
29
29
|
item = reserve_without_loner(queue)
|
30
|
-
Resque::Plugins::Loner::Helpers.mark_loner_as_unqueued(
|
30
|
+
Resque::Plugins::Loner::Helpers.mark_loner_as_unqueued(queue, item) if item && !Resque.inline?
|
31
31
|
item
|
32
32
|
end
|
33
33
|
|
34
34
|
#
|
35
35
|
# Overwriting original destroy method to mark all destroyed jobs as unqueued.
|
36
|
-
# Because the original method only returns the amount of jobs destroyed, but not
|
36
|
+
# Because the original method only returns the amount of jobs destroyed, but not
|
37
37
|
# the jobs themselves. Hence Resque::Plugins::Loner::Helpers.job_destroy looks almost
|
38
38
|
# as the original method Resque::Job.destroy. Couldn't make it any dry'er.
|
39
39
|
#
|
data/lib/resque-ext/resque.rb
CHANGED
@@ -1,26 +1,21 @@
|
|
1
1
|
module Resque
|
2
|
-
|
3
|
-
|
4
|
-
enqueued_in?(queue_from_class(klass), klass, *args )
|
2
|
+
def self.enqueued?(klass, *args)
|
3
|
+
enqueued_in?(queue_from_class(klass), klass, *args)
|
5
4
|
end
|
6
5
|
|
7
6
|
def self.enqueued_in?(queue, klass, *args)
|
8
|
-
item = { :
|
7
|
+
item = { class: klass.to_s, args: args }
|
9
8
|
return nil unless Resque::Plugins::Loner::Helpers.item_is_a_unique_job?(item)
|
10
9
|
Resque::Plugins::Loner::Helpers.loner_queued?(queue, item)
|
11
10
|
end
|
12
11
|
|
13
12
|
def self.remove_queue_with_loner_cleanup(queue)
|
14
|
-
|
13
|
+
remove_queue_without_loner_cleanup(queue)
|
15
14
|
Resque::Plugins::Loner::Helpers.cleanup_loners(queue)
|
16
15
|
end
|
17
16
|
|
18
|
-
|
19
17
|
class << self
|
20
|
-
|
21
18
|
alias_method :remove_queue_without_loner_cleanup, :remove_queue
|
22
19
|
alias_method :remove_queue, :remove_queue_with_loner_cleanup
|
23
|
-
|
24
20
|
end
|
25
|
-
|
26
21
|
end
|
data/lib/resque-loner.rb
CHANGED
data/lib/resque-loner/helpers.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
+
require 'resque-loner/legacy_helpers'
|
2
|
+
|
1
3
|
module Resque
|
2
4
|
module Plugins
|
3
5
|
module Loner
|
4
6
|
class Helpers
|
5
|
-
extend Resque::
|
7
|
+
extend Resque::Plugins::Loner::LegacyHelpers
|
6
8
|
|
7
9
|
def self.loner_queued?(queue, item)
|
8
10
|
return false unless item_is_a_unique_job?(item)
|
9
|
-
redis.get(unique_job_queue_key(queue, item)) ==
|
11
|
+
redis.get(unique_job_queue_key(queue, item)) == '1'
|
10
12
|
end
|
11
13
|
|
12
14
|
def self.mark_loner_as_queued(queue, item)
|
13
15
|
return unless item_is_a_unique_job?(item)
|
14
16
|
key = unique_job_queue_key(queue, item)
|
15
17
|
redis.set(key, 1)
|
16
|
-
unless(ttl=item_ttl(item)) == -1 # no need to incur overhead for default value
|
18
|
+
unless (ttl = item_ttl(item)) == -1 # no need to incur overhead for default value
|
17
19
|
redis.expire(key, ttl)
|
18
20
|
end
|
19
21
|
end
|
@@ -21,17 +23,21 @@ module Resque
|
|
21
23
|
def self.mark_loner_as_unqueued(queue, job)
|
22
24
|
item = job.is_a?(Resque::Job) ? job.payload : job
|
23
25
|
return unless item_is_a_unique_job?(item)
|
24
|
-
|
26
|
+
unless (ttl = loner_lock_after_execution_period(item)) == 0
|
27
|
+
redis.expire(unique_job_queue_key(queue, item), ttl)
|
28
|
+
else
|
29
|
+
redis.del(unique_job_queue_key(queue, item))
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
def self.unique_job_queue_key(queue, item)
|
28
|
-
job_key = constantize(item[:class] || item[
|
34
|
+
job_key = constantize(item[:class] || item['class']).redis_key(item)
|
29
35
|
"loners:queue:#{queue}:job:#{job_key}"
|
30
36
|
end
|
31
37
|
|
32
38
|
def self.item_is_a_unique_job?(item)
|
33
39
|
begin
|
34
|
-
klass = constantize(item[:class] || item[
|
40
|
+
klass = constantize(item[:class] || item['class'])
|
35
41
|
klass.included_modules.include?(::Resque::Plugins::UniqueJob)
|
36
42
|
rescue
|
37
43
|
false # Resque testsuite also submits strings as job classes while Resque.enqueue'ing,
|
@@ -40,12 +46,20 @@ module Resque
|
|
40
46
|
|
41
47
|
def self.item_ttl(item)
|
42
48
|
begin
|
43
|
-
constantize(item[:class] || item[
|
49
|
+
constantize(item[:class] || item['class']).loner_ttl
|
44
50
|
rescue
|
45
51
|
-1
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
55
|
+
def self.loner_lock_after_execution_period(item)
|
56
|
+
begin
|
57
|
+
constantize(item[:class] || item['class']).loner_lock_after_execution_period
|
58
|
+
rescue
|
59
|
+
0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
49
63
|
def self.job_destroy(queue, klass, *args)
|
50
64
|
klass = klass.to_s
|
51
65
|
redis_queue = "queue:#{queue}"
|
@@ -57,7 +71,7 @@ module Resque
|
|
57
71
|
match &= json['args'] == args unless args.empty?
|
58
72
|
|
59
73
|
if match
|
60
|
-
|
74
|
+
Resque::Plugins::Loner::Helpers.mark_loner_as_unqueued(queue, json)
|
61
75
|
end
|
62
76
|
end
|
63
77
|
end
|
@@ -66,7 +80,6 @@ module Resque
|
|
66
80
|
keys = redis.keys("loners:queue:#{queue}:job:*")
|
67
81
|
redis.del(*keys) unless keys.empty?
|
68
82
|
end
|
69
|
-
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|