Class: Redis::Connection::Memory

Inherits:
Object
  • Object
show all
Includes:
FakeRedis, CommandHelper
Defined in:
lib/redis/connection/memory.rb

Constant Summary

Constants included from FakeRedis

FakeRedis::Redis, FakeRedis::VERSION

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Memory

Returns a new instance of Memory.



36
37
38
# File 'lib/redis/connection/memory.rb', line 36

def initialize(options = {})
  self.options = options
end

Instance Attribute Details

#bufferObject

Returns the value of attribute buffer.



15
16
17
# File 'lib/redis/connection/memory.rb', line 15

def buffer
  @buffer
end

#database_idObject



40
41
42
# File 'lib/redis/connection/memory.rb', line 40

def database_id
  @database_id ||= 0
end

#optionsObject

Returns the value of attribute options.



15
16
17
# File 'lib/redis/connection/memory.rb', line 15

def options
  @options
end

#repliesObject



61
62
63
# File 'lib/redis/connection/memory.rb', line 61

def replies
  @replies ||= []
end

Class Method Details

.connect(options = {}) ⇒ Object



32
33
34
# File 'lib/redis/connection/memory.rb', line 32

def self.connect(options = {})
  new(options)
end

.databasesObject

Tracks all databases for all instances across the current process. We have to be able to handle two clients with the same host/port accessing different databases at once without overwriting each other. So we store our “data” outside the client instances, in this class level instance method. Client instances access it with a key made up of their host/port, and then select which DB out of the array of them they want. Allows the access we need.



23
24
25
# File 'lib/redis/connection/memory.rb', line 23

def self.databases
  @databases ||= Hash.new {|h,k| h[k] = [] }
end

.reset_all_databasesObject

Used for resetting everything in specs



28
29
30
# File 'lib/redis/connection/memory.rb', line 28

def self.reset_all_databases
  @databases = nil
end

Instance Method Details

#[](key) ⇒ Object



600
601
602
# File 'lib/redis/connection/memory.rb', line 600

def [](key)
  get(key)
end

#[]=(key, value) ⇒ Object



604
605
606
# File 'lib/redis/connection/memory.rb', line 604

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

#append(key, value) ⇒ Object



194
195
196
197
# File 'lib/redis/connection/memory.rb', line 194

def append(key, value)
  data[key] = (data[key] || "")
  data[key] = data[key] + value.to_s
end

#auth(password) ⇒ Object



122
123
124
# File 'lib/redis/connection/memory.rb', line 122

def auth(password)
  "OK"
end

#bgreriteaofObject



153
# File 'lib/redis/connection/memory.rb', line 153

def bgreriteaof ; end

#bgsaveObject



151
# File 'lib/redis/connection/memory.rb', line 151

def bgsave ; end

#connect_unix(path, timeout) ⇒ Object



70
71
# File 'lib/redis/connection/memory.rb', line 70

def connect_unix(path, timeout)
end

#connected?Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/redis/connection/memory.rb', line 66

def connected?
  true
end

#dataObject



57
58
59
# File 'lib/redis/connection/memory.rb', line 57

def data
  find_database
end

#database_instance_keyObject



45
46
47
# File 'lib/redis/connection/memory.rb', line 45

def database_instance_key
  [options[:host], options[:port]].hash
end

#databasesObject



49
50
51
# File 'lib/redis/connection/memory.rb', line 49

def databases
  self.class.databases[database_instance_key]
end

#dbsizeObject



247
248
249
# File 'lib/redis/connection/memory.rb', line 247

def dbsize
  data.keys.count
end

#decr(key) ⇒ Object



669
670
671
672
# File 'lib/redis/connection/memory.rb', line 669

def decr(key)
  data.merge!({ key => (data[key].to_i - 1).to_s || "-1"})
  data[key].to_i
end

#decrby(key, by) ⇒ Object



674
675
676
677
# File 'lib/redis/connection/memory.rb', line 674

def decrby(key, by)
  data.merge!({ key => ((data[key].to_i - by.to_i) || (by.to_i * -1)).to_s })
  data[key].to_i
end

#del(*keys) ⇒ Object

Raises:

  • (Redis::CommandError)


468
469
470
471
472
473
474
475
476
# File 'lib/redis/connection/memory.rb', line 468

def del(*keys)
  keys = keys.flatten(1)
  raise Redis::CommandError, "ERR wrong number of arguments for 'del' command" if keys.empty?
  old_count = data.keys.size
  keys.each do |key|
    data.delete(key)
  end
  old_count - data.keys.size
