Class: SolidRedis::RESP::Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/solid_redis/resp.rb

Instance Method Summary collapse

Constructor Details

#initialize(io, read_timeout:) ⇒ Reader

Returns a new instance of Reader.



31
32
33
34
35
# File 'lib/solid_redis/resp.rb', line 31

def initialize(io, read_timeout:)
  @io = io
  @read_timeout = read_timeout
  @buffer = +""
end

Instance Method Details

#read(exception: true) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/solid_redis/resp.rb', line 60

def read(exception: true)
  case (type = read_bytes(1))
  when "+" then read_line
  when "-" then error_response(read_line, exception)
  when ":" then Integer(read_line)
  when "$" then read_bulk
  when "*" then read_array(exception)
  when "_" then read_line && nil
  when "#" then read_line == "t"
  when "," then Float(read_line)
  when "(" then Integer(read_line)
  when "%" then read_map(exception)
  when "~", ">" then read_collection(exception)
  when "=" then read_verbatim
  when "!" then error_response(read_sized_string, exception)
  when "|" then read_map(exception) && read(exception: exception)
  else raise ProtocolError, "Unknown RESP type byte: #{type.inspect}"
  end
rescue EOFError
  raise ConnectionError, "Redis closed the connection"
rescue ArgumentError => error
  raise ProtocolError, "Invalid Redis response: #{error.message}", cause: error
end

#wait_readable(timeout) ⇒ Object

Waits until at least one byte is available without consuming it. Returns false on timeout. Unlike a timed-out read, this never leaves a partially consumed frame behind, so it is the safe way to poll for the next Pub/Sub message.



51
52
53
54
55
56
57
58
# File 'lib/solid_redis/resp.rb', line 51

def wait_readable(timeout)
  return true unless @buffer.empty?
  return true unless @io.respond_to?(:to_io)

  !IO.select([@io], nil, nil, timeout).nil?
rescue IOError, SystemCallError => error
  raise ConnectionError, error.message, cause: error
end

#with_timeout(timeout) ⇒ Object

Temporarily overrides the read timeout. nil waits forever, which is what blocking commands such as BLPOP with a 0 timeout require.



39
40
41
42
43
44
45
# File 'lib/solid_redis/resp.rb', line 39

def with_timeout(timeout)
  previous = @read_timeout
  @read_timeout = timeout
  yield
ensure
  @read_timeout = previous
end