module Porpoise::Set

Public Class Methods

sadd(key, *members) click to toggle source
# File lib/porpoise/set.rb, line 4
def sadd(key, *members)
  o = find_stored_object(key)
  previous_set = o.value.dup
  o.value = o.value.concat(members).uniq
  o.save

  o.value.size - previous_set.size
end
scard(key) click to toggle source
# File lib/porpoise/set.rb, line 13
def scard(key)
  o = find_stored_object(key)
  o.value.size
end
sdiff(key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 18
def sdiff(key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set = current_set - oo[ok].value
  end
  current_set
end
sdiffstore(destination, key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 31
def sdiffstore(destination, key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set = current_set - oo[ok].value
  end

  no = find_stored_object(destination)
  no.value = current_set
  no.save
  no.value.size
end
sinter(key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 48
def sinter(key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set = current_set & oo[ok].value
  end
  return current_set
end
sinterstore(destination, key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 61
def sinterstore(destination, key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set = current_set & oo[ok].value
  end

  no = find_stored_object(destination)
  no.value = current_set
  no.save
  no.value.size
end
sismember(key, member) click to toggle source
# File lib/porpoise/set.rb, line 78
def sismember(key, member)
  o = find_stored_object(key)
  return o.value.include?(member) ? 1 : 0
end
smembers(key) click to toggle source
# File lib/porpoise/set.rb, line 83
def smembers(key)
  o = find_stored_object(key)
  return o.value
end
smove(source, destination, member) click to toggle source
# File lib/porpoise/set.rb, line 88
def smove(source, destination, member)
  Porpoise::KeyValueObject.transaction do
    src = find_stored_object(source, false, true)
    dst = find_stored_object(destination, false, true)
    
    ele = src.value.delete(member)
    return 0 if ele.nil?

    dst.value << ele unless dst.value.include?(ele)
    res = dst.save && src.save

    return (ele && res) ? 1 : 0
  end
end
spop(key, count = 1) click to toggle source
# File lib/porpoise/set.rb, line 103
def spop(key, count = 1)
  o = find_stored_object(key)
  return nil if o.new_record?
  
  pd = [] 
  count.times do
    pd.push(o.value.shuffle!.pop) if o.value.size > 0
  end
 
  o.save

  return pd
end
srandmember(key, count = 1) click to toggle source
# File lib/porpoise/set.rb, line 117
def srandmember(key, count = 1)
  o = find_stored_object(key)
  return [] if o.new_record?

  return o.value.sample(count)
end
srem(key, member, *other_members) click to toggle source
# File lib/porpoise/set.rb, line 124
def srem(key, member, *other_members)
  o = find_stored_object(key)
  return 0 if o.new_record?

  previous_set = o.value.dup
  all_members = [member].concat(other_members)
  o.value = o.value.reject { |v| all_members.include?(v) }
  o.save

  previous_set - o.value
end
sunion(key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 136
def sunion(key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value.dup
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set.concat(oo[ok].value)
  end
  current_set.uniq
end
sunionstore(destination, key, *other_keys) click to toggle source
# File lib/porpoise/set.rb, line 149
def sunionstore(destination, key, *other_keys)
  o = find_stored_object(key)
  current_set = o.value.dup
  other_keys = other_keys.map { |k| Porpoise::key_with_namespace(k) }

  oo = Porpoise::KeyValueObject.not_expired.where(key: other_keys).all.index_by(&:key)
  other_keys.each do |ok|
    next unless oo.has_key?(ok)
    current_set.concat(oo[ok].value)
  end

  no = find_stored_object(destination)
  no.value = current_set.uniq
  no.save
  no.value.size
end

Private Class Methods

find_stored_object(key, raise_on_type_mismatch = true, raise_on_not_found = false) click to toggle source
# File lib/porpoise/set.rb, line 168
def find_stored_object(key, 
                       raise_on_type_mismatch = true,
                       raise_on_not_found = false)

  key = Porpoise::key_with_namespace(key)
  o = Porpoise::KeyValueObject.not_expired.where(key: key).first
  
  if raise_on_type_mismatch && !o.nil? && o.data_type != 'Array'
    raise Porpoise::TypeMismatch.new(
      "Key #{key} is not of type Set (is #{o.data_type})"
    )
  end

  if raise_on_not_found && o.nil?
    raise Porpoise::KeyNotFound.new("Key #{key} could not be found")
  elsif o.nil?
    o = Porpoise::KeyValueObject.new(key: key, value: ::Array.new)
  elsif o.expired?
    Porpoise::KeyValueObject.retry_lock_error(20) { o.delete }
    o = Porpoise::KeyValueObject.new(key: key, value: ::Array.new)
  end

  return o
end