end

#disconnectObject



73
74
# File 'lib/redis/connection/memory.rb', line 73

def disconnect
end

#echo(string) ⇒ Object



235
236
237
# File 'lib/redis/connection/memory.rb', line 235

def echo(string)
  string
end

#execObject



695
696
697
# File 'lib/redis/connection/memory.rb', line 695

def exec
  buffer.tap {|x| self.buffer = nil }
end

#exists(key) ⇒ Object



251
252
253
# File 'lib/redis/connection/memory.rb', line 251

def exists(key)
  data.key?(key)
end

#expire(key, ttl) ⇒ Object



503
504
505
506
507
# File 'lib/redis/connection/memory.rb', line 503

def expire(key, ttl)
  return unless data[key]
  data.expires[key] = Time.now + ttl
  true
end

#expireat(key, timestamp) ⇒ Object



517
518
519
520
# File 'lib/redis/connection/memory.rb', line 517

def expireat(key, timestamp)
  data.expires[key] = Time.at(timestamp)
  true
end

#find_database(id = database_id) ⇒ Object



53
54
55
# File 'lib/redis/connection/memory.rb', line 53

def find_database id=database_id
  databases[id] ||= ExpiringHash.new
end

#flushallObject



117
118
119
120
# File 'lib/redis/connection/memory.rb', line 117

def flushall
  self.class.databases[database_instance_key] = []
  "OK"
end

#flushdbObject

NOT IMPLEMENTED:

  • blpop

  • brpop

  • brpoplpush

  • discard

  • sort

  • subscribe

  • psubscribe

  • publish



112
113
114
115
# File 'lib/redis/connection/memory.rb', line 112

def flushdb
  databases.delete_at(database_id)
  "OK"
end

#get(key) ⇒ Object



164
165
166
167
# File 'lib/redis/connection/memory.rb', line 164

def get(key)
  data_type_check(key, String)
  data[key]
end

#getbit(key, offset) ⇒ Object



169
170
171
172
# File 'lib/redis/connection/memory.rb', line 169

def getbit(key, offset)
  return unless data[key]
  data[key].unpack('B*')[0].split("")[offset].to_i
end

#getrange(key, start, ending) ⇒ Object Also known as: substr



174
175
176
177
# File 'lib/redis/connection/memory.rb', line 174

def getrange(key, start, ending)
  return unless data[key]
  data[key][start..ending]
end

#getset(key, value) ⇒ Object



180
181
182
183
184
185
# File 'lib/redis/connection/memory.rb', line 180

def getset(key, value)
  data_type_check(key, String)
  data[key].tap do
    set(key, value)
  end
end

#hdel(key, field) ⇒ Object



214
215
216
217
218
# File 'lib/redis/connection/memory.rb', line 214

def hdel(key, field)
  data_type_check(key, Hash)
  data[key] && data[key].delete(field)
  remove_key_for_empty_collection(key)
end

#hexists(key, field) ⇒ Object



592
593
594
595
596
# File 'lib/redis/connection/memory.rb', line 592

def hexists(key, field)
  data_type_check(key, Hash)
  return false unless data[key]
  data[key].key?(field)
end

#hget(key, field) ⇒ Object



209
210
211
212
# File 'lib/redis/connection/memory.rb', line 209

def hget(key, field)
  data_type_check(key, Hash)
  data[key] && data[key][field.to_s]
end

#hgetall(key) ⇒ Object



204
205
206
207
# File 'lib/redis/connection/memory.rb', line 204

def hgetall(key)
  data_type_check(key, Hash)
  data[key].to_a.flatten || {}
end

#hincrby(key, field, increment) ⇒ Object



582
583
584
585
586
587
588
589
590
# File 'lib/redis/connection/memory.rb', line 582

def hincrby(key, field, increment)
  data_type_check(key, Hash)
  if data[key]
    data[key][field] = (data[key][field.to_s].to_i + increment.to_i).to_s
  else
    data[key] = { field => increment.to_s }
  end
  data[key][field].to_i
end

#hkeys(key) ⇒ Object



220
221
222
223
224
# File 'lib/redis/connection/memory.rb', line 220

def hkeys(key)
  data_type_check(key, Hash)
  return [] if data[key].nil?
  data[key].keys
end

#hlen(key) ⇒ Object



