Class: Redis

Inherits:
Object
  • Object
show all
Defined in:
lib/redis.rb,
lib/pipeline.rb

Direct Known Subclasses

Pipeline

Defined Under Namespace

Classes: Pipeline

Constant Summary collapse

ERR =
"-".freeze
OK =
'OK'.freeze
SINGLE =
'+'.freeze
BULK =
'$'.freeze
MULTI =
'*'.freeze
INT =
':'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Redis

Returns a new instance of Redis.



22
23
24
25
26
27
# File 'lib/redis.rb', line 22

def initialize(opts={})
  @opts = {:host => 'localhost', :port => '6379', :db => 0}.merge(opts)
  $debug = @opts[:debug]
  @db = @opts[:db]
  @server = Server.new(@opts[:host], @opts[:port], (@opts[:timeout]||10))
end

Instance Attribute Details

#serverObject (readonly)

Returns the value of attribute server.



19
20
21
# File 'lib/redis.rb', line 19

def server
  @server
end

Instance Method Details

#[](key) ⇒ Object



192
193
194
# File 'lib/redis.rb', line 192

def [](key)
  get(key)
end

#[]=(key, val) ⇒ Object



419
420
421
# File 'lib/redis.rb', line 419

def []=(key, val)
  set(key,val)
end

#bgsaveObject



105
106
107
108
# File 'lib/redis.rb', line 105

def bgsave
  write "BGSAVE\r\n"
  get_response == OK
end

#bulk_replyObject



123
124
125
126
127
128
129
130
131
132
# File 'lib/redis.rb', line 123

def bulk_reply
  begin
    x = read
    puts "bulk_reply read value is #{x.inspect}" if $debug
    return x
  rescue => e
    puts "error in bulk_reply #{e}" if $debug
    nil
  end
end

#dbsizeObject



431
432
433
434
# File 'lib/redis.rb', line 431

def dbsize
  write("DBSIZE\r\n")
  get_response
end

#decr(key, decrement = nil) ⇒ Object



215
216
217
218
219
220
221
222
# File 'lib/redis.rb', line 215

def decr(key, decrement=nil)
  if decrement
    write "DECRBY #{key} #{decrement}\r\n"
  else
    write "DECR #{key}\r\n"
  end    
  get_response
end

#delete(key) ⇒ Object



187
188
189
190
# File 'lib/redis.rb', line 187

def delete(key)
  write "DEL #{key}\r\n"
  get_response == 1
end

#expire(key, expiry = nil) ⇒ Object



436
437
438
439
# File 'lib/redis.rb', line 436

def expire(key, expiry=nil)
  write("EXPIRE #{key} #{expiry}\r\n")
  get_response == 1
end

#fetch(len) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/redis.rb', line 141

def fetch(len)
  with_socket_management(@server) do |socket|
    len = [0, len.to_i].max
    res = socket.read(len + 2)
    res = res.chomp if res
    res
  end
end

#flush_allObject



92
93
94
95
96
97
98
# File 'lib/redis.rb', line 92

def flush_all
  puts "Warning!\nFlushing *ALL* databases!\n5 Seconds to Hit ^C!"
  trap('INT') {quit; return false}
  sleep 5
  write "FLUSHALL\r\n"
  get_response == OK
end

#flush_dbObject



87
88
89
90
# File 'lib/redis.rb', line 87

def flush_db
  write "FLUSHDB\r\n"
  get_response == OK
end

#get(key) ⇒ Object



196
197
198
199
# File 'lib/redis.rb', line 196

def get(key)
  write "GET #{key}\r\n"
  get_response
end

#get_replyObject



409
410
411
412
413
414
415
416
417
# File 'lib/redis.rb', line 409

def get_reply
  begin
    r = read(1)
    raise RedisError if (r == "\r" || r == "\n")
  rescue RedisError
    retry
  end
  r
end

#get_responseObject



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/redis.rb', line 459

def get_response
  begin
    rtype = get_reply
  rescue => e
    raise RedisError, e.inspect
  end
  puts "reply_type is #{rtype.inspect}" if $debug
  case rtype
  when SINGLE
    single_line
  when BULK
    bulk_reply
  when MULTI
    multi_bulk
  when INT
    integer_reply
  when ERR
    raise RedisError, single_line
  else
    raise RedisError, "Unknown response.."
  end
end

#hostObject



43
44
45
# File 'lib/redis.rb', line 43

def host
  @opts[:host]
end

#incr(key, increment = nil) ⇒ Object



206
207
208
209
210
211
212
213
# File 'lib/redis.rb', line 206

