resque-loner 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -3,3 +3,7 @@
3
3
  **.swp
4
4
  Gemfile.lock
5
5
  .rvmrc
6
+ spec/stdout
7
+ coverage/
8
+ .ruby-version
9
+ .ruby-gemset
@@ -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
@@ -0,0 +1 @@
1
+ SimpleCov.start { add_filter '/spec/' } if ENV['COVERAGE']
@@ -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
@@ -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 do
5
- gem 'gemcutter'
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
@@ -1,6 +1,9 @@
1
1
  Resque-Loner
2
2
  ======
3
3
 
4
+ [![Build Status](https://secure.travis-ci.org/resque/resque-loner.png?branch=master)](https://travis-ci.org/resque/resque-loner)
5
+ [![Code Climate](https://codeclimate.com/github/resque/resque-loner.png)](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.10.0 version of resque, so make sure you have that version of resque installed, when you run the resque-tests.
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 "rubygems"
8
- require "bundler"
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 "Run specs for resque-loner"
22
+ desc 'Run specs for resque-loner'
32
23
  RSpec::Core::RakeTask.new(:spec) do |t|
33
- t.pattern = "spec/**/*_spec.rb"
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 "Run the test suite with rg"
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 << "test"
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 "Launch Kicker (like autotest)"
43
+ desc 'Launch Kicker (like autotest)'
61
44
  task :kicker do
62
- puts "Kicking... (ctrl+c to cancel)"
63
- exec "kicker -e rake test lib examples"
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
-
@@ -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 = { :class => klass.to_s, :args => args }
17
- return "EXISTED" if Resque::Plugins::Loner::Helpers.loner_queued?(queue, item)
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.first
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( queue, item ) if item && !Resque.inline?
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
  #
@@ -1,26 +1,21 @@
1
1
  module Resque
2
-
3
- def self.enqueued?( klass, *args)
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 = { :class => klass.to_s, :args => args }
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
- self.remove_queue_without_loner_cleanup(queue)
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
@@ -2,5 +2,6 @@ require 'rubygems'
2
2
  require 'resque'
3
3
  require 'resque-loner/unique_job'
4
4
  require 'resque-loner/helpers'
5
+ require 'resque-loner/legacy_helpers'
5
6
  require 'resque-ext/job'
6
- require 'resque-ext/resque'
7
+ require 'resque-ext/resque'
@@ -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::Helpers
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)) == "1"
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
- redis.del(unique_job_queue_key(queue, item))
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["class"]).redis_key(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["class"])
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["class"]).loner_ttl
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
- Resque::Plugins::Loner::Helpers.mark_loner_as_unqueued( queue, json )
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