570
571
572
573
574
# File 'lib/redis/connection/memory.rb', line 570

def hlen(key)
  data_type_check(key, Hash)
  return 0 unless data[key]
  data[key].size
end

#hmget(key, *fields) ⇒ Object

Raises:

  • (Redis::CommandError)


557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/redis/connection/memory.rb', line 557

def hmget(key, *fields)
  raise Redis::CommandError, "wrong number of arguments for 'hmget' command" if fields.empty?
  data_type_check(key, Hash)
  fields.map do |field|
    field = field.to_s
    if data[key]
      data[key][field]
    else
      nil
    end
  end
end

#hmset(key, *fields) ⇒ Object

Raises:

  • (Redis::CommandError)


546
547
548
549
550
551
552
553
554
555
# File 'lib/redis/connection/memory.rb', line 546

def hmset(key, *fields)
  # mapped_hmset gives us [[:k1, "v1", :k2, "v2"]] for `fields`. Fix that.
  fields = fields[0] if mapped_param?(fields)
  raise Redis::CommandError, "ERR wrong number of arguments for HMSET" if fields.empty? || fields.size.odd?
  data_type_check(key, Hash)
  data[key] ||= {}
  fields.each_slice(2) do |field|
    data[key][field[0].to_s] = field[1].to_s
  end
end

#hset(key, field, value) ⇒ Object



526
527
528
529
530
531
532
533
534
535
536
537
# File 'lib/redis/connection/memory.rb', line 526

def hset(key, field, value)
  data_type_check(key, Hash)
  field = field.to_s
  if data[key]
    result = !data[key].include?(field)
    data[key][field] = value.to_s
    result
  else
    data[key] = { field => value.to_s }
    true
  end
end

#hsetnx(key, field, value) ⇒ Object



539
540
541
542
543
544
# File 'lib/redis/connection/memory.rb', line 539

def hsetnx(key, field, value)
  data_type_check(key, Hash)
  field = field.to_s
  return false if data[key] && data[key][field]
  hset(key, field, value)
end

#hvals(key) ⇒ Object



576
577
578
579
580
# File 'lib/redis/connection/memory.rb', line 576

def hvals(key)
  data_type_check(key, Hash)
  return [] unless data[key]
  data[key].values
end

#incr(key) ⇒ Object



659
660
661
662
# File 'lib/redis/connection/memory.rb', line 659

def incr(key)
  data.merge!({ key => (data[key].to_i + 1).to_s || "1"})
  data[key].to_i
end

#incrby(key, by) ⇒ Object



664
665
666
667
# File 'lib/redis/connection/memory.rb', line 664

def incrby(key, by)
  data.merge!({ key => (data[key].to_i + by.to_i).to_s || by })
  data[key].to_i
end

#infoObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/redis/connection/memory.rb', line 132

def info
  {
    "redis_version" => "0.07",
    "connected_clients" => "1",
    "connected_slaves" => "0",
    "used_memory" => "3187",
    "changes_since_last_save" => "0",
    "last_save_time" => "1237655729",
    "total_connections_received" => "1",
    "total_commands_processed" => "1",
    "uptime_in_seconds" => "36000",
    "uptime_in_days" => 0
  }
end

#keys(pattern = "*") ⇒ Object



226
227
228
229
# File 'lib/redis/connection/memory.rb', line 226

def keys(pattern = "*")
  regexp = Regexp.new(pattern.split("*").map { |r| Regexp.escape(r) }.join(".*"))
  data.keys.select { |key| key =~ regexp }
end

#lastsaveObject



243
244
245
# File 'lib/redis/connection/memory.rb', line 243

def lastsave
  Time.now.to_i
end

#lindex(key, index) ⇒ Object



272
273
274
275
# File 'lib/redis/connection/memory.rb', line 272

def lindex(key, index)
  data_type_check(key, Array)
  data[key] && data[key][index]
end

#linsert(key, where, pivot, value) ⇒ Object



277
278
279
280
281
282
283
284
285
286
# File 'lib/redis/connection/memory.rb', line 277

def linsert(key, where, pivot, value)
  data_type_check(key, Array)
  return unless data[key]
  index = data[key].index(pivot)
  case where
    when :before then data[key].insert(index, value)
    when :after  then data[key].insert(index + 1, value)
    else raise Redis::CommandError, "ERR syntax error"
  end
end

#llen(key) ⇒ Object



