class Redi2casa
Constants
- VERSION
Public Class Methods
new(hosts, keyspace)
click to toggle source
# File lib/redi2casa.rb, line 7 def initialize(hosts, keyspace) @hosts = hosts @keyspace = keyspace connect end
Public Instance Methods
clear_bits(key)
click to toggle source
# File lib/redi2casa/clear_bits.rb, line 2 def clear_bits key del(key, "hash") end
Also aliased as: clearbits
connect()
click to toggle source
# File lib/redi2casa.rb, line 13 def connect @db_conn = Cql::Client.connect(:hosts => @hosts) @db_conn.use(@keyspace) end
Also aliased as: reconnect
del(key, type)
click to toggle source
Type can be sets, hashes, lists, keyvalue
# File lib/redi2casa/del.rb, line 3 def del key, type if type == "counter" raise RuntimeError.new("deleting counters is not supported") elsif type == 'keyvalue' execute("delete from keyvalue where key = ?", key.to_s) elsif type == 'hash' execute("delete from hashes where key = ?", key.to_s) elsif type == 'list' execute("delete from lists where namespace = ?", key.to_s) elsif type == 'set' execute("delete from sets where key = ?", key.to_s) elsif type == 'sorted_set' execute("delete from sorted_sets where key = ?", key.to_s) else raise RuntimeError.new("Invalid type") end end
execute(base_query, *args)
click to toggle source
# File lib/redi2casa.rb, line 24 def execute base_query, *args @failed ||= 0 statement = @db_conn.prepare(base_query) statement.execute(*args) rescue Cql::NotConnectedError, Cql::Io::ConnectionError, Cql::Io::ConnectionTimeoutError reconnect @failed += 1 retry if @failed < 3 raise rescue Cql::QueryError => e if e.message =~ /Operation timed out/i @failed += 1 retry if @failed < 3 raise end raise Redi2casaError.new("Cql::QueryError query:#{base_query}, args: #{args.inspect}, exception: #{e.inspect}") rescue ThreadError => e if e.message =~ /Attempt to unlock a mutex/i @failed += 1 retry if @failed < 3 raise end raise ensure @failed = 0 end
get(key, type = 'keyvalue')
click to toggle source
# File lib/redi2casa/get.rb, line 2 def get key, type = 'keyvalue' if type == 'keyvalue' resp = execute("select * from keyvalue where key = ?", key.to_s) parse_response(resp, "value") elsif type == 'counter' # @ is a special column in counter used by incrby resp = execute("select value from counters where KEY = ? and column1 = '@'", key.to_s) parse_response(resp, "value").to_i end end
get_bit(key, offset)
click to toggle source
# File lib/redi2casa/get_bit.rb, line 2 def get_bit key, offset hget("#{key}", "#{offset}", "hash").to_i end
Also aliased as: getbit
hdel(key, column1, type = "counter")
click to toggle source
# File lib/redi2casa/hdel.rb, line 2 def hdel key, column1, type = "counter" if type == "counter" raise RuntimeError.new("deleting counters is not supported") elsif type == "hash" execute("delete from hashes where key = ? and column1 = ?", key.to_s, column1.to_s) end end
hget(key, column1, type = "counter")
click to toggle source
# File lib/redi2casa/hget.rb, line 2 def hget key, column1, type = "counter" if type.to_s == "hash" resp = execute("select value from hashes where key = ? and column1 = ?", key.to_s, column1.to_s) parse_response(resp, "value") elsif type.to_s == "counter" resp = execute("select value from counters where key = ? and column1 = ?", key.to_s, column1.to_s) parse_response(resp, "value").to_i end end
hgetall(key, type = "counter")
click to toggle source
# File lib/redi2casa/hgetall.rb, line 2 def hgetall key, type = "counter" if type.to_s == "counter" response = execute("select * from counters where KEY = ?", key.to_s) response.inject({}) {|hsh, entry| hsh[entry["column1"]] = entry["value"]; hsh} elsif type.to_s == "hash" response = execute("select * from hashes where KEY = ?", key.to_s) response.inject({}) {|hsh, entry| hsh[entry["column1"]] = entry["value"]; hsh} end end
hincrby(key, column1, value = 1)
click to toggle source
# File lib/redi2casa/hincrby.rb, line 2 def hincrby key, column1, value = 1 value = value.to_i execute("update counters set value = value + ? where key = ? and column1 = ?", value, key.to_s, column1.to_s) end
hkeys(key, type = "counter")
click to toggle source
# File lib/redi2casa/hkeys.rb, line 2 def hkeys key, type = "counter" if type.to_s == "counter" response = execute("select column1 from counters where key = ?", key.to_s) elsif type.to_s == "hash" response = execute("select column1 from hashes where key = ?", key.to_s) else raise RuntimeError.new("Invalid type") end response.collect {|entry| entry["column1"]} end
hlen(key, type = "hash")
click to toggle source
Supports only hashes now
# File lib/redi2casa/hlen.rb, line 3 def hlen key, type = "hash" if type == "hash" response = execute("select count(*) from hashes where key = ?", key.to_s) elsif type == "counter" response = execute("select count(*) from counters where key = ?", key.to_s) else raise RuntimeError.new("Invalid type") end parse_response(response, "count").to_i end
hmget(key, type, *column1s)
click to toggle source
# File lib/redi2casa/hmget.rb, line 2 def hmget key, type, *column1s column1s.flatten! column1s.collect! { |column1| column1.to_s } if type == "counter" table = "counters" elsif type == "hash" table = "hashes" else raise RuntimeError.new("invalid table") end resp = execute("select column1, value from #{table} where key = ? and column1 IN ?", key.to_s, column1s) hash = {} resp.each do |r| hash[r["column1"]] = r["value"] end result = [] column1s.each do |column1| result << hash[column1.to_s] end result end
hset(key, column1, value)
click to toggle source
# File lib/redi2casa/hset.rb, line 2 def hset key, column1, value execute("UPDATE hashes SET value = ? WHERE column1 = ? and key = ?", value.to_s, column1.to_s, key.to_s) end
incrby(key, value = 1)
click to toggle source
# File lib/redi2casa/incrby.rb, line 2 def incrby key, value = 1 hincrby key, '@', value end
Also aliased as: incr
keys(pattern, type)
click to toggle source
# File lib/redi2casa/keys.rb, line 2 def keys pattern, type end
lflush(namespace)
click to toggle source
# File lib/redi2casa/ltrim.rb, line 19 def lflush namespace execute("UPDATE lists SET values = [] WHERE namespace = ?", namespace.to_s) end
llen(namespace)
click to toggle source
# File lib/redi2casa/llen.rb, line 2 def llen namespace lrange(namespace, 0, -1).size end
lpop(namespace)
click to toggle source
has a read modify write problem
# File lib/redi2casa/lpop.rb, line 3 def lpop namespace resp = execute("select values from lists where namespace = ?", namespace.to_s) values = [] resp.each {|entry| values = entry.to_hash["values"]} if values resp = values.shift lrepush(namespace, values) else resp = values end resp end
lpush(namespace, data)
click to toggle source
# File lib/redi2casa/lpush.rb, line 2 def lpush namespace, data execute("UPDATE lists SET values = ? + values WHERE namespace = ?", [ data.to_s], namespace.to_s) end
lrange(namespace, first, last)
click to toggle source
# File lib/redi2casa/lrange.rb, line 2 def lrange namespace, first, last resp = execute("select values from lists where namespace = ?", namespace.to_s) resp.each {|entry| values = entry.to_hash["values"] || [] return values[first..last] } end
lrem(namespace, count, value)
click to toggle source
# File lib/redi2casa/lrem.rb, line 2 def lrem namespace, count, value elements = lrange(namespace, 0, -1) if count == 0 delete_positions = [] elements.delete(value) elsif count < 0 count = count * -1 delete_positions = [] (elements.length - 1).downto(0) do |i| if elements[i] == value && count > 0 delete_positions << i count -= 1 end end elsif count > 0 delete_positions = [] elements.each_index do |i| if elements[i] == value && count > 0 delete_positions << i count -= 1 end end end delete_positions.sort! delete_positions.reverse! puts delete_positions.inspect delete_positions.each do |pos| elements.delete_at(pos) end lrepush(namespace, elements) end
ltrim(namespace, first, last)
click to toggle source
# File lib/redi2casa/ltrim.rb, line 2 def ltrim namespace, first, last resp = execute("select values from lists where namespace = ?", namespace.to_s) values = {} resp.each {|entry| values = entry.to_hash["values"]} values_count = values.count #if first is greater than list length, redis returns empty list #if negative value of last is equal or greater than list length a similar behaviour is shown if (first > values_count) || (-last >= values_count) lflush(namespace) elsif last > values_count last = values_count else new_list = values[first..last] lrepush(namespace, new_list) end end
mget(keys, type = "keyvalue")
click to toggle source
# File lib/redi2casa/mget.rb, line 2 def mget keys, type = "keyvalue" values = keys.collect do |key| get(key, type) end end
parse_response(resp, key)
click to toggle source
# File lib/redi2casa.rb, line 20 def parse_response(resp, key) resp.map {|entry| entry[key].to_s }.first end
rpop(namespace)
click to toggle source
# File lib/redi2casa/rpop.rb, line 2 def rpop namespace resp = execute("select values from lists where namespace = ?", namespace.to_s) values = [] resp.fetch {|entry| values = entry.to_hash["values"]} resp = values.pop lrepush(namespace, values) resp end
rpush(namespace, data)
click to toggle source
# File lib/redi2casa/rpush.rb, line 2 def rpush namespace, data execute("UPDATE lists SET values = values + ? WHERE namespace = ?", [ data.to_s], namespace.to_s) end
sadd(key, *members)
click to toggle source
# File lib/redi2casa/sadd.rb, line 2 def sadd key, *members members.flatten! members.collect! { |member| member.to_s } execute("update sets set members = members + ? where key = ?", members, key.to_s) end
sadd_with_expire( key, ttl, *members)
click to toggle source
# File lib/redi2casa/sadd_with_expire.rb, line 2 def sadd_with_expire( key, ttl, *members) members.flatten! members.collect! { |member| member.to_s } execute("update sets using ttl ? set members = members + ? where key = ?", ttl, members, key.to_s) end
scard(key)
click to toggle source
# File lib/redi2casa/scard.rb, line 2 def scard key smembers(key).size end
set(key, value)
click to toggle source
# File lib/redi2casa/set.rb, line 2 def set key, value execute("UPDATE keyvalue set value = ? where key = ?", value.to_s, key.to_s) end
set_bit(key, offset, bit)
click to toggle source
FIXME:This could potentially lead to read write problem.
# File lib/redi2casa/set_bit.rb, line 3 def set_bit key, offset, bit if !(bit != 0 || bit != 1) raise RuntimeError.new("Invalid bit") end hset("#{key}","#{offset}", bit.to_s) end
Also aliased as: setbit
setex(key, ttl, value)
click to toggle source
# File lib/redi2casa/setex.rb, line 2 def setex key, ttl, value execute("UPDATE keyvalue using TTL ? set value = ? where key = ?", ttl, value.to_s, key.to_s) end
sismember(key, value)
click to toggle source
# File lib/redi2casa/sismember.rb, line 2 def sismember key, value smembers(key).include?(value) end
smembers(key)
click to toggle source
# File lib/redi2casa/smembers.rb, line 2 def smembers key resp = execute("select * from sets where key = ?", key.to_s) if resp.first resp.first["members"].to_a else [] end end
spop(key)
click to toggle source
# File lib/redi2casa/spop.rb, line 2 def spop key members = smembers(key) if members srem key, members.first members.first end end
srem(key, member)
click to toggle source
# File lib/redi2casa/srem.rb, line 2 def srem key, member execute("update sets set members = members - {'#{member}'} where key = ?", key.to_s) end
zadd(key, score, value)
click to toggle source
Random text is an extra column added to make sure we have multiple entries with same key, score and value
# File lib/redi2casa/zadd.rb, line 3 def zadd key, score, value execute("insert into sorted_sets (key, score,value, random_text) values (?, ?, ?, ?)", key.to_s, score, value, Time.now.to_i.to_s) end
zrangebyscore(key, lower_limit, higher_limit = -1)
click to toggle source
Ranges are exclusive
# File lib/redi2casa/zrangebyscore.rb, line 3 def zrangebyscore key, lower_limit, higher_limit = -1 if higher_limit == -1 resp = execute("select value from sorted_sets where key = ? and score >= ?", key.to_s, lower_limit) else resp = execute("select value from sorted_sets where key = ? and score >= ? and score <= ?", key.to_s, lower_limit, higher_limit) end resp.collect do |entry| entry['value'] end end
zrem(key, member)
click to toggle source
# File lib/redi2casa/zrem.rb, line 2 def zrem key, member resp = execute("select * from sorted_sets where key = ?", key.to_s) resp.each do |entry| if entry['value'] == member.to_s execute("delete from sorted_sets where key = ? and score = ? and value = ?", key, entry['score'], entry['value']) end end end
zscore(key, value)
click to toggle source
# File lib/redi2casa/zscore.rb, line 2 def zscore key, value resp = execute("select * from sorted_sets where key = ?", key.to_s) resp.each do |entry| return entry['score'] if entry['value'] == value.to_s end nil end
Private Instance Methods
lrepush(namespace, list)
click to toggle source
# File lib/redi2casa/ltrim.rb, line 24 def lrepush namespace, list execute("UPDATE lists SET values = ? WHERE namespace = ?", list, namespace.to_s) end