lib/redis/connection/memory.rb in kuende-fakeredis-0.6.0 vs lib/redis/connection/memory.rb in kuende-fakeredis-0.10.0

- old
+ new

@@ -7,11 +7,10 @@ require "fakeredis/sorted_set_argument_handler" require "fakeredis/sorted_set_store" require "fakeredis/transaction_commands" require "fakeredis/zset" require "fakeredis/bitop_command" -require "fakeredis/version" class Redis module Connection class Memory include Redis::Connection::CommandHelper @@ -88,10 +87,19 @@ end def disconnect end + def client(command, options = {}) + case command + when :setname then true + when :getname then nil + else + raise Redis::CommandError, "ERR unknown command '#{command}'" + end + end + def timeout=(usecs) end def read replies.shift @@ -345,11 +353,18 @@ data[key].size end def lrange(key, startidx, endidx) data_type_check(key, Array) - (data[key] && data[key][startidx..endidx]) || [] + if data[key] + # In Ruby when negative start index is out of range Array#slice returns + # nil which is not the case for lrange in Redis. + startidx = 0 if startidx < 0 && startidx.abs > data[key].size + data[key][startidx..endidx] || [] + else + [] + end end def ltrim(key, start, stop) data_type_check(key, Array) return unless data[key] @@ -378,13 +393,13 @@ value = value.to_s index = data[key].index(pivot.to_s) return -1 if index.nil? - case where - when :before then data[key].insert(index, value) - when :after then data[key].insert(index + 1, value) + case where.to_s + when /\Abefore\z/i then data[key].insert(index, value) + when /\Aafter\z/i then data[key].insert(index + 1, value) else raise_syntax_error end end def lset(key, index, value) @@ -551,15 +566,18 @@ result = self.srem(source, value) self.sadd(destination, value) if result result end - def spop(key) + def spop(key, count = nil) data_type_check(key, ::Set) - elem = srandmember(key) - srem(key, elem) - elem + results = (count || 1).times.map do + elem = srandmember(key) + srem(key, elem) + elem + end.compact + count.nil? ? results.first : results end def scard(key) data_type_check(key, ::Set) return 0 unless data[key] @@ -618,10 +636,48 @@ def srandmember(key, number=nil) number.nil? ? srandmember_single(key) : srandmember_multiple(key, number) end + def sscan(key, start_cursor, *args) + data_type_check(key, ::Set) + return ["0", []] unless data[key] + + match = "*" + count = 10 + + if args.size.odd? + raise_argument_error('sscan') + end + + if idx = args.index("MATCH") + match = args[idx + 1] + end + + if idx = args.index("COUNT") + count = args[idx + 1] + end + + start_cursor = start_cursor.to_i + + cursor = start_cursor + next_keys = [] + + if start_cursor + count >= data[key].length + next_keys = (data[key].to_a)[start_cursor..-1] + cursor = 0 + else + cursor = start_cursor + count + next_keys = (data[key].to_a)[start_cursor..cursor-1] + end + + filtered_next_keys = next_keys.select{ |k,v| File.fnmatch(match, k)} + result = filtered_next_keys.flatten.map(&:to_s) + + return ["#{cursor}", result] + end + def del(*keys) keys = keys.flatten(1) raise_argument_error('del') if keys.empty? old_count = data.keys.size @@ -733,10 +789,11 @@ else fields.each_slice(2) do |field| data[key][field[0].to_s] = field[1].to_s end end + "OK" end def hmget(key, *fields) raise_argument_error('hmget') if fields.empty? @@ -912,37 +969,38 @@ def scan(start_cursor, *args) match = "*" count = 10 - if args.size.odd? - raise_argument_error('scan') - end - if idx = args.index("MATCH") match = args[idx + 1] end if idx = args.index("COUNT") count = args[idx + 1] end start_cursor = start_cursor.to_i - data_type_check(start_cursor, Fixnum) + data_type_check(start_cursor, Integer) cursor = start_cursor - next_keys = [] + returned_keys = [] + final_page = start_cursor + count >= keys(match).length - if start_cursor + count >= data.length - next_keys = keys(match)[start_cursor..-1] + if final_page + previous_keys_been_deleted = (count >= keys(match).length) + start_index = previous_keys_been_deleted ? 0 : cursor + + returned_keys = keys(match)[start_index..-1] cursor = 0 else - cursor = start_cursor + 10 - next_keys = keys(match)[start_cursor..cursor] + end_index = start_cursor + (count - 1) + returned_keys = keys(match)[start_cursor..end_index] + cursor = start_cursor + count end - return "#{cursor}", next_keys + return "#{cursor}", returned_keys end def zadd(key, *args) if !args.first.is_a?(Array) if args.size < 2 @@ -1030,11 +1088,11 @@ return [] unless data[key] results = sort_keys(data[key]) # Select just the keys unless we want scores results = results.map(&:first) unless with_scores - results[start..stop].flatten.map(&:to_s) + (results[start..stop] || []).flatten.map(&:to_s) end def zrangebylex(key, start, stop, *opts) data_type_check(key, ZSet) return [] unless data[key] @@ -1239,11 +1297,11 @@ if idx = args.index("COUNT") count = args[idx + 1] end start_cursor = start_cursor.to_i - data_type_check(start_cursor, Fixnum) + data_type_check(start_cursor, Integer) cursor = start_cursor next_keys = [] sorted_keys = sort_keys(data[key]) @@ -1370,6 +1428,7 @@ end end end end +# FIXME this line should be deleted as explicit enabling is better Redis::Connection.drivers << Redis::Connection::Memory