255
256
257
258
259
# File 'lib/redis/connection/memory.rb', line 255

def llen(key)
  data_type_check(key, Array)
  return 0 unless data[key]
  data[key].size
end

#lpop(key) ⇒ Object



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

def lpop(key)
  data_type_check(key, Array)
  return unless data[key]
  data[key].shift
end

#lpush(key, value) ⇒ Object



328
329
330
331
332
333
334
335
# File 'lib/redis/connection/memory.rb', line 328

def lpush(key, value)
  data_type_check(key, Array)
  data[key] ||= []
  [value].flatten.each do |val|
    data[key].unshift(val.to_s)
  end
  data[key].size
end

#lpushx(key, value) ⇒ Object



337
338
339
340
341
# File 'lib/redis/connection/memory.rb', line 337

def lpushx(key, value)
  data_type_check(key, Array)
  return unless data[key]
  lpush(key, value)
end

#lrange(key, startidx, endidx) ⇒ Object



261
262
263
264
# File 'lib/redis/connection/memory.rb', line 261

def lrange(key, startidx, endidx)
  data_type_check(key, Array)
  (data[key] && data[key][startidx..endidx]) || []
end

#lrem(key, count, value) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/redis/connection/memory.rb', line 295

def lrem(key, count, value)
  data_type_check(key, Array)
  return unless data[key]
  old_size = data[key].size
  diff =
    if count == 0
      data[key].delete(value)
      old_size - data[key].size
    else
      array = count > 0 ? data[key].dup : data[key].reverse
      count.abs.times{ array.delete_at(array.index(value) || array.length) }
      data[key] = count > 0 ? array.dup : array.reverse
      old_size - data[key].size
    end
  remove_key_for_empty_collection(key)
  diff
end

#lset(key, index, value) ⇒ Object

Raises:

  • (Redis::CommandError)


288
289
290
291
292
293
# File 'lib/redis/connection/memory.rb', line 288

def lset(key, index, value)
  data_type_check(key, Array)
  return unless data[key]
  raise(Redis::CommandError, "ERR index out of range") if index >= data[key].size
  data[key][index] = value
end

#ltrim(key, start, stop) ⇒ Object



266
267
268
269
270
# File 'lib/redis/connection/memory.rb', line 266

def ltrim(key, start, stop)
  data_type_check(key, Array)
  return unless data[key]
  data[key] = data[key][start..stop]
end

#mget(*keys) ⇒ Object

Raises:

  • (Redis::CommandError)


187
188
189
190
191
192
# File 'lib/redis/connection/memory.rb', line 187

def mget(*keys)
  raise Redis::CommandError, "wrong number of arguments for 'mget' command" if keys.empty?
  # We work with either an array, or list of arguments
  keys = keys.first if keys.size == 1
  data.values_at(*keys)
end

#monitorObject



147
# File 'lib/redis/connection/memory.rb', line 147

def monitor; end

#move(key, destination_id) ⇒ Object

Raises:

  • (Redis::CommandError)


155
156
157
158
159
160
161
162
# File 'lib/redis/connection/memory.rb', line 155

def move key, destination_id
  raise Redis::CommandError, "ERR source and destination objects are the same" if destination_id == database_id
  destination = find_database(destination_id)
  return false unless data.has_key?(key)
  return false if destination.has_key?(key)
  destination[key] = data.delete(key)
  true
end

#mset(*pairs) ⇒ Object



636
637
638
639
640
641
642
643
# File 'lib/redis/connection/memory.rb', line 636

def mset(*pairs)
  # Handle pairs for mapped_mset command
  pairs = pairs[0] if mapped_param?(pairs)
  pairs.each_slice(2) do |pair|
    data[pair[0].to_s] = pair[1].to_s
  end
  "OK"
end

#msetnx(*pairs) ⇒ Object



645
646
647
648
649
650
651
652
653
# File 'lib/redis/connection/memory.rb', line 645

def msetnx(*pairs)
  # Handle pairs for mapped_msetnx command
  pairs = pairs[0] if mapped_param?(pairs)
  keys = []
  pairs.each_with_index{|item, index| keys << item.to_s if index % 2 == 0}
  return false if keys.any?{|key| data.key?(key) }
  mset(*pairs)
  true
end

#multiObject



699
700
701
702
703
# File 'lib/redis/connection/memory.rb', line 699

def multi
  self.buffer = []
  yield if block_given?
  "OK"
end

