resque-workers-lock 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Bart Olsthoorn, website: bartolsthoorn.nl
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Resque Workers Lock
2
+ This is a [resque](https://github.com/defunkt/resque) plugin inspired by [resque-lock](https://github.com/defunkt/resque-lock) and requires Resque 1.7.0.
3
+
4
+ ``` ruby
5
+ gem 'resque-workers-lock'
6
+ ```
7
+
8
+ ## What does it do?
9
+ If resque jobs have the same lock applied this means that those jobs cannot be processed simultaneously by two or more workers.
10
+
11
+ ## What is the default lock?
12
+ By default the lock is the instance name + arguments (just like the classic resque-lock). Override this lock to lock on specific arguments.
13
+
14
+ ## How does it differ from resque-lock?
15
+ Resque-lock will not let you queue jobs when you locked them. Resque-workers-lock locks on a workers-level and will requeue the locked jobs. Resque workers lock will not prevent you to queue jobs. If a worker takes on a job that is already being processed by another worker it will put the job back up in the queue!
16
+
17
+ ## Example
18
+ This example shows how you can use the workers-lock to prevent two jobs with the same domain to be processed simultaneously.
19
+ ``` ruby
20
+ require 'resque/plugins/workers/lock'
21
+
22
+ class Scraper
23
+ extend Resque::Plugins::Workers::Lock
24
+
25
+ def self.lock(domain)
26
+ return domain
27
+ end
28
+
29
+ def self.perform(domain)
30
+ # do the work
31
+ end
32
+ end
33
+ ```
34
+
35
+ ## Requeue loop
36
+ When a job is requeue'ed there is a small delay (1 second by default) before the worker places the job actually back in the queue. Let's say you have two jobs left, and one job is taking 15 seconds on the first worker and the other similar job is being blocked by the second worker. The second worker will continuously try to put the job back in the queue and it will try to process it again (racing for 15 seconds untill the other job has finished). This only happens when there are no other (not locked) jobs in the queue.
37
+
38
+ To overwrite this delay in your class:
39
+ ``` ruby
40
+ def self.requeue_perform_delay
41
+ 5.0
42
+ end
43
+ ```
44
+
45
+ Please note that setting this value to 5 seconds will keep the worker idle for 5 seconds when the job is locked.
46
+
47
+ ## Possibilities to prevent the loop
48
+ Do a delayed resque (re)queue. However, this will have approximately the same results and will require a large extra chunk of code and rake configurations.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rake/testtask'
2
+ require 'rdoc/task'
3
+
4
+ def command?(command)
5
+ system("type #{command} > /dev/null")
6
+ end
7
+
8
+ # Tests
9
+
10
+ task :default => :test
11
+
12
+ if command? :turn
13
+ desc "Run tests"
14
+ task :test do
15
+ suffix = "-n #{ENV['TEST']}" if ENV['TEST']
16
+ sh "turn test/*.rb #{suffix}"
17
+ end
18
+ else
19
+ Rake::TestTask.new do |t|
20
+ t.libs << 'lib'
21
+ t.pattern = 'test/**/*_test.rb'
22
+ t.verbose = false
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ module Resque
2
+ module Plugins
3
+ module Workers
4
+ module Lock
5
+ # Override in your job to control the lock key.
6
+ def lock(*args)
7
+ "lock:#{name}-#{args.to_s}"
8
+ end
9
+
10
+ def requeue_perform_delay
11
+ 1.0
12
+ end
13
+
14
+ def before_perform_lock(*args)
15
+ nx = Resque.redis.setnx(lock(*args), true)
16
+ if nx == false
17
+ sleep(requeue_perform_delay)
18
+ Resque.enqueue(self, *args)
19
+ raise Resque::Job::DontPerform
20
+ end
21
+ end
22
+
23
+ def around_perform_lock(*args)
24
+ begin
25
+ yield
26
+ ensure
27
+ # Clear the lock. (even with errors)
28
+ Resque.redis.del(lock(*args))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/test/lock_test.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'test/unit'
2
+ require 'resque'
3
+ require 'resque/plugins/workers/lock'
4
+
5
+ $counter = 0
6
+
7
+ class LockTest < Test::Unit::TestCase
8
+ class Job
9
+ extend Resque::Plugins::Workers::Lock
10
+ @queue = :lock_test
11
+
12
+ def self.perform
13
+ raise "This should not have not happened"
14
+ end
15
+ end
16
+
17
+ def setup
18
+ Resque.redis.del('queue:lock_test')
19
+ Resque.redis.del(Job.lock)
20
+ end
21
+
22
+ def test_lint
23
+ assert_nothing_raised do
24
+ Resque::Plugin.lint(Resque::Plugins::Workers::Lock)
25
+ end
26
+ end
27
+
28
+ def test_version
29
+ major, minor, patch = Resque::Version.split('.')
30
+ assert_equal 1, major.to_i
31
+ assert minor.to_i >= 17
32
+ assert Resque::Plugin.respond_to?(:before_enqueue_hooks)
33
+ end
34
+
35
+ def test_enqueue
36
+ 3.times { Resque.enqueue(Job) }
37
+
38
+ assert_equal 3, Resque.redis.llen('queue:lock_test')
39
+ end
40
+
41
+ def test_lock
42
+ # TODO: test that two workers are not processing two jobs
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-workers-lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bart Olsthoorn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: resque
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: turn
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! "A Resque plugin. If you want to prevent specific jobs to be processed
63
+ simultaneously, \nextend it with this module. It locks on the first argument in
64
+ the perform method.\n\nFor example:\n\n class Scraper\n extend Resque::Plugins::Workers::Lock\n\n
65
+ \ def self.lock(domain)\n return domain\n end\n\n def
66
+ self.perform(domain)\n # do the work\n end\n end\n"
67
+ email: bartolsthoorn@gmail.com
68
+ executables: []
69
+ extensions: []
70
+ extra_rdoc_files: []
71
+ files:
72
+ - README.md
73
+ - Rakefile
74
+ - LICENSE
75
+ - lib/resque/plugins/workers/lock.rb
76
+ - test/lock_test.rb
77
+ homepage: http://github.com/bartolsthoorn/resque-workers-lock
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.24
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Resque plugin, prevent specific jobs to be processed simultaneously by multiple
101
+ workers.
102
+ test_files: []