def incr(key, increment=nil)
  if increment
    write "INCRBY #{key} #{increment}\r\n"
  else
    write "INCR #{key}\r\n"
  end    
  get_response
end

#infoObject



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/redis.rb', line 110

def info
 info = {}
 write("INFO\r\n")
 x = get_response
 x.each do |kv|
   k,v = kv.split(':', 2)
   k,v = k.chomp, v = v.chomp
   info[k.to_sym] = v
 end
 info
end

#integer_replyObject



482
483
484
# File 'lib/redis.rb', line 482

def integer_reply
  Integer(read_proto)
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


182
183
184
185
# File 'lib/redis.rb', line 182

def key?(key)
  write "EXISTS #{key}\r\n"
  get_response == 1
end

#keys(glob) ⇒ Object



158
159
160
161
# File 'lib/redis.rb', line 158

def keys(glob)
  write "KEYS #{glob}\r\n"
  get_response.split(' ')
end

#last_saveObject



100
101
102
103
# File 'lib/redis.rb', line 100

def last_save
  write "LASTSAVE\r\n"
  get_response.to_i
end

#list_index(key, index) ⇒ Object



279
280
281
282
# File 'lib/redis.rb', line 279

def list_index(key, index)
  write "LINDEX #{key} #{index}\r\n"
  get_response
end

#list_length(key) ⇒ Object



229
230
231
232
233
234
235
236
237
# File 'lib/redis.rb', line 229

def list_length(key)
  write "LLEN #{key}\r\n"
  case i = get_response
  when -2
    raise RedisError, "key: #{key} does not hold a list value"
  else
    i
  end
end

#list_range(key, start, ending) ⇒ Object



269
270
271
272
# File 'lib/redis.rb', line 269

def list_range(key, start, ending)
  write "LRANGE #{key} #{start} #{ending}\r\n"
  get_response
end

#list_rm(key, count, value) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
# File 'lib/redis.rb', line 284

def list_rm(key, count, value)
  write "LREM #{key} #{count} #{value.to_s.size}\r\n#{value}\r\n"
  case num = get_response
  when -1
    raise RedisError, "key: #{key} does not exist"
  when -2
    raise RedisError, "key: #{key} does not hold a list value"
  else
    num
  end
end

#list_set(key, index, val) ⇒ Object



264
265
266
267
# File 'lib/redis.rb', line 264

def list_set(key, index, val)
  write "LSET #{key} #{index} #{val.to_s.size}\r\n#{val}\r\n"
  get_response == OK
end

#list_trim(key, start, ending) ⇒ Object



274
275
276
277
# File 'lib/redis.rb', line 274

def list_trim(key, start, ending)
  write "LTRIM #{key} #{start} #{ending}\r\n"
  get_response
end

#mget(*keys) ⇒ Object



201
202
203
204
# File 'lib/redis.rb', line 201

def mget(*keys)
  write "MGET #{keys.join(' ')}\r\n"
  get_response
end

#monitorObject



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/redis.rb', line 64

def monitor
  with_socket_management(@server) do |socket|
    trap("INT") { puts "\nGot ^C! Dying!"; exit }
    write "MONITOR\r\n"
    puts "Now Monitoring..."
    socket.read(12)
    loop do
      x = socket.gets
      puts x unless x.nil?
    end
  end
end

#multi_bulkObject



396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/redis.rb', line 396

def multi_bulk
  res = read_proto
  puts "mb res is #{res.inspect}" if $debug
  list = []
  Integer(res).times do
    vf = get_response
    puts "curren vf is #{vf.inspect}" if $debug
    list << vf
    puts "current list is #{list.inspect}" if $debug
  end
  list
end

#pipelined {|pipeline| ... } ⇒ Object

Yields:

  • (pipeline)


29
30
31
32
33
# File 'lib/redis.rb', line 29

def pipelined
  pipeline = Pipeline.new(self)
  yield pipeline
  pipeline.finish
end

#pop_head(key) ⇒ Object



254
255
256
257
# File 'lib/redis.rb', line 254

def pop_head(key)
  write "LPOP #{key}\r\n"
  get_response
end

#pop_tail(key) ⇒ Object



259
260
261
262
# File 'lib/redis.rb', line 259

def pop_tail(key)
  write "RPOP #{key}\r\n"
  get_response
end

#portObject



39
40
41
# File 'lib/redis.rb', line 39

def port
  @opts[:port]
end

#push_head(key, string) ⇒ Object



249
250
251
252
# File 'lib/redis.rb', line 249

def push_head(key, string)
  write "LPUSH #{key} #{string.to_s.size}\r\n#{string.to_s}\r\n"
  get_response
end

#push_tail(key, string) ⇒ Object