#persist(key) ⇒ Object



522
523
524
# File 'lib/redis/connection/memory.rb', line 522

def persist(key)
  !!data.expires.delete(key)
end

#pingObject



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

def ping
  "PONG"
end

#quitObject



689
# File 'lib/redis/connection/memory.rb', line 689

def quit ; end

#randomkeyObject



231
232
233
# File 'lib/redis/connection/memory.rb', line 231

def randomkey
  data.keys[rand(dbsize)]
end

#readObject



98
99
100
# File 'lib/redis/connection/memory.rb', line 98

def read
  replies.shift
end

#rename(key, new_key) ⇒ Object



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

def rename(key, new_key)
  return unless data[key]
  data[new_key] = data[key]
  data.expires[new_key] = data.expires[key] if data.expires.include?(key)
  data.delete(key)
end

#renamenx(key, new_key) ⇒ Object



494
495
496
497
498
499
500
501
# File 'lib/redis/connection/memory.rb', line 494

def renamenx(key, new_key)
  if exists(new_key)
    false
  else
    rename(key, new_key)
    true
  end
end

#rpop(key) ⇒ Object



343
344
345
346
347
# File 'lib/redis/connection/memory.rb', line 343

def rpop(key)
  data_type_check(key, Array)
  return unless data[key]
  data[key].pop
end

#rpoplpush(key1, key2) ⇒ Object



349
350
351
352
353
354
# File 'lib/redis/connection/memory.rb', line 349

def rpoplpush(key1, key2)
  data_type_check(key1, Array)
  rpop(key1).tap do |elem|
    lpush(key2, elem)
  end
end

#rpush(key, value) ⇒ Object



313
314
315
316
317
318
319
320
# File 'lib/redis/connection/memory.rb', line 313

def rpush(key, value)
  data_type_check(key, Array)
  data[key] ||= []
  [value].flatten.each do |val|
    data[key].push(val.to_s)
  end
  data[key].size
end

#rpushx(key, value) ⇒ Object



322
323
324
325
326
# File 'lib/redis/connection/memory.rb', line 322

def rpushx(key, value)
  data_type_check(key, Array)
  return unless data[key]
  rpush(key, value)
end

#sadd(key, value) ⇒ Object



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/redis/connection/memory.rb', line 374

def sadd(key, value)
  data_type_check(key, ::Set)
  value = Array(value)

  result = if data[key]
    old_set = data[key].dup
    data[key].merge(value.map(&:to_s))
    (data[key] - old_set).size
  else
    data[key] = ::Set.new(value.map(&:to_s))
    data[key].size
  end

  # 0 = false, 1 = true, 2+ untouched
  return result == 1 if result < 2
  result
end

#saveObject



149
# File 'lib/redis/connection/memory.rb', line 149

def save; end

#scard(key) ⇒ Object



413
414
415
416
417
# File 'lib/redis/connection/memory.rb', line 413

def scard(key)
  data_type_check(key, ::Set)
  return 0 unless data[key]
  data[key].size
end

#sdiff(key1, *keys) ⇒ Object



448
449
450
451
452
453
454
# File 'lib/redis/connection/memory.rb', line 448

def sdiff(key1, *keys)
  [key1, *keys].each { |k| data_type_check(k, ::Set) }
  keys = keys.map { |k| data[k] || ::Set.new }
  keys.inject(data[key1]) do |memo, set|
    memo - set
  end.to_a
end

#sdiffstore(destination, key1, *keys) ⇒ Object



456
457
458
459
460
# File 'lib/redis/connection/memory.rb', line 456

def sdiffstore(destination, key1, *keys)
  data_type_check(destination, ::Set)
  result = sdiff(key1, *keys)
  data[destination] = ::Set.new(result)
end

#select(index) ⇒ Object



126
127
128
129
130
# File 'lib/redis/connection/memory.rb', line 126

def select(index)
  data_type_check(index, Integer)
  self.database_id = index
  "OK"
end

#set(key, value) ⇒ Object



608
609
610
611
# File 'lib/redis/connection/memory.rb', line 608

def set(key, value)
  data[key] = value.to_s
  "OK"
end

#setbit(key, offset, bit) ⇒ Object



613
614
615
616
617
618
619
620
621
622
623
# File 'lib/redis/connection/memory.rb', line 613

