discourse/lib/temporary_redis.rb

112 lines
2.4 KiB
Ruby

# frozen_string_literal: true
class TemporaryRedis
REDIS_TEMP_DIR = "/tmp/discourse_temp_redis"
REDIS_LOG_PATH = "#{REDIS_TEMP_DIR}/redis.log"
REDIS_PID_PATH = "#{REDIS_TEMP_DIR}/redis.pid"
attr_reader :instance
def initialize
set_redis_server_bin
end
def port
@port ||= find_free_port(11_000..11_900)
end
def start
return if @started
FileUtils.rm_rf(REDIS_TEMP_DIR)
Dir.mkdir(REDIS_TEMP_DIR)
FileUtils.touch(REDIS_LOG_PATH)
puts "Starting redis on port: #{port}"
@thread =
Thread.new do
system(
@redis_server_bin,
"--port",
port.to_s,
"--pidfile",
REDIS_PID_PATH,
"--logfile",
REDIS_LOG_PATH,
"--databases",
"1",
"--save",
'""',
"--appendonly",
"no",
"--daemonize",
"no",
"--maxclients",
"100",
"--dir",
REDIS_TEMP_DIR,
)
end
puts "Waiting for redis server to start..."
success = false
instance = nil
config = { port: port, host: "127.0.0.1", db: 0 }
start = Time.now
while !success
begin
instance = DiscourseRedis.new(config, namespace: true)
success = instance.ping == "PONG"
rescue Redis::CannotConnectError
ensure
if !success && (Time.now - start) >= 5
STDERR.puts "ERROR: Could not connect to redis in 5 seconds."
self.remove
exit(1)
elsif !success
sleep 0.1
end
end
end
puts "Redis is ready"
@instance = instance
@started = true
end
def remove
if @instance
@instance.shutdown
@thread.join
puts "Redis has been shutdown."
end
FileUtils.rm_rf(REDIS_TEMP_DIR)
@started = false
puts "Redis files have been cleaned up."
end
private
def set_redis_server_bin
path = `which redis-server 2> /dev/null`.strip
if path.size < 1
STDERR.puts "ERROR: redis-server is not installed on this machine. Please install it"
exit(1)
end
@redis_server_bin = path
rescue => ex
STDERR.puts "ERROR: Failed to find redis-server binary:"
STDERR.puts ex.inspect
exit(1)
end
def find_free_port(range)
range.each { |port| return port if port_available?(port) }
end
def port_available?(port)
TCPServer.open(port).close
true
rescue Errno::EADDRINUSE
false
end
end