244
245
246
247
# File 'lib/redis.rb', line 244

def push_tail(key, string)
  write "RPUSH #{key} #{string.to_s.size}\r\n#{string.to_s}\r\n"
  get_response
end

#quitObject



77
78
79
# File 'lib/redis.rb', line 77

def quit
  write "QUIT\r\n"
end

#randkeyObject



224
225
226
227
# File 'lib/redis.rb', line 224

def randkey
  write "RANDOMKEY\r\n"
  get_response
end

#read(length = read_proto) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/redis.rb', line 150

def read(length = read_proto)
  with_socket_management(@server) do |socket|
    res = socket.read(length)
    puts "read is #{res.inspect}" if $debug
    res
  end
end

#read_protoObject



517
518
519
520
521
522
523
524
525
# File 'lib/redis.rb', line 517

def read_proto
  with_socket_management(@server) do |socket|
    if res = socket.gets
      x = res.chomp
      puts "read_proto is #{x.inspect}\n\n" if $debug
      x.to_i
    end
  end
end

#read_socketObject



495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/redis.rb', line 495

def read_socket
  begin
    socket = @server.socket
    while res = socket.read(8096)
      break if res.size != 8096
    end
  #Timeout or server down
  rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNREFUSED => e
    server.close
    puts "Client (#{server.inspect}) disconnected from server: #{e.inspect}\n" if $debug
    retry
  rescue Timeout::Error => e
  #BTM - Ignore this error so we don't go into an endless loop
    puts "Client (#{server.inspect}) Timeout\n" if $debug
  #Server down
  rescue NoMethodError => e
    puts "Client (#{server.inspect}) tryin server that is down: #{e.inspect}\n Dying!" if $debug
    raise Errno::ECONNREFUSED
    #exit
  end
end

#rename(oldkey, newkey) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/redis.rb', line 168

def rename(oldkey, newkey)
  write "RENAMENX #{oldkey} #{newkey}\r\n"
  case get_response
  when -1
    raise RedisRenameError, "source key: #{oldkey} does not exist"
  when 0
    raise RedisRenameError, "target key: #{oldkey} already exists"
  when -3
    raise RedisRenameError, "source and destination keys are the same"
  when 1
    true
  end
end

#rename!(oldkey, newkey) ⇒ Object



163
164
165
166
# File 'lib/redis.rb', line 163

def rename!(oldkey, newkey)
  write "RENAME #{oldkey} #{newkey}\r\n"
  get_response
end

#select_db(index) ⇒ Object



81
82
83
84
85
# File 'lib/redis.rb', line 81

def select_db(index)
  @db = index
  write "SELECT #{index}\r\n"
  get_response
end

#set(key, val, expiry = nil) ⇒ Object



424
425
426
427
428
429
# File 'lib/redis.rb', line 424

def set(key, val, expiry=nil)
  write("SET #{key} #{val.to_s.size}\r\n#{val}\r\n")
  s = get_response == OK
  return expire(key, expiry) if s && expiry
  s
end

#set_add(key, member) ⇒ Object



296
297
298
299
300
301
302
303
304
305
306
# File 'lib/redis.rb', line 296

def set_add(key, member)
  write "SADD #{key} #{member.to_s.size}\r\n#{member}\r\n"
  case get_response
  when 1
    true
  when 0
    false
  when -2
    raise RedisError, "key: #{key} contains a non set value"
  end
end

#set_count(key) ⇒ Object



320
321
322
323
324
325
326
327
328
# File 'lib/redis.rb', line 320

def set_count(key)
  write "SCARD #{key}\r\n"
  case i = get_response
  when -2
    raise RedisError, "key: #{key} contains a non set value"
  else
    i
  end
end

#set_delete(key, member) ⇒ Object



308
309
310
311
312
313
314
315
316
317
318
# File 'lib/redis.rb', line 308

def set_delete(key, member)
  write "SREM #{key} #{member.to_s.size}\r\n#{member}\r\n"
  case get_response
  when 1
    true
  when 0
    false
  when -2
    raise RedisError, "key: #{key} contains a non set value"
  end
end

#set_diff(*keys) ⇒ Object



367
368
369
370
# File 'lib/redis.rb', line 367

def set_diff(*keys)
  write "SDIFF #{keys.join(' ')}\r\n"
  Set.new(get_response)
end

#set_diff_store(destkey, *keys) ⇒ Object



372
373
374
375
# File 'lib/redis.rb', line 372

def set_diff_store(destkey, *keys)
  write "SDIFFSTORE #{destkey} #{keys.join(' ')}\r\n"
  get_response
end

#set_inter_store(destkey, *keys) ⇒ Object



