Class: Hiredis::Ruby::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/hiredis/ruby/connection.rb

Constant Summary collapse

EMPTY_ARRAY =
[].freeze
COMMAND_DELIMITER =
"\r\n".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConnection

Returns a new instance of Connection.



193
194
195
196
197
# File 'lib/hiredis/ruby/connection.rb', line 193

def initialize
  @sock = nil
  @timeout = nil
  @fiber_scheduler_supported = defined?(Fiber.scheduler)
end

Instance Attribute Details

#sockObject (readonly)

Returns the value of attribute sock.



191
192
193
# File 'lib/hiredis/ruby/connection.rb', line 191

def sock
  @sock
end

Class Method Details

.errno_to_classObject



12
13
14
# File 'lib/hiredis/ruby/connection.rb', line 12

def self.errno_to_class
  Errno::Mapping
end

Instance Method Details

#_connect(host, port, timeout) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/hiredis/ruby/connection.rb', line 31

def _connect(host, port, timeout)
  sock = nil

  begin
    Timeout.timeout(timeout) do
      sock = TCPSocket.new(host, port)
    end
  rescue SocketError => se
    raise se.message
  rescue Timeout::Error
    raise Errno::ETIMEDOUT
  end

  sock
end

#_connect_unix(path, timeout) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/hiredis/ruby/connection.rb', line 47

def _connect_unix(path, timeout)
  sock = nil

  begin
    Timeout.timeout(timeout) do
      sock = UNIXSocket.new(path)
    end
  rescue SocketError => se
    raise se.message
  rescue Timeout::Error
    raise Errno::ETIMEDOUT
  end

  sock
end

#_wait_readable(io, timeout) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/hiredis/ruby/connection.rb', line 144

def _wait_readable(io, timeout)
  if @fiber_scheduler_supported && Fiber.scheduler
    Fiber.scheduler.io_wait(io, IO::READABLE, timeout)
  else
    IO.select([io], EMPTY_ARRAY, EMPTY_ARRAY, timeout)
  end
end

#_wait_writable(io, timeout) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/hiredis/ruby/connection.rb', line 152

def _wait_writable(io, timeout)
  if @fiber_scheduler_supported && Fiber.scheduler
    Fiber.scheduler.io_wait(io, IO::WRITABLE, timeout)
  else
    IO.select(EMPTY_ARRAY, [io], EMPTY_ARRAY, timeout)
  end
end

#_write(sock, data, timeout) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/hiredis/ruby/connection.rb', line 63

def _write(sock, data, timeout)
  begin
    Timeout.timeout(timeout) do
      sock.write(data)
    end
  rescue Timeout::Error
    raise Errno::EAGAIN
  end
end

#connect(host, port, usecs = nil) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/hiredis/ruby/connection.rb', line 203

def connect(host, port, usecs = nil)
  # Temporarily override timeout on #connect
  timeout = usecs ? (usecs / 1_000_000.0) : @timeout

  # Optionally disconnect current socket
  disconnect if connected?

  sock = _connect(host, port, timeout)
  sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1

  @reader = ::Hiredis::Ruby::Reader.new
  @sock = sock

  nil
end

#connect_unix(path, usecs = 0) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/hiredis/ruby/connection.rb', line 219

def connect_unix(path, usecs = 0)
  # Temporarily override timeout on #connect
  timeout = usecs ? (usecs / 1_000_000.0) : @timeout

  # Optionally disconnect current socket
  disconnect if connected?

  sock = _connect_unix(path, timeout)

  @reader = ::Hiredis::Ruby::Reader.new
  @sock = sock

  nil
end

#connected?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/hiredis/ruby/connection.rb', line 199

def connected?
  !! @sock
end

#disconnectObject



234
235
236
237
238
239
# File 'lib/hiredis/ruby/connection.rb', line 234

def disconnect
  @sock.close
rescue
ensure
  @sock = nil
end

#filenoObject



253
254
255
256
257
# File 'lib/hiredis/ruby/connection.rb', line 253

def fileno
  raise "not connected" unless connected?

  @sock.fileno
end

#flushObject

No-op for now..



278
279
# File 'lib/hiredis/ruby/connection.rb', line 278

def flush
end

#readObject



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/hiredis/ruby/connection.rb', line 281

def read
  raise "not connected" unless connected?

  while (reply = @reader.gets) == false
    begin
      @reader.feed @sock.read_nonblock(1024)
    rescue Errno::EAGAIN
      if _wait_readable(@sock, @timeout)
        # Readable, try again
        retry
      else
        # Timed out, raise
        raise Errno::EAGAIN
      end
    end
  end

  reply
rescue ::EOFError
  raise Errno::ECONNRESET
end

#timeout=(usecs) ⇒ Object

Raises:

  • (ArgumentError)


241
242
243
244
245
246
247
248
249
250
251
# File 'lib/hiredis/ruby/connection.rb', line 241

def timeout=(usecs)
  raise ArgumentError.new("timeout cannot be negative") if usecs < 0

  if usecs == 0
    @timeout = nil
  else
    @timeout = usecs / 1_000_000.0
  end

  nil
end

#write(args) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/hiredis/ruby/connection.rb', line 261

def write(args)
  command = []
  command << "*#{args.size}"
  args.each do |arg|
    arg = arg.to_s
    command << "$#{string_size arg}"
    command << arg
  end

  data = command.join(COMMAND_DELIMITER) + COMMAND_DELIMITER

  _write(@sock, data, @timeout)

  nil
end