def setbit(key, offset, bit)
  old_val = data[key] ? data[key].unpack('B*')[0].split("") : []
  size_increment = [((offset/8)+1)*8-old_val.length, 0].max
  old_val += Array.new(size_increment).map{"0"}
  original_val = old_val[offset]
  old_val[offset] = bit.to_s
  new_val = ""
  old_val.each_slice(8){|b| new_val = new_val + b.join("").to_i(2).chr }
  data[key] = new_val
  original_val
end

#setex(key, seconds, value) ⇒ Object



625
626
627
628
# File 'lib/redis/connection/memory.rb', line 625

def setex(key, seconds, value)
  data[key] = value.to_s
  expire(key, seconds)
end

#setnx(key, value) ⇒ Object



478
479
480
481
482
483
484
485
# File 'lib/redis/connection/memory.rb', line 478

def setnx(key, value)
  if exists(key)
    false
  else
    set(key, value)
    true
  end
end

#setrange(key, offset, value) ⇒ Object



630
631
632
633
634
# File 'lib/redis/connection/memory.rb', line 630

def setrange(key, offset, value)
  return unless data[key]
  s = data[key][offset,value.size]
  data[key][s] = value
end

#shutdownObject



691
# File 'lib/redis/connection/memory.rb', line 691

def shutdown; end

#sinter(*keys) ⇒ Object



419
420
421
422
423
424
425
426
# File 'lib/redis/connection/memory.rb', line 419

def sinter(*keys)
  keys.each { |k| data_type_check(k, ::Set) }
  return ::Set.new if keys.any? { |k| data[k].nil? }
  keys = keys.map { |k| data[k] || ::Set.new }
  keys.inject do |set, key|
    set & key
  end.to_a
end

#sinterstore(destination, *keys) ⇒ Object



428
429
430
431
432
# File 'lib/redis/connection/memory.rb', line 428

def sinterstore(destination, *keys)
  data_type_check(destination, ::Set)
  result = sinter(*keys)
  data[destination] = ::Set.new(result)
end

#sismember(key, value) ⇒ Object



368
369
370
371
372
# File 'lib/redis/connection/memory.rb', line 368

def sismember(key, value)
  data_type_check(key, ::Set)
  return false unless data[key]
  data[key].include?(value.to_s)
end

#slaveof(host, port) ⇒ Object



693
# File 'lib/redis/connection/memory.rb', line 693

def slaveof(host, port) ; end

#smembers(key) ⇒ Object



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

def smembers(key)
  data_type_check(key, ::Set)
  return [] unless data[key]
  data[key].to_a.reverse
end

#smove(source, destination, value) ⇒ Object



399
400
401
402
403
404
# File 'lib/redis/connection/memory.rb', line 399

def smove(source, destination, value)
  data_type_check(destination, ::Set)
  result = self.srem(source, value)
  self.sadd(destination, value) if result
  result
end

#sort(key) ⇒ Object



655
656
657
# File 'lib/redis/connection/memory.rb', line 655

def sort(key)
  # TODO: Implement
end

#spop(key) ⇒ Object



406
407
408
409
410
411
# File 'lib/redis/connection/memory.rb', line 406

def spop(key)
  data_type_check(key, ::Set)
  elem = srandmember(key)
  srem(key, elem)
  elem
end

#srandmember(key) ⇒ Object



462
463
464
465
466
# File 'lib/redis/connection/memory.rb', line 462

def srandmember(key)
  data_type_check(key, ::Set)
  return nil unless data[key]
  data[key].to_a[rand(data[key].size)]
end

#srem(key, value) ⇒ Object



392
393
394
395
396
397
# File 'lib/redis/connection/memory.rb', line 392

def srem(key, value)
  data_type_check(key, ::Set)
  deleted = !!(data[key] && data[key].delete?(value.to_s))
  remove_key_for_empty_collection(key)
  deleted
end

#strlen(key) ⇒ Object



199
200
201
202
# File 'lib/redis/connection/memory.rb', line 199

def strlen(key)
  return unless data[key]
  data[key].size
end

#sunion(*keys) ⇒ Object



434
435
436
437
438
439
440
# File 'lib/redis/connection/memory.rb', line 434

def sunion(*keys)
  keys.each { |k| data_type_check(k, ::Set) }
  keys = keys.map { |k| data[k] || ::Set.new }
  keys.inject(::Set.new) do |set, key|
    set | key
  end.to_a
end

#sunionstore(destination, *keys) ⇒ Object



442
443
444
445
446
# File 'lib/redis/connection/memory.rb', line 442

def sunionstore(destination, *keys)
  data_type_check(destination, ::Set)
  result = sunion(*keys)
  data[destination] = ::Set.new(result)
end

#syncObject



598
# File 'lib/redis/connection/memory.rb', line 598

def sync ; end

#timeout=(usecs) ⇒ Object



76
77
# File 'lib/redis/connection/memory.rb', line 76

def timeout=(usecs)
end

#ttl(key) ⇒ Object



509
510
511
512
513
514
515
# File 'lib/redis/connection/memory.rb', line 509

def ttl(key)
  if data.expires.include?(key) && (ttl = data.expires[key].to_i - Time.now.to_i) > 0
    ttl
  else
    -1
  end
end

#type(key) ⇒ Object



679
680
681
682
683
684
685
686
687
# File 'lib/redis/connection/memory.rb', line 679

def type(key)
  case data[key]
    when nil then "none"
    when String then "string"
    when Hash then "hash"
    when Array then "list"
    when ::Set then "set"
  end
end

#unwatchObject



709
710
711
# File 'lib/redis/connection/memory.rb', line 709

def unwatch
  "OK"
end

#watch(_) ⇒ Object



705
706
707
# File 'lib/redis/connection/memory.rb', line 705

def watch(_)
  "OK"
end

#write(command) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/redis/connection/memory.rb', line 79

def write(command)
  meffod = command.shift
  if respond_to?(meffod)
    reply = send(meffod, *command)
  else
    raise Redis::CommandError, "ERR unknown command '#{meffod}'"
  end

  if reply == true
    reply = 1
  elsif reply == false
    reply = 0
  end

  replies << reply
  buffer << reply if buffer && meffod != :multi
  nil
end

#zadd(key, *args) ⇒ Object



713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
# File 'lib/redis/connection/memory.rb', line 713

def zadd(key, *args)
  if !args.first.is_a?(Array)
    if args.size < 2
      raise Redis::CommandError, "ERR wrong number of arguments for 'zadd' command"
    elsif args.size.odd?
      raise Redis::CommandError, "ERR syntax error"
    end
  else
    unless args.all? {|pair| pair.size == 2 }
      raise(Redis::CommandError, "ERR syntax error")
    end
  end

  data_type_check(key, ZSet)
  data[key] ||= ZSet.new

  if args.size == 2
    score, value = args
    exists = !data[key].key?(value.to_s)
    data[key][value.to_s] = score
  else
    # Turn [1, 2, 3, 4] into [[1, 2], [3, 4]] unless it is already
    args = args.each_slice(2).to_a unless args.first.is_a?(Array)
    exists = args.map(&:last).map { |el| data[key].key?(el.to_s) }.count(false)
    args.each { |s, v| data[key][v.to_s] = s }
  end

  exists
end

#zcard(key) ⇒ Object



756
757
758
759
# File 'lib/redis/connection/memory.rb', line 756

def zcard(key)
  data_type_check(key, ZSet)
  data[key] ? data[key].size : 0
end

#zcount(key, min, max) ⇒ Object



767
768
769
770
771
# File 'lib/redis/connection/memory.rb', line 767

def zcount(key, min, max)
  data_type_check(key, ZSet)
  return 0 unless data[key]
  data[key].select_by_score(min, max).size
end

#zincrby(key, num, value) ⇒ Object



773
774
775
776
777
778
779
# File 'lib/redis/connection/memory.rb', line 773

def zincrby(key, num, value)
  data_type_check(key, ZSet)
  data[key] ||= ZSet.new
  data[key][value.to_s] ||= 0
  data[key].increment(value.to_s, num)
  data[key][value.to_s].to_s
end

#zinterstore(out, *args) ⇒ Object



862
863
864
865
866
867
# File 'lib/redis/connection/memory.rb', line 862

def zinterstore(out, *args)
  data_type_check(out, ZSet)
  args_handler = SortedSetArgumentHandler.new(args)
  data[out] = SortedSetIntersectStore.new(args_handler, data).call
  data[out].size
end

#zrange(key, start, stop, with_scores = nil) ⇒ Object



791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
# File 'lib/redis/connection/memory.rb', line 791

def zrange(key, start, stop, with_scores = nil)
  data_type_check(key, ZSet)
  return [] unless data[key]

  # Sort by score, or if scores are equal, key alphanum
  results = data[key].sort do |(k1, v1), (k2, v2)|
    if v1 == v2
      k1 <=> k2
    else
      v1 <=> v2
    end
  end
  # Select just the keys unless we want scores
  results = results.map(&:first) unless with_scores
  results[start..stop].flatten.map(&:to_s)
end

#zrangebyscore(key, min, max, *opts) ⇒ Object



819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
# File 'lib/redis/connection/memory.rb', line 819

def zrangebyscore(key, min, max, *opts)
  data_type_check(key, ZSet)
  return [] unless data[key]

  range = data[key].select_by_score(min, max)
  vals = if opts.include?('WITHSCORES')
    range.sort_by {|_,v| v }
  else
    range.keys.sort_by {|k| range[k] }
  end

  limit = get_limit(opts, vals)
  vals = vals[*limit] if limit

  vals.flatten.map(&:to_s)
end

#zrank(key, value) ⇒ Object



781
782
783
784
# File 'lib/redis/connection/memory.rb', line 781

def zrank(key, value)
  data_type_check(key, ZSet)
  data[key].keys.sort_by {|k| data[key][k] }.index(value.to_s)
end

#zrem(key, value) ⇒ Object



743
744
745
746
747
748
749
750
751
752
753
754
# File 'lib/redis/connection/memory.rb', line 743

def zrem(key, value)
  data_type_check(key, ZSet)
  values = Array(value)
  return 0 unless data[key]

  response = values.map do |v|
    data[key].delete(v) if data[key].has_key?(v)
  end.compact.size

  remove_key_for_empty_collection(key)
  response
end

#zremrangebyrank(key, start, stop) ⇒ Object



876
877
878
879
880
881
882
# File 'lib/redis/connection/memory.rb', line 876

def zremrangebyrank(key, start, stop)
  sorted_elements = data[key].sort_by { |k, v| v }
  start = sorted_elements.length if start > sorted_elements.length
  elements_to_delete = sorted_elements[start..stop]
  elements_to_delete.each { |elem, rank| data[key].delete(elem) }
  elements_to_delete.size
end

#zremrangebyscore(key, min, max) ⇒ Object



853
854
855
856
857
858
859
860
# File 'lib/redis/connection/memory.rb', line 853

def zremrangebyscore(key, min, max)
  data_type_check(key, ZSet)
  return 0 unless data[key]

  range = data[key].select_by_score(min, max)
  range.each {|k,_| data[key].delete(k) }
  range.size
end

#zrevrange(key, start, stop, with_scores = nil) ⇒ Object



808
809
810
811
812
813
814
815
816
817
# File 'lib/redis/connection/memory.rb', line 808

def zrevrange(key, start, stop, with_scores = nil)
  data_type_check(key, ZSet)
  return [] unless data[key]

  if with_scores
    data[key].sort_by {|_,v| -v }
  else
    data[key].keys.sort_by {|k| -data[key][k] }
  end[start..stop].flatten.map(&:to_s)
end

#zrevrangebyscore(key, max, min, *opts) ⇒ Object



836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
# File 'lib/redis/connection/memory.rb', line 836

def zrevrangebyscore(key, max, min, *opts)
  data_type_check(key, ZSet)
  return [] unless data[key]

  range = data[key].select_by_score(min, max)
  vals = if opts.include?('WITHSCORES')
    range.sort_by {|_,v| -v }
  else
    range.keys.sort_by {|k| -range[k] }
  end

  limit = get_limit(opts, vals)
  vals = vals[*limit] if limit

  vals.flatten.map(&:to_s)
end

#zrevrank(key, value) ⇒ Object



786
787
788
789
# File 'lib/redis/connection/memory.rb', line 786

def zrevrank(key, value)
  data_type_check(key, ZSet)
  data[key].keys.sort_by {|k| -data[key][k] }.index(value.to_s)
end

#zscore(key, value) ⇒ Object



761
762
763
764
765
# File 'lib/redis/connection/memory.rb', line 761

def zscore(key, value)
  data_type_check(key, ZSet)
  value = data[key] && data[key][value.to_s]
  value && value.to_s
end

#zunionstore(out, *args) ⇒ Object



869
870
871
872
873
874
# File 'lib/redis/connection/memory.rb', line 869

def zunionstore(out, *args)
  data_type_check(out, ZSet)
  args_handler = SortedSetArgumentHandler.new(args)
  data[out] = SortedSetUnionStore.new(args_handler, data).call
  data[out].size
end