module MeRedisHotMigrator

We need only to fallback getters, when you are setting

new value it will go in a new place already
me_mget doesn't compartible with pipeline, it will raise exception when placed inside one.

Constants

ZK_FALLBACK_METHODS

Public Class Methods

included(base) click to toggle source
# File lib/me_redis/me_redis_hot_migrator.rb, line 7
def self.included(base)
  base::Future.prepend(FutureMigrator)

  base.class_eval do
    ZK_FALLBACK_METHODS.each do |method|
      alias_method "_#{method}", method
    end

    include(MeRedis)

    def me_get( key )
      prev_future = _get( key ) unless @client.is_a?(self.class::Client)
      newvl = super(key)

      newvl.prev_future = prev_future if newvl.is_a?(self.class::Future)
      newvl || _get( key )
    end

    def me_mget(*keys)
      #cannot run in pipeline because of fallbacks
      raise 'Cannot run in pipeline!!!' unless @client.is_a?(self.class::Client)
      me_mget_p(*keys).map(&:value)
    end

  end

  base.prepend( MeRedisHotMigrator::PrependMethods )
end

Public Instance Methods

hash_migration_possible?( keys ) click to toggle source
# File lib/me_redis/me_redis_hot_migrator.rb, line 57
def hash_migration_possible?( keys )
  result = keys.map{ |key| [split_key(key).each_with_index.map{|v,i| i == 0 ? zip_key(v) : v }, key] }.to_h

  raise ArgumentError.new( "Hash zipping is not one to one! #{result.keys} != #{keys}" ) if result.length != keys.length

  result.each do |sp_key, key|
    key_start = key.to_s.scan(/\A(.*?)(\d+)\z/).flatten[0]
    if sp_key[0].start_with?( key_start )
      raise ArgumentError.new( "#{sp_key[0]} contains original key main part: #{key_start} Hash migration must be done with key zipping!")
    end
  end

  true
end
key_zipping_migration_reversible?( keys ) click to toggle source
# File lib/me_redis/me_redis_hot_migrator.rb, line 119
def key_zipping_migration_reversible?( keys )
  !!zk_map_keys(keys)
end
me_get( key ) click to toggle source
Calls superclass method
# File lib/me_redis/me_redis_hot_migrator.rb, line 17
def me_get( key )
  prev_future = _get( key ) unless @client.is_a?(self.class::Client)
  newvl = super(key)

  newvl.prev_future = prev_future if newvl.is_a?(self.class::Future)
  newvl || _get( key )
end
me_mget(*keys) click to toggle source
# File lib/me_redis/me_redis_hot_migrator.rb, line 25
def me_mget(*keys)
  #cannot run in pipeline because of fallbacks
  raise 'Cannot run in pipeline!!!' unless @client.is_a?(self.class::Client)
  me_mget_p(*keys).map(&:value)
end
migrate_to_hash_representation( keys ) click to toggle source

keys will exists after migrate, you need to call del(keys) directly uses hsetnx, meaning you will not overwrtite new values

# File lib/me_redis/me_redis_hot_migrator.rb, line 74
def migrate_to_hash_representation( keys )
  raise StandardError.new('Cannot migrate inside pipeline.') unless @client.is_a?( self.class::Client )
  raise ArgumentError.new('Migration is unavailable!') unless hash_migration_possible?( keys )

  values = mget( keys )
  pipelined do
    keys.each_with_index do |key, i|
      me_setnx( key, values[i] )
    end
  end
end
migrate_to_key_zipping(keys) click to toggle source

——————————-KZ migration————————————

# File lib/me_redis/me_redis_hot_migrator.rb, line 97
def migrate_to_key_zipping(keys)
  pipelined do
    zk_map_keys(keys).each{|new_key, key| renamenx( key, new_key )}
  end
end
reverse_from_hash_representation!( keys ) click to toggle source
# File lib/me_redis/me_redis_hot_migrator.rb, line 86
def reverse_from_hash_representation!( keys )
  raise "Cannot migrate inside pipeline" unless @client.is_a?(self.class::Client )
  values = me_mget( keys )

  pipelined do
    keys.each_with_index{|key, i| set( key, values[i] ) }
  end
end
reverse_from_key_zipping!( keys ) click to toggle source

reverse migration done with same set of keys, i.e, if you migrated [ user:1, user:2 ] with migrate_to_key_zipping and want to reverse migration then use same argument [ user:1, user:2 ]

# File lib/me_redis/me_redis_hot_migrator.rb, line 106
def reverse_from_key_zipping!( keys )
  pipelined do
    zk_map_keys(keys).each{|new_key, key| rename( new_key, key ) }
  end
end
zk_map_keys(keys) click to toggle source

use only uniq keys! or zk_map_keys will fire an error! if transition is not one to one zk_map_keys would also fire an error

# File lib/me_redis/me_redis_hot_migrator.rb, line 114
def zk_map_keys(keys)
  keys.map{ |key| [zip_key(key), key] }.to_h
      .tap{ |result| raise ArgumentError.new( "Key zipping is not one to one! #{result.keys} != #{keys}" ) if result.length != keys.length }
end