Skip to content

Instantly share code, notes, and snippets.

@mthadley
Last active June 16, 2022 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mthadley/45a3fdb65e3bd2984aea6a6a36e7e6b1 to your computer and use it in GitHub Desktop.
Save mthadley/45a3fdb65e3bd2984aea6a6a36e7e6b1 to your computer and use it in GitHub Desktop.
`dump` or `restore` Redis keys
#!/usr/bin/env ruby
require "bundler/inline"
require "json"
require "base64"
gemfile do
source "https://rubygems.org"
gem "redis", "~> 4.6"
gem "hiredis", "~> 0.6"
end
class RedisClient
attr_reader :redis
def initialize(url)
@redis = Redis.new(url: url, driver: :hiredis)
end
end
class KeysDumper < RedisClient
def dump(path)
keys = {}
puts "Dumping Keys"
redis.scan_each.each_slice(50) do |batch|
key_futures = {}
redis.pipelined do |pipeline|
batch.each do |key|
key_futures[key] = {
data: pipeline.dump(key),
ttl: pipeline.pttl(key)
}
print "."
end
end
key_futures.each do |key, futures|
keys[key] = {
data_base64: Base64.encode64(futures.fetch(:data).value),
ttl: parse_ttl(futures.fetch(:ttl).value),
}
end
end
puts "\nDone!"
File.open(path, "w") do |file|
file.write(JSON.pretty_generate(keys))
end
end
private
def parse_ttl(value)
case value
when -2 then raise "Key not found: #{key}"
when -1 then nil # No TTL set for key
else value
end
end
end
class KeysImporter < RedisClient
def restore(path)
puts "Restoring Keys"
JSON.load_file!(path).each_slice(50) do |keys|
redis.pipelined do |pipeline|
keys.each do |key, data|
pipeline.restore(
key,
data.fetch("ttl") || 0,
Base64.decode64(data.fetch("data_base64")),
replace: true
)
print "."
end
end
end
puts "\nDone!"
end
end
redis_url = ENV.fetch("REDIS_URL")
keys_file_path = ENV.fetch("KEYS_FILE") { "keys.json" }
case (cmd = ARGV[0])
when "dump" then KeysDumper.new(redis_url).dump(keys_file_path)
when "restore" then KeysImporter.new(redis_url).restore(keys_file_path)
when nil then raise "Need a command, one of 'dump' or 'restore'."
else raise "Not a valid command: #{cmd}."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment