Module: MeRedisHotMigrator

Defined in:
lib/me_redis/me_redis_hot_migrator.rb

Overview

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.

Defined Under Namespace

Modules: FutureMigrator, PrependMethods

Constant Summary collapse

ZK_FALLBACK_METHODS =
%i[mget hget hgetall get exists type getset]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 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

Instance Method Details

#hash_migration_possible?(keys) ⇒ Boolean

——————————-ME method migration—————————— check if migration possible, if not raises exception with a reason

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 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) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/me_redis/me_redis_hot_migrator.rb', line 119

def key_zipping_migration_reversible?( keys )
  !!zk_map_keys(keys)
end

#migrate_to_hash_representation(keys) ⇒ Object

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

Raises:

  • (StandardError)


74
75
76
77
78
79
80
81
82
83
84
# 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) ⇒ Object

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



97
98
99
100
101
# 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) ⇒ Object



86
87
88
89
90
91
92
93
# 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) ⇒ Object

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 ]



106
107
108
109
110
# 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) ⇒ Object

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



114
115
116
117
# 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