Skip to content

Commit

Permalink
Merge pull request #29 from seamusabshere/recover-function
Browse files Browse the repository at this point in the history
recover from SCRIPT FLUSH
  • Loading branch information
maltoe committed Nov 13, 2015
2 parents a92b6a4 + 4c7879a commit 8a3a5b5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
21 changes: 19 additions & 2 deletions lib/redlock/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,15 @@ def initialize(connection)
end

def lock(resource, val, ttl)
@redis.evalsha(@lock_script_sha, keys: [resource], argv: [val, ttl])
recover_from_script_flush do
@redis.evalsha @lock_script_sha, keys: [resource], argv: [val, ttl]
end
end

def unlock(resource, val)
@redis.evalsha(@unlock_script_sha, keys: [resource], argv: [val])
recover_from_script_flush do
@redis.evalsha @unlock_script_sha, keys: [resource], argv: [val]
end
rescue
# Nothing to do, unlocking is just a best-effort attempt.
end
Expand All @@ -117,6 +121,19 @@ def load_scripts
@unlock_script_sha = @redis.script(:load, UNLOCK_SCRIPT)
@lock_script_sha = @redis.script(:load, LOCK_SCRIPT)
end

def recover_from_script_flush
tries = 0
yield
rescue Redis::CommandError
if $!.message.include?('NOSCRIPT') and tries == 0
load_scripts
tries += 1
retry
else
raise $!
end
end
end

def try_lock_instances(resource, ttl, extend)
Expand Down
21 changes: 21 additions & 0 deletions spec/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,25 @@
end
end
end

describe 'after SCRIPT FLUSH' do
let(:server) { Redis.new }
it 'recovers lock function' do
lock_info = lock_manager.lock('a', ttl)
expect(lock_info).to be_lock_info_for('a')
server.script :flush
lock_info = lock_manager.lock('b', ttl)
expect(lock_info).to be_lock_info_for('b')
end

it 'recovers unlock function' do
lock_info = lock_manager.lock(resource_key, ttl)
lock_manager.unlock(lock_info)
expect(resource_key).to be_lockable(lock_manager, ttl)
server.script :flush
lock_info = lock_manager.lock(resource_key, ttl)
lock_manager.unlock(lock_info)
expect(resource_key).to be_lockable(lock_manager, ttl)
end
end
end

0 comments on commit 8a3a5b5

Please sign in to comment.