Skip to content

Instantly share code, notes, and snippets.

@aks
Created November 12, 2020 02:53
Show Gist options
  • Save aks/c8e91883ee899472eaf9d5d130c5df3e to your computer and use it in GitHub Desktop.
Save aks/c8e91883ee899472eaf9d5d130c5df3e to your computer and use it in GitHub Desktop.
Little ruby test script to make sure that Redis SET NAME VALUE NX:TRUE locking really works
#!/usr/bin/env ruby
#
require 'redis'
require 'securerandom'
require 'awesome_print'
class RedisTest
attr_reader :name, :redis
HOW_MANY = (1..5)
def initialize(name)
@name = name
@redis = Redis.new
delete_lock(quiet: true)
end
def run_tests
[:serial_test, :parallel_test].each do |test_name|
warn "Running #{test_name}:"
send(test_name)
end
end
def serial_test
delete_lock
if HOW_MANY.map { locked? }.one?
puts 'ok'
else
warn "Serial lock test failed!"
end
end
def parallel_test
delete_lock
if run_many { locked? }.one?
puts 'ok'
else
warn "Parallel lock test failed!"
end
end
def run_many
outfiles = []
HOW_MANY.map { outfiles << fork_one { yield } }
Process.waitall
outfiles.map do |file|
file.rewind
file.read.chomp == "true"
end
ensure
outfiles.each { |file| file.unlink }
end
def fork_one
outfile = Tempfile.new
fork { outfile.puts yield }
outfile
end
def locked?
try_lock && read_lock == my_uuid
end
def read_lock
redis.get lock_name
end
def try_lock
redis.set lock_name, my_uuid, nx: true
end
def delete_lock(quiet: false)
if redis.del(lock_name) != 1
warn "lock #{lock_name} deletion failed!" unless quiet
end
end
def lock_name
@lock ||= name + '-lock'
end
def my_uuid
@uuid ||= SecureRandom.uuid
end
end
RedisTest.new('redis-test').run_tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment