Class: MockRedis::Database

Inherits:
Object
  • Object
show all
Includes:
ConnectionMethod, GeospatialMethods, HashMethods, InfoMethod, ListMethods, SetMethods, SortMethod, StreamMethods, StringMethods, UtilityMethods, ZsetMethods
Defined in:
lib/mock_redis/database.rb

Constant Summary

Constants included from GeospatialMethods

GeospatialMethods::D_R, GeospatialMethods::EARTH_RADIUS_IN_METERS, GeospatialMethods::LAT_RANGE, GeospatialMethods::LNG_RANGE, GeospatialMethods::STEP, GeospatialMethods::UNITS

Constants included from InfoMethod

InfoMethod::ALL_INFO, InfoMethod::CLIENTS_INFO, InfoMethod::COMMAND_STATS_COMBINED_INFO, InfoMethod::COMMAND_STATS_SOLO_INFO, InfoMethod::CPU_INFO, InfoMethod::DEFAULT_INFO, InfoMethod::KEYSPACE_INFO, InfoMethod::MEMORY_INFO, InfoMethod::PERSISTENCE_INFO, InfoMethod::REPLICATION_INFO, InfoMethod::SERVER_INFO, InfoMethod::STATS_INFO

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ConnectionMethod

#connection

Methods included from StreamMethods

#xadd, #xlen, #xrange, #xread, #xrevrange, #xtrim

Methods included from GeospatialMethods

#geodist, #geohash, #geopos

Methods included from InfoMethod

#info

Methods included from SortMethod

#sort

Methods included from ZsetMethods

#zadd, #zcard, #zcount, #zincrby, #zinterstore, #zpopmax, #zpopmin, #zrange, #zrangebyscore, #zrank, #zrem, #zremrangebyrank, #zremrangebyscore, #zrevrange, #zrevrangebyscore, #zrevrank, #zscan, #zscan_each, #zscore, #zunionstore

Methods included from StringMethods

#append, #bitcount, #bitfield, #decr, #decrby, #get, #getbit, #getrange, #getset, #incr, #incrby, #incrbyfloat, #mapped_mget, #mapped_mset, #mapped_msetnx, #mget, #mset, #msetnx, #set, #setbit, #setex, #setnx, #setrange, #strlen

Methods included from SetMethods

#sadd, #scard, #sdiff, #sdiffstore, #sinter, #sinterstore, #sismember, #smembers, #smove, #spop, #srandmember, #srem, #sscan, #sscan_each, #sunion, #sunionstore

Methods included from ListMethods

#blpop, #brpop, #brpoplpush, #lindex, #linsert, #llen, #lpop, #lpush, #lpushx, #lrange, #lrem, #lset, #ltrim, #rpop, #rpoplpush, #rpush, #rpushx

Methods included from HashMethods

#hdel, #hexists, #hget, #hgetall, #hincrby, #hincrbyfloat, #hkeys, #hlen, #hmget, #hmset, #hscan, #hscan_each, #hset, #hsetnx, #hvals, #mapped_hmget, #mapped_hmset

Constructor Details

#initialize(base, *_args) ⇒ Database

Returns a new instance of Database.



32
33
34
35
36
# File 'lib/mock_redis/database.rb', line 32

def initialize(base, *_args)
  @base = base
  @data = MockRedis::IndifferentHash.new
  @expire_times = []
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



30
31
32
# File 'lib/mock_redis/database.rb', line 30

def data
  @data
end

#expire_timesObject (readonly)

Returns the value of attribute expire_times.



30
31
32
# File 'lib/mock_redis/database.rb', line 30

def expire_times
  @expire_times
end

Instance Method Details

#auth(_) ⇒ Object

Redis commands go below this line and above ‘private’



46
47
48
# File 'lib/mock_redis/database.rb', line 46

def auth(_)
  'OK'
end

#bgrewriteaofObject



50
51
52
# File 'lib/mock_redis/database.rb', line 50

def bgrewriteaof
  'Background append only file rewriting started'
end

#bgsaveObject



54
55
56
# File 'lib/mock_redis/database.rb', line 54

def bgsave
  'Background saving started'
end

#connected?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/mock_redis/database.rb', line 64

def connected?
  true
end

#dbsizeObject



68
69
70
# File 'lib/mock_redis/database.rb', line 68

def dbsize
  data.keys.length
end

#del(*keys) ⇒ Object Also known as: unlink



72
73
74
75
76
77
78
79
80
81
# File 'lib/mock_redis/database.rb', line 72

def del(*keys)
  keys = keys.flatten.map(&:to_s)
  assert_has_args(keys, 'del')

  keys.
    find_all { |key| data[key] }.
    each { |k| persist(k) }.
    each { |k| data.delete(k) }.
    length
end

#disconnectObject Also known as: close



58
59
60
# File 'lib/mock_redis/database.rb', line 58

def disconnect
  nil
end

#dump(key) ⇒ Object



134
135
136
137
# File 'lib/mock_redis/database.rb', line 134

def dump(key)
  value = data[key]
  value ? Marshal.dump(value) : nil
end

#echo(msg) ⇒ Object



84
85
86
# File 'lib/mock_redis/database.rb', line 84

def echo(msg)
  msg.to_s
end

#eval(*args) ⇒ Object



279
# File 'lib/mock_redis/database.rb', line 279

def eval(*args); end

#evalsha(*args) ⇒ Object



277
# File 'lib/mock_redis/database.rb', line 277

def evalsha(*args); end

#exists(*keys) ⇒ Object



120
121
122
# File 'lib/mock_redis/database.rb', line 120

def exists(*keys)
  keys.count { |key| data.key?(key) }
end

#exists?(*keys) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
127
# File 'lib/mock_redis/database.rb', line 124

def exists?(*keys)
  keys.each { |key| return true if data.key?(key) }
  false
end

#expire(key, seconds) ⇒ Object



88
89
90
# File 'lib/mock_redis/database.rb', line 88

def expire(key, seconds)
  pexpire(key, seconds.to_i * 1000)
end

#expire_keysObject

This method isn’t private, but it also isn’t a Redis command, so it doesn’t belong up above with all the Redis commands.



360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/mock_redis/database.rb', line 360

def expire_keys
  now_sec, miliseconds = now
  now_ms = now_sec * 1_000 + miliseconds

  to_delete = expire_times.take_while do |(time, _key)|
    (time.to_r * 1_000).to_i <= now_ms
  end

  to_delete.each do |(_time, key)|
    del(key)
  end
end

#expireat(key, timestamp) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/mock_redis/database.rb', line 98

def expireat(key, timestamp)
  unless looks_like_integer?(timestamp.to_s)
    raise Redis::CommandError, 'ERR value is not an integer or out of range'
  end

  pexpireat(key, timestamp.to_i * 1000)
end

#flushdbObject



129
130
131
132
# File 'lib/mock_redis/database.rb', line 129

def flushdb
  data.each_key { |k| del(k) }
  'OK'
end

#initialize_copy(_source) ⇒ Object



38
39
40
41
42
# File 'lib/mock_redis/database.rb', line 38

def initialize_copy(_source)
  @data = @data.clone
  @data.each_key { |k| @data[k] = @data[k].clone }
  @expire_times = @expire_times.map(&:clone)
end

#keys(format = '*') ⇒ Object



150
151
152
# File 'lib/mock_redis/database.rb', line 150

def keys(format = '*')
  data.keys.grep(redis_pattern_to_ruby_regex(format))
end

#lastsaveObject



168
169
170
# File 'lib/mock_redis/database.rb', line 168

def lastsave
  now.first
end

#nowObject Also known as: time



250
251
252
253
254
# File 'lib/mock_redis/database.rb', line 250

def now
  current_time = @base.options[:time_class].now
  miliseconds = (current_time.to_r - current_time.to_i) * 1_000
  [current_time.to_i, miliseconds.to_i]
end

#persist(key) ⇒ Object



172
173
174
175
176
177
178
179
# File 'lib/mock_redis/database.rb', line 172

def persist(key)
  if exists?(key) && has_expiration?(key)
    remove_expiration(key)
    true
  else
    false
  end
end