352
353
354
355
# File 'lib/redis.rb', line 352

def set_inter_store(destkey, *keys)
  write "SINTERSTORE #{destkey} #{keys.join(' ')}\r\n"
  get_response
end

#set_intersect(*keys) ⇒ Object



347
348
349
350
# File 'lib/redis.rb', line 347

def set_intersect(*keys)
  write "SINTER #{keys.join(' ')}\r\n"
  Set.new(get_response)
end

#set_member?(key, member) ⇒ Boolean

Returns:

  • (Boolean)


330
331
332
333
334
335
336
337
338
339
340
# File 'lib/redis.rb', line 330

def set_member?(key, member)
  write "SISMEMBER #{key} #{member.to_s.size}\r\n#{member}\r\n"
  case get_response
  when 1
    true
  when 0
    false
  when -2
    raise RedisError, "key: #{key} contains a non set value"
  end
end

#set_members(key) ⇒ Object



342
343
344
345
# File 'lib/redis.rb', line 342

def set_members(key)
  write "SMEMBERS #{key}\r\n"
  Set.new(get_response)
end

#set_move(srckey, destkey, member) ⇒ Object



377
378
379
380
# File 'lib/redis.rb', line 377

def set_move(srckey, destkey, member)
  write "SMOVE #{srckey} #{destkey} #{member.to_s.size}\r\n#{member}\r\n"
  get_response == 1
end

#set_union(*keys) ⇒ Object



357
358
359
360
# File 'lib/redis.rb', line 357

def set_union(*keys)
  write "SUNION #{keys.join(' ')}\r\n"
  Set.new(get_response)
end

#set_union_store(destkey, *keys) ⇒ Object



362
363
364
365
# File 'lib/redis.rb', line 362

def set_union_store(destkey, *keys)
  write "SUNIONSTORE #{destkey} #{keys.join(' ')}\r\n"
  get_response
end

#set_unless_exists(key, val) ⇒ Object



441
442
443
444
# File 'lib/redis.rb', line 441

def set_unless_exists(key, val)
  write "SETNX #{key} #{val.to_s.size}\r\n#{val}\r\n"
  get_response == 1
end

#single_lineObject



486
487
488
489
490
491
492
493
# File 'lib/redis.rb', line 486

def single_line
  buff = ""
  while buff[-2..-1] != "\r\n"
    buff << read(1)
  end
  puts "single_line value is #{buff[0..-3].inspect}" if $debug
  buff[0..-3]
end

#sort(key, opts = {}) ⇒ Object



382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/redis.rb', line 382

def sort(key, opts={})
  cmd = "SORT #{key}"
  cmd << " BY #{opts[:by]}" if opts[:by]
  cmd << " GET #{opts[:get]}" if opts[:get]
  cmd << " INCR #{opts[:incr]}" if opts[:incr]
  cmd << " DEL #{opts[:del]}" if opts[:del]
  cmd << " DECR #{opts[:decr]}" if opts[:decr]
  cmd << " #{opts[:order]}" if opts[:order]
  cmd << " LIMIT #{opts[:limit].join(' ')}" if opts[:limit]
  cmd << "\r\n"
  write(cmd)
  get_response
end

#status_code_replyObject



446
447
448
449
450
451
452
453
454
455
456
457
# File 'lib/redis.rb', line 446

def status_code_reply
  begin
    res = read_proto  
    if res.index('-') == 0          
      raise RedisError, res
    else          
      true
    end
  rescue RedisError
     raise RedisError
  end
end

#to_sObject



35
36
37
# File 'lib/redis.rb', line 35

def to_s
  "#{host}:#{port}"
end

#type?(key) ⇒ Boolean

Returns:

  • (Boolean)


239
240
241
242
# File 'lib/redis.rb', line 239

def type?(key)
  write "TYPE #{key}\r\n"
  get_response
end

#with_socket_management(server, &block) ⇒ Object



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

def with_socket_management(server, &block)
  begin
    socket = server.socket
    block.call(socket)
  #Timeout or server down
  rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNREFUSED, Timeout::Error => e
    server.close
    puts "Client (#{server.inspect}) disconnected from server: #{e.inspect}\n" if $debug
    retry
  #Server down
  rescue NoMethodError => e
    puts "Client (#{server.inspect}) tryin server that is down: #{e.inspect}\n Dying!" if $debug
    raise Errno::ECONNREFUSED
    #exit
  end
end

#write(data) ⇒ Object



134
135
136
137
138
139
# File 'lib/redis.rb', line 134

def write(data)
  with_socket_management(@server) do |socket|
    puts "writing: #{data}" if $debug
    socket.write(data)
  end
end