Skip to content

Commit 0e0b271

Browse files
authored
Merge pull request #588 from Shopify/refresh-lock
Refresh script sha if it doesnt exist on Redis server
2 parents f88f808 + f65e7dd commit 0e0b271

3 files changed

Lines changed: 29 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
### Changed
77
- Change log format and file name
88
- Drop testing on ruby 1.9.3
9+
- `Lock::Resilient`: Refresh lua script sha if it does not exist in redis server
910

1011
### Fixed
1112
- Reporting version via `resque-scheduler --version`

lib/resque/scheduler/lock/resilient.rb

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,11 @@ module Scheduler
66
module Lock
77
class Resilient < Base
88
def acquire!
9-
Resque.redis.evalsha(
10-
acquire_sha,
11-
keys: [key],
12-
argv: [value]
13-
).to_i == 1
9+
evalsha(:acquire, [key], [value]).to_i == 1
1410
end
1511

1612
def locked?
17-
Resque.redis.evalsha(
18-
locked_sha,
19-
keys: [key],
20-
argv: [value]
21-
).to_i == 1
13+
evalsha(:locked, [key], [value]).to_i == 1
2214
end
2315

2416
def timeout=(seconds)
@@ -32,6 +24,21 @@ def timeout=(seconds)
3224

3325
private
3426

27+
def evalsha(script, keys, argv, refresh: false)
28+
sha_method_name = "#{script}_sha"
29+
Resque.redis.evalsha(
30+
send(sha_method_name, refresh),
31+
keys: keys,
32+
argv: argv
33+
)
34+
rescue Redis::CommandError => e
35+
if e.message =~ /NOSCRIPT/
36+
refresh = true
37+
retry
38+
end
39+
raise
40+
end
41+
3542
def locked_sha(refresh = false)
3643
@locked_sha = nil if refresh
3744

test/scheduler_locking_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,17 @@ def lock_is_not_held(lock)
222222
assert !@lock.locked?, 'you should not have the lock'
223223
end
224224

225+
test 'refreshes sha cache when the sha cannot be found on ' \
226+
'the redis server' do
227+
assert @lock.acquire!
228+
assert @lock.locked?
229+
230+
Resque.redis.script(:flush)
231+
232+
assert @lock.locked?
233+
assert_false @lock.acquire!
234+
end
235+
225236
test 'you should not be able to acquire the lock if someone ' \
226237
'else holds it' do
227238
lock_is_not_held(@lock)

0 commit comments

Comments
 (0)