Class: Wurk::Preflight::Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/wurk/preflight/reader.rb

Overview

The only way a preflight touches Redis. Anything outside the allowlist raises before it reaches the socket, so "read-only" is enforced here rather than promised by each check. LLEN is left out on purpose: sampling never needs a length, and a list's length is the one read an operator's alert may already key on.

Defined Under Namespace

Classes: Forbidden

Constant Summary collapse

ALLOWED =
%w[INFO DBSIZE SCAN TYPE EXISTS GET HGET HMGET HGETALL SMEMBERS LRANGE LINDEX ZRANGE ZCARD].freeze
CLIENT_LIMITS =

Bounded per call, so a stalled server costs seconds and never hangs an operator's shell. No retries: a read that failed is reported, not replayed.

{ connect_timeout: 2.0, read_timeout: 5.0, write_timeout: 5.0, reconnect_attempts: 0 }.freeze

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Reader

Returns a new instance of Reader.



22
23
24
25
# File 'lib/wurk/preflight/reader.rb', line 22

def initialize(config)
  opts = RedisOptions.normalize(config.redis_config).except(*RedisOptions::POOL_KEYS).merge(CLIENT_LIMITS)
  @client = (RedisOptions.sentinel?(opts) ? RedisClient.sentinel(**opts) : RedisClient.config(**opts)).new_client
end

Instance Method Details

#call(*command) ⇒ Object



27
28
29
# File 'lib/wurk/preflight/reader.rb', line 27

def call(*command)
  @client.call(*guard(command))
end

#close ⇒ Object



49
# File 'lib/wurk/preflight/reader.rb', line 49

def close = @client.close

#pipeline(commands) ⇒ Object



31
32
33
34
35
36
# File 'lib/wurk/preflight/reader.rb', line 31

def pipeline(commands)
  return [] if commands.empty?

  commands.each { |command| guard(command) }
  @client.pipelined { |pipe| commands.each { |command| pipe.call(*command) } }
end

#target ⇒ Object

Where this reads from, for the report. Built field by field so no credential can reach it.



40
41
42
43
44
45
46
47
# File 'lib/wurk/preflight/reader.rb', line 40

def target
  config = @client.config
  return { 'path' => config.path, 'db' => config.db.to_i } if config.path

  { 'host' => config.host, 'port' => config.port, 'db' => config.db.to_i }
rescue ::StandardError => e
  { 'host' => "unknown (#{e.class})" }
end