#pexpire(key, ms) ⇒ Object



92
93
94
95
96
# File 'lib/mock_redis/database.rb', line 92

def pexpire(key, ms)
  now, miliseconds = @base.now
  now_ms = (now * 1000) + miliseconds
  pexpireat(key, now_ms + ms.to_i)
end

#pexpireat(key, timestamp_ms) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/mock_redis/database.rb', line 106

def pexpireat(key, timestamp_ms)
  unless looks_like_integer?(timestamp_ms.to_s)
    raise Redis::CommandError, 'ERR value is not an integer or out of range'
  end

  if exists?(key)
    timestamp = Rational(timestamp_ms.to_i, 1000)
    set_expiration(key, @base.time_at(timestamp))
    true
  else
    false
  end
end

#pingObject



181
182
183
# File 'lib/mock_redis/database.rb', line 181

def ping
  'PONG'
end

#pttl(key) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/mock_redis/database.rb', line 237

def pttl(key)
  now, miliseconds = @base.now
  now_ms = now * 1000 + miliseconds

  if !exists?(key)
    -2
  elsif has_expiration?(key)
    (expiration(key).to_r * 1000).to_i - now_ms
  else
    -1
  end
end

#quitObject



185
186
187
# File 'lib/mock_redis/database.rb', line 185

def quit
  'OK'
end

#randomkeyObject



189
190
191
# File 'lib/mock_redis/database.rb', line 189

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

#rename(key, newkey) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/mock_redis/database.rb', line 193

def rename(key, newkey)
  unless data.include?(key)
    raise Redis::CommandError, 'ERR no such key'
  end

  if key != newkey
    data[newkey] = data.delete(key)
    if has_expiration?(key)
      set_expiration(newkey, expiration(key))
      remove_expiration(key)
    end
  end

  'OK'
end

#renamenx(key, newkey) ⇒ Object



209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/mock_redis/database.rb', line 209

def renamenx(key, newkey)
  unless data.include?(key)
    raise Redis::CommandError, 'ERR no such key'
  end

  if exists?(newkey)
    false
  else
    rename(key, newkey)
    true
  end
end

#restore(key, ttl, value, replace: false) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/mock_redis/database.rb', line 139

def restore(key, ttl, value, replace: false)
  if !replace && exists?(key)
    raise Redis::CommandError, 'BUSYKEY Target key name already exists.'
  end
  data[key] = Marshal.load(value) # rubocop:disable Security/MarshalLoad
  if ttl > 0
    pexpire(key, ttl)
  end
  'OK'
end

#saveObject



222
223
224
# File 'lib/mock_redis/database.rb', line 222

def save
  'OK'
end

#scan(cursor, opts = {}) ⇒ Object



154
155
156
# File 'lib/mock_redis/database.rb', line 154

def scan(cursor, opts = {})
  common_scan(data.keys, cursor, opts)
end

#scan_each(opts = {}, &block) ⇒ Object



158
159
160
161
162
163
164
165
166
# File 'lib/mock_redis/database.rb', line 158

def scan_each(opts = {}, &block)
  return to_enum(:scan_each, opts) unless block_given?
  cursor = 0
  loop do
    cursor, keys = scan(cursor, opts)
    keys.each(&block)
    break if cursor == '0'
  end
end

#script(subcommand, *args) ⇒ Object



275
# File 'lib/mock_redis/database.rb', line 275

def script(subcommand, *args); end

#ttl(key) ⇒ Object



226
227
228
229
230
231
232
233
234
235
# File 'lib/mock_redis/database.rb', line 226

def ttl(key)
  if !exists?(key)
    -2
  elsif has_expiration?(key)
    now, = @base.now
    expiration(key).to_i - now
  else
    -1
  end
end

#type(key) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/mock_redis/database.rb', line 257

def type(key)
  if !exists?(key)
    'none'
  elsif hashy?(key)
    'hash'
  elsif stringy?(key)
    'string'
  elsif listy?(key)
    'list'
  elsif sety?(key)
    'set'
  elsif zsety?(key)
    'zset'
  else
    raise ArgumentError, "Not sure how #{data[key].inspect} got in here"
  end
end