sidetiq 0.3.5 → 0.3.6
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 +4 -4
- data/.travis.yml +33 -0
- data/CHANGELOG.md +11 -0
- data/lib/sidetiq.rb +2 -0
- data/lib/sidetiq/clock.rb +1 -19
- data/lib/sidetiq/lock.rb +63 -0
- data/lib/sidetiq/schedulable.rb +1 -1
- data/lib/sidetiq/schedule.rb +1 -1
- data/lib/sidetiq/version.rb +1 -1
- data/test/test_lock.rb +30 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1df64df09fdf5d7e87b13410a3a8b39c325fd70a
|
4
|
+
data.tar.gz: 43e79f2eb7c71065ba27f54cf8e36924c8575250
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b11cd2d90c41504bd9914ca3058cc242c9d4819d4d8550348e2326d85aaacbcf9293f02f5ac01b058be6b222f94eedbca5bafeba76c3cc231e168c1d63a964c
|
7
|
+
data.tar.gz: c5b583be6d96c52e8494bc790c406f5d06cd84e0e0b643e0ca14ef9eae1dc36b5e858cfde858a2e8891d3c11bb18d2982f4018370beba0451cccd54f1171930d
|
data/.travis.yml
CHANGED
@@ -1,6 +1,39 @@
|
|
1
1
|
language: ruby
|
2
|
+
branches:
|
3
|
+
only:
|
4
|
+
- master
|
5
|
+
services:
|
6
|
+
- redis-server
|
2
7
|
rvm:
|
3
8
|
- 1.9.3
|
4
9
|
- 2.0.0
|
5
10
|
- jruby-19mode
|
6
11
|
- rbx-19mode
|
12
|
+
- ruby-head
|
13
|
+
- jruby-head
|
14
|
+
jdk:
|
15
|
+
- openjdk6
|
16
|
+
- openjdk7
|
17
|
+
- oraclejdk7
|
18
|
+
matrix:
|
19
|
+
exclude:
|
20
|
+
- rvm: 2.0.0
|
21
|
+
jdk: openjdk7
|
22
|
+
- rvm: 2.0.0
|
23
|
+
jdk: openjdk6
|
24
|
+
- rvm: 1.9.3
|
25
|
+
jdk: openjdk7
|
26
|
+
- rvm: 1.9.3
|
27
|
+
jdk: openjdk6
|
28
|
+
- rvm: rbx-19mode
|
29
|
+
jdk: openjdk7
|
30
|
+
- rvm: rbx-19mode
|
31
|
+
jdk: openjdk6
|
32
|
+
- rvm: ruby-head
|
33
|
+
jdk: openjdk7
|
34
|
+
- rvm: ruby-head
|
35
|
+
jdk: openjdk6
|
36
|
+
allow_failures:
|
37
|
+
- rvm: rbx-19mode
|
38
|
+
- rvm: ruby-head
|
39
|
+
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.3.6
|
2
|
+
-----
|
3
|
+
|
4
|
+
- Better protection against stale locks and race-conditions.
|
5
|
+
|
6
|
+
Locking is now done using WATCH/MULTI/EXEC/UNWATCH and additionally
|
7
|
+
includes a host and process specific identifier to prevent accidental
|
8
|
+
unlocks from other Sidekiq processes.
|
9
|
+
|
10
|
+
- Fix Sidetiq::Schedulable documentation.
|
11
|
+
|
1
12
|
0.3.5
|
2
13
|
-----
|
3
14
|
|
data/lib/sidetiq.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'monitor'
|
3
3
|
require 'ostruct'
|
4
4
|
require 'singleton'
|
5
|
+
require 'socket'
|
5
6
|
|
6
7
|
# gems
|
7
8
|
require 'ice_cube'
|
@@ -10,6 +11,7 @@ require 'sidekiq'
|
|
10
11
|
# internal
|
11
12
|
require 'sidetiq/config'
|
12
13
|
require 'sidetiq/clock'
|
14
|
+
require 'sidetiq/lock'
|
13
15
|
require 'sidetiq/middleware'
|
14
16
|
require 'sidetiq/schedule'
|
15
17
|
require 'sidetiq/schedulable'
|
data/lib/sidetiq/clock.rb
CHANGED
@@ -52,7 +52,7 @@ module Sidetiq
|
|
52
52
|
tick = gettime
|
53
53
|
mon_synchronize do
|
54
54
|
schedules.each do |worker, sched|
|
55
|
-
|
55
|
+
Lock.new(worker).synchronize do |redis|
|
56
56
|
if sched.backfill? && (last = worker.last_scheduled_occurrence) > 0
|
57
57
|
last = Sidetiq.config.utc ? Time.at(last).utc : Time.at(last)
|
58
58
|
sched.occurrences_between(last + 1, tick).each do |past_t|
|
@@ -150,24 +150,6 @@ module Sidetiq
|
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
-
def synchronize_clockworks(klass)
|
154
|
-
lock = "sidetiq:#{klass.name}:lock"
|
155
|
-
|
156
|
-
Sidekiq.redis do |redis|
|
157
|
-
if redis.setnx(lock, 1)
|
158
|
-
Sidetiq.logger.debug "Sidetiq::Clock lock #{lock}"
|
159
|
-
|
160
|
-
begin
|
161
|
-
redis.pexpire(lock, Sidetiq.config.lock_expire)
|
162
|
-
yield redis
|
163
|
-
ensure
|
164
|
-
redis.del(lock)
|
165
|
-
Sidetiq.logger.debug "Sidetiq::Clock unlock #{lock}"
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
153
|
def clock
|
172
154
|
loop do
|
173
155
|
sleep_time = time { yield }
|
data/lib/sidetiq/lock.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module Sidetiq
|
2
|
+
class Lock # :nodoc: all
|
3
|
+
attr_reader :key, :timeout
|
4
|
+
|
5
|
+
OWNER = "#{Socket.gethostname}:#{Process.pid}"
|
6
|
+
|
7
|
+
def initialize(key, timeout = Sidetiq.config.lock_expire)
|
8
|
+
@key = key.kind_of?(Class) ? "sidetiq:#{key.name}:lock" : "sidetiq:#{key}:lock"
|
9
|
+
@timeout = timeout
|
10
|
+
end
|
11
|
+
|
12
|
+
def synchronize
|
13
|
+
Sidekiq.redis do |redis|
|
14
|
+
if lock(redis)
|
15
|
+
Sidetiq.logger.debug "Sidetiq::Clock lock #{key}"
|
16
|
+
|
17
|
+
begin
|
18
|
+
yield redis
|
19
|
+
ensure
|
20
|
+
unlock(redis)
|
21
|
+
Sidetiq.logger.debug "Sidetiq::Clock unlock #{key}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def lock(redis)
|
30
|
+
acquired = false
|
31
|
+
|
32
|
+
watch(redis, key) do
|
33
|
+
if !redis.exists(key)
|
34
|
+
acquired = !!redis.multi do |multi|
|
35
|
+
multi.psetex(key, timeout, OWNER)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
acquired
|
41
|
+
end
|
42
|
+
|
43
|
+
def unlock(redis)
|
44
|
+
watch(redis, key) do
|
45
|
+
if redis.get(key) == OWNER
|
46
|
+
redis.multi do |multi|
|
47
|
+
multi.del(key)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def watch(redis, *args)
|
54
|
+
redis.watch(*args)
|
55
|
+
|
56
|
+
begin
|
57
|
+
yield
|
58
|
+
ensure
|
59
|
+
redis.unwatch
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/sidetiq/schedulable.rb
CHANGED
data/lib/sidetiq/schedule.rb
CHANGED
data/lib/sidetiq/version.rb
CHANGED
data/test/test_lock.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
class TestLock < Sidetiq::TestCase
|
4
|
+
def test_locking
|
5
|
+
lock_name = SecureRandom.hex(8)
|
6
|
+
key = SecureRandom.hex(8)
|
7
|
+
|
8
|
+
Sidekiq.redis do |redis|
|
9
|
+
redis.set(key, 0)
|
10
|
+
|
11
|
+
5.times.map do
|
12
|
+
Thread.start do
|
13
|
+
locked(lock_name) do |r|
|
14
|
+
sleep 0.1
|
15
|
+
r.incr(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end.each(&:join)
|
19
|
+
|
20
|
+
assert_equal "1", redis.get(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def locked(lock_name)
|
25
|
+
Sidetiq::Lock.new(lock_name).synchronize do |redis|
|
26
|
+
yield redis
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidetiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Svensson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- lib/sidetiq.rb
|
57
57
|
- lib/sidetiq/clock.rb
|
58
58
|
- lib/sidetiq/config.rb
|
59
|
+
- lib/sidetiq/lock.rb
|
59
60
|
- lib/sidetiq/middleware.rb
|
60
61
|
- lib/sidetiq/schedulable.rb
|
61
62
|
- lib/sidetiq/schedule.rb
|
@@ -73,6 +74,7 @@ files:
|
|
73
74
|
- test/helper.rb
|
74
75
|
- test/test_clock.rb
|
75
76
|
- test/test_config.rb
|
77
|
+
- test/test_lock.rb
|
76
78
|
- test/test_middleware.rb
|
77
79
|
- test/test_schedule.rb
|
78
80
|
- test/test_sidetiq.rb
|
@@ -113,6 +115,7 @@ test_files:
|
|
113
115
|
- test/helper.rb
|
114
116
|
- test/test_clock.rb
|
115
117
|
- test/test_config.rb
|
118
|
+
- test/test_lock.rb
|
116
119
|
- test/test_middleware.rb
|
117
120
|
- test/test_schedule.rb
|
118
121
|
- test/test_sidetiq.rb
|