redis_migrator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/README.md +35 -0
- data/lib/redis_migrator/redis_helper.rb +52 -0
- data/lib/redis_migrator/redis_populator.rb +63 -0
- data/lib/redis_migrator.rb +96 -0
- data/migrator_benchmark.rb +22 -0
- data/redis_migrator.gemspec +20 -0
- data/spec/migrator_spec.rb +63 -0
- data/spec/mock_redis/lib/mock_redis/assertions.rb +13 -0
- data/spec/mock_redis/lib/mock_redis/database.rb +432 -0
- data/spec/mock_redis/lib/mock_redis/distributed.rb +6 -0
- data/spec/mock_redis/lib/mock_redis/exceptions.rb +3 -0
- data/spec/mock_redis/lib/mock_redis/expire_wrapper.rb +25 -0
- data/spec/mock_redis/lib/mock_redis/hash_methods.rb +118 -0
- data/spec/mock_redis/lib/mock_redis/list_methods.rb +187 -0
- data/spec/mock_redis/lib/mock_redis/multi_db_wrapper.rb +86 -0
- data/spec/mock_redis/lib/mock_redis/set_methods.rb +126 -0
- data/spec/mock_redis/lib/mock_redis/string_methods.rb +203 -0
- data/spec/mock_redis/lib/mock_redis/transaction_wrapper.rb +80 -0
- data/spec/mock_redis/lib/mock_redis/undef_redis_methods.rb +11 -0
- data/spec/mock_redis/lib/mock_redis/utility_methods.rb +25 -0
- data/spec/mock_redis/lib/mock_redis/version.rb +3 -0
- data/spec/mock_redis/lib/mock_redis/zset.rb +110 -0
- data/spec/mock_redis/lib/mock_redis/zset_methods.rb +210 -0
- data/spec/mock_redis/lib/mock_redis.rb +119 -0
- data/spec/redis_helper_spec.rb +58 -0
- data/spec/spec_helper.rb +29 -0
- metadata +107 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
class MockRedis
|
5
|
+
class Zset
|
6
|
+
include Enumerable
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_reader :members, :scores
|
10
|
+
|
11
|
+
def_delegators :members, :empty?, :include?, :size
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@members = Set.new
|
15
|
+
@scores = Hash.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize_copy(source)
|
19
|
+
super
|
20
|
+
@members = @members.clone
|
21
|
+
@scores = @scores.clone
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(score, member)
|
25
|
+
members.add(member)
|
26
|
+
if score.to_f.to_i == score.to_f
|
27
|
+
scores[member] = score.to_f.to_i
|
28
|
+
else
|
29
|
+
scores[member] = score.to_f
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete?(member)
|
35
|
+
scores.delete(member)
|
36
|
+
members.delete?(member) and self
|
37
|
+
end
|
38
|
+
|
39
|
+
def each
|
40
|
+
members.each {|m| yield score(m), m}
|
41
|
+
end
|
42
|
+
|
43
|
+
def in_range(min, max)
|
44
|
+
in_from_the_left = case min
|
45
|
+
when "-inf"
|
46
|
+
lambda {|_| true }
|
47
|
+
when "+inf"
|
48
|
+
lambda {|_| false }
|
49
|
+
when /\((.*)$/
|
50
|
+
val = $1.to_f
|
51
|
+
lambda {|x| x.to_f > val }
|
52
|
+
else
|
53
|
+
lambda {|x| x.to_f >= min.to_f }
|
54
|
+
end
|
55
|
+
|
56
|
+
in_from_the_right = case max
|
57
|
+
when "-inf"
|
58
|
+
lambda {|_| false }
|
59
|
+
when "+inf"
|
60
|
+
lambda {|_| true }
|
61
|
+
when /\((.*)$/
|
62
|
+
val = $1.to_f
|
63
|
+
lambda {|x| x.to_f < val }
|
64
|
+
else
|
65
|
+
lambda {|x| x.to_f <= max.to_f }
|
66
|
+
end
|
67
|
+
|
68
|
+
sorted.find_all do |(score, member)|
|
69
|
+
in_from_the_left[score] && in_from_the_right[score]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def intersection(other)
|
74
|
+
if !block_given?
|
75
|
+
intersection(other, &:+)
|
76
|
+
else
|
77
|
+
self.members.intersection(other.members).reduce(self.class.new) do |acc, m|
|
78
|
+
new_score = yield(self.score(m), other.score(m))
|
79
|
+
acc.add(new_score, m)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def score(member)
|
85
|
+
scores[member]
|
86
|
+
end
|
87
|
+
|
88
|
+
def sorted
|
89
|
+
members.map do |m|
|
90
|
+
[score(m), m]
|
91
|
+
end.sort_by(&:first)
|
92
|
+
end
|
93
|
+
|
94
|
+
def sorted_members
|
95
|
+
sorted.map(&:last)
|
96
|
+
end
|
97
|
+
|
98
|
+
def union(other)
|
99
|
+
if !block_given?
|
100
|
+
union(other, &:+)
|
101
|
+
else
|
102
|
+
self.members.union(other.members).reduce(self.class.new) do |acc, m|
|
103
|
+
new_score = yield(self.score(m), other.score(m))
|
104
|
+
acc.add(new_score, m)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'mock_redis/assertions'
|
2
|
+
require 'mock_redis/utility_methods'
|
3
|
+
require 'mock_redis/zset'
|
4
|
+
|
5
|
+
class MockRedis
|
6
|
+
module ZsetMethods
|
7
|
+
include Assertions
|
8
|
+
include UtilityMethods
|
9
|
+
|
10
|
+
def zadd(key, score, member)
|
11
|
+
assert_scorey(score)
|
12
|
+
|
13
|
+
retval = !zscore(key, member)
|
14
|
+
with_zset_at(key) {|z| z.add(score, member.to_s)}
|
15
|
+
retval
|
16
|
+
end
|
17
|
+
|
18
|
+
def zcard(key)
|
19
|
+
with_zset_at(key, &:size)
|
20
|
+
end
|
21
|
+
|
22
|
+
def zcount(key, min, max)
|
23
|
+
assert_scorey(min, 'min or max')
|
24
|
+
assert_scorey(max, 'min or max')
|
25
|
+
|
26
|
+
with_zset_at(key) do |z|
|
27
|
+
z.count do |score, _|
|
28
|
+
score >= min && score <= max
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def zincrby(key, increment, member)
|
34
|
+
assert_scorey(increment)
|
35
|
+
member = member.to_s
|
36
|
+
with_zset_at(key) do |z|
|
37
|
+
old_score = z.include?(member) ? z.score(member) : 0
|
38
|
+
new_score = old_score + increment
|
39
|
+
z.add(new_score, member)
|
40
|
+
new_score.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def zinterstore(destination, keys, options={})
|
45
|
+
assert_has_args(keys, 'zinterstore')
|
46
|
+
|
47
|
+
data[destination] = combine_weighted_zsets(keys, options, :intersection)
|
48
|
+
zcard(destination)
|
49
|
+
end
|
50
|
+
|
51
|
+
def zrange(key, start, stop, options={})
|
52
|
+
with_zset_at(key) do |z|
|
53
|
+
to_response(z.sorted[start..stop] || [], options)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def zrangebyscore(key, min, max, options={})
|
58
|
+
with_zset_at(key) do |zset|
|
59
|
+
all_results = zset.in_range(min, max)
|
60
|
+
to_response(apply_limit(all_results, options[:limit]), options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def zrank(key, member)
|
65
|
+
with_zset_at(key) {|z| z.sorted_members.index(member.to_s) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def zrem(key, member)
|
69
|
+
with_zset_at(key) {|z| !!z.delete?(member.to_s)}
|
70
|
+
end
|
71
|
+
|
72
|
+
def zrevrange(key, start, stop, options={})
|
73
|
+
with_zset_at(key) do |z|
|
74
|
+
to_response(z.sorted.reverse[start..stop], options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def zremrangebyrank(key, start, stop)
|
79
|
+
zrange(key, start, stop).
|
80
|
+
each {|member| zrem(key, member)}.
|
81
|
+
size
|
82
|
+
end
|
83
|
+
|
84
|
+
def zremrangebyscore(key, min, max)
|
85
|
+
zrangebyscore(key, min, max).
|
86
|
+
each {|member| zrem(key, member)}.
|
87
|
+
size
|
88
|
+
end
|
89
|
+
|
90
|
+
def zrevrangebyscore(key, max, min, options={})
|
91
|
+
with_zset_at(key) do |zset|
|
92
|
+
to_response(
|
93
|
+
apply_limit(
|
94
|
+
zset.in_range(min, max).reverse,
|
95
|
+
options[:limit]),
|
96
|
+
options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def zrevrank(key, member)
|
101
|
+
with_zset_at(key) {|z| z.sorted_members.reverse.index(member.to_s) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def zscore(key, member)
|
105
|
+
with_zset_at(key) do |z|
|
106
|
+
score = z.score(member.to_s)
|
107
|
+
score.to_s if score
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def zunionstore(destination, keys, options={})
|
112
|
+
assert_has_args(keys, 'zunionstore')
|
113
|
+
|
114
|
+
data[destination] = combine_weighted_zsets(keys, options, :union)
|
115
|
+
zcard(destination)
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def apply_limit(collection, limit)
|
120
|
+
if limit
|
121
|
+
if limit.is_a?(Array) && limit.length == 2
|
122
|
+
offset, count = limit
|
123
|
+
collection.drop(offset).take(count)
|
124
|
+
else
|
125
|
+
raise RuntimeError, "ERR syntax error"
|
126
|
+
end
|
127
|
+
else
|
128
|
+
collection
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_response(score_member_pairs, options)
|
133
|
+
score_member_pairs.map do |(score,member)|
|
134
|
+
if options[:with_scores] || options[:withscores]
|
135
|
+
[member, score.to_s]
|
136
|
+
else
|
137
|
+
member
|
138
|
+
end
|
139
|
+
end.flatten
|
140
|
+
end
|
141
|
+
|
142
|
+
def combine_weighted_zsets(keys, options, how)
|
143
|
+
weights = options.fetch(:weights, keys.map { 1 })
|
144
|
+
if weights.length != keys.length
|
145
|
+
raise RuntimeError, "ERR syntax error"
|
146
|
+
end
|
147
|
+
|
148
|
+
aggregator = case options.fetch(:aggregate, :sum).to_s.downcase.to_sym
|
149
|
+
when :sum
|
150
|
+
proc {|a,b| [a,b].compact.reduce(&:+)}
|
151
|
+
when :min
|
152
|
+
proc {|a,b| [a,b].compact.min}
|
153
|
+
when :max
|
154
|
+
proc {|a,b| [a,b].compact.max}
|
155
|
+
else
|
156
|
+
raise RuntimeError, "ERR syntax error"
|
157
|
+
end
|
158
|
+
|
159
|
+
with_zsets_at(*keys) do |*zsets|
|
160
|
+
zsets.zip(weights).map do |(zset, weight)|
|
161
|
+
zset.reduce(Zset.new) do |acc, (score, member)|
|
162
|
+
acc.add(score * weight, member)
|
163
|
+
end
|
164
|
+
end.reduce do |za, zb|
|
165
|
+
za.send(how, zb, &aggregator)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
def with_zset_at(key, &blk)
|
172
|
+
with_thing_at(key, :assert_zsety, proc {Zset.new}, &blk)
|
173
|
+
end
|
174
|
+
|
175
|
+
def with_zsets_at(*keys, &blk)
|
176
|
+
if keys.length == 1
|
177
|
+
with_zset_at(keys.first, &blk)
|
178
|
+
else
|
179
|
+
with_zset_at(keys.first) do |set|
|
180
|
+
with_zsets_at(*(keys[1..-1])) do |*sets|
|
181
|
+
blk.call(*([set] + sets))
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def zsety?(key)
|
188
|
+
data[key].nil? || data[key].kind_of?(Zset)
|
189
|
+
end
|
190
|
+
|
191
|
+
def assert_zsety(key)
|
192
|
+
unless zsety?(key)
|
193
|
+
raise RuntimeError,
|
194
|
+
"ERR Operation against a key holding the wrong kind of value"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def looks_like_float?(x)
|
199
|
+
# ugh, exceptions for flow control.
|
200
|
+
!!Float(x) rescue false
|
201
|
+
end
|
202
|
+
|
203
|
+
def assert_scorey(value, what='value')
|
204
|
+
unless looks_like_float?(value)
|
205
|
+
raise RuntimeError, "ERR #{what} is not a double"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
require 'mock_redis/assertions'
|
4
|
+
require 'mock_redis/database'
|
5
|
+
require 'mock_redis/distributed'
|
6
|
+
require 'mock_redis/expire_wrapper'
|
7
|
+
require 'mock_redis/multi_db_wrapper'
|
8
|
+
require 'mock_redis/transaction_wrapper'
|
9
|
+
require 'mock_redis/undef_redis_methods'
|
10
|
+
|
11
|
+
class MockRedis
|
12
|
+
include UndefRedisMethods
|
13
|
+
|
14
|
+
attr_reader :options
|
15
|
+
|
16
|
+
DEFAULTS = {
|
17
|
+
:scheme => "redis",
|
18
|
+
:host => "127.0.0.1",
|
19
|
+
:port => 6379,
|
20
|
+
:path => nil,
|
21
|
+
:timeout => 5.0,
|
22
|
+
:password => nil,
|
23
|
+
:db => 0,
|
24
|
+
}
|
25
|
+
|
26
|
+
def initialize(*args)
|
27
|
+
@options = _parse_options(args.first)
|
28
|
+
|
29
|
+
@db = TransactionWrapper.new(
|
30
|
+
ExpireWrapper.new(
|
31
|
+
MultiDbWrapper.new(
|
32
|
+
Database.new(*args))))
|
33
|
+
end
|
34
|
+
|
35
|
+
def id
|
36
|
+
"redis://#{self.host}:#{self.port}/#{self.db}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(command, &block)
|
40
|
+
self.send(*command)
|
41
|
+
end
|
42
|
+
|
43
|
+
def host
|
44
|
+
self.options[:host]
|
45
|
+
end
|
46
|
+
|
47
|
+
def port
|
48
|
+
self.options[:port]
|
49
|
+
end
|
50
|
+
|
51
|
+
def db
|
52
|
+
self.options[:db]
|
53
|
+
end
|
54
|
+
|
55
|
+
def client
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def respond_to?(method, include_private=false)
|
60
|
+
super || @db.respond_to?(method, include_private)
|
61
|
+
end
|
62
|
+
|
63
|
+
def method_missing(method, *args, &block)
|
64
|
+
@db.send(method, *args, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize_copy(source)
|
68
|
+
super
|
69
|
+
@db = @db.clone
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def _parse_options(options)
|
76
|
+
return {} if options.nil?
|
77
|
+
|
78
|
+
defaults = DEFAULTS.dup
|
79
|
+
|
80
|
+
url = options[:url] || ENV["REDIS_URL"]
|
81
|
+
|
82
|
+
# Override defaults from URL if given
|
83
|
+
if url
|
84
|
+
require "uri"
|
85
|
+
|
86
|
+
uri = URI(url)
|
87
|
+
|
88
|
+
if uri.scheme == "unix"
|
89
|
+
defaults[:path] = uri.path
|
90
|
+
else
|
91
|
+
# Require the URL to have at least a host
|
92
|
+
raise ArgumentError, "invalid url" unless uri.host
|
93
|
+
|
94
|
+
defaults[:scheme] = uri.scheme
|
95
|
+
defaults[:host] = uri.host
|
96
|
+
defaults[:port] = uri.port if uri.port
|
97
|
+
defaults[:password] = uri.password if uri.password
|
98
|
+
defaults[:db] = uri.path[1..-1].to_i if uri.path
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
options = defaults.merge(options)
|
103
|
+
|
104
|
+
if options[:path]
|
105
|
+
options[:scheme] = "unix"
|
106
|
+
options.delete(:host)
|
107
|
+
options.delete(:port)
|
108
|
+
else
|
109
|
+
options[:host] = options[:host].to_s
|
110
|
+
options[:port] = options[:port].to_i
|
111
|
+
end
|
112
|
+
|
113
|
+
options[:timeout] = options[:timeout].to_f
|
114
|
+
options[:db] = options[:db].to_i
|
115
|
+
|
116
|
+
options
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
describe Redis::Helper do
|
2
|
+
before do
|
3
|
+
Redis.should_receive(:new).any_number_of_times {|options|
|
4
|
+
MockRedis.new(options)
|
5
|
+
}
|
6
|
+
|
7
|
+
@migrator = Redis::Migrator.new(["redis://localhost:6379"],
|
8
|
+
["redis://localhost:6377"])
|
9
|
+
|
10
|
+
@r1 = @migrator.old_cluster
|
11
|
+
@r2 = @migrator.new_cluster
|
12
|
+
@migrator.stub!(:redis).and_return(@r1)
|
13
|
+
@pipe = PipeMock.new(@r2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should copy a string" do
|
17
|
+
@r1.set("a", "some_string")
|
18
|
+
@migrator.copy_string(@pipe, "a")
|
19
|
+
|
20
|
+
@r2.get("a").should == "some_string"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should copy a hash" do
|
24
|
+
@r1.hmset("myhash",
|
25
|
+
"first_name", "James",
|
26
|
+
"last_name", "Randi",
|
27
|
+
"age", "83")
|
28
|
+
|
29
|
+
@migrator.copy_hash(@pipe, "myhash")
|
30
|
+
|
31
|
+
@r2.hgetall("myhash").should == {"first_name" => "James", "last_name" => "Randi", "age" => "83"}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should copy a list" do
|
35
|
+
('a'..'z').to_a.each { |val| @r1.lpush("mylist", val) }
|
36
|
+
|
37
|
+
@migrator.copy_list(@pipe, "mylist")
|
38
|
+
|
39
|
+
@r2.lrange("mylist", 0, -1).should == ('a'..'z').to_a
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should copy a set" do
|
43
|
+
('a'..'z').to_a.each { |val| @r1.sadd("myset", val) }
|
44
|
+
|
45
|
+
@migrator.copy_set(@pipe, "myset")
|
46
|
+
|
47
|
+
@r2.smembers("myset").should == ('a'..'z').to_a
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should copy zset" do
|
51
|
+
('a'..'z').to_a.each { |val| @r1.zadd("myzset", rand(100), val) }
|
52
|
+
|
53
|
+
@migrator.copy_zset(@pipe, "myzset")
|
54
|
+
|
55
|
+
@r2.zrange("myzset", 0, -1, :with_scores => true).sort.should == @r1.zrange("myzset", 0, -1, :with_scores => true).sort
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), "mock_redis/lib"))
|
2
|
+
|
3
|
+
require_relative "../lib/redis_migrator.rb"
|
4
|
+
|
5
|
+
# include patched version of mock_redis
|
6
|
+
# that works with Redis::Distributed
|
7
|
+
require "mock_redis.rb"
|
8
|
+
|
9
|
+
class PipeMock
|
10
|
+
def initialize(redis)
|
11
|
+
@redis = redis
|
12
|
+
end
|
13
|
+
|
14
|
+
def close; true; end
|
15
|
+
|
16
|
+
def <<(val)
|
17
|
+
val[0] = val[0].downcase.to_sym
|
18
|
+
@redis.send(*val)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
class Redis
|
24
|
+
module Helper
|
25
|
+
def to_redis_proto(*cmd)
|
26
|
+
cmd
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redis_migrator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Artem Yankov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-05 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: redis
|
16
|
+
requirement: &70245281843860 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.2.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70245281843860
|
25
|
+
description: Redis-migrator takes a list of nodes for your old cluster and list of
|
26
|
+
nodes for your new cluster and determines for which keys routes were changed. Then
|
27
|
+
it moves those keys to new nodes.
|
28
|
+
email:
|
29
|
+
- artem.yankov@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- .rspec
|
36
|
+
- README.md
|
37
|
+
- lib/redis_migrator.rb
|
38
|
+
- lib/redis_migrator/redis_helper.rb
|
39
|
+
- lib/redis_migrator/redis_populator.rb
|
40
|
+
- migrator_benchmark.rb
|
41
|
+
- redis_migrator.gemspec
|
42
|
+
- spec/migrator_spec.rb
|
43
|
+
- spec/mock_redis/lib/mock_redis.rb
|
44
|
+
- spec/mock_redis/lib/mock_redis/assertions.rb
|
45
|
+
- spec/mock_redis/lib/mock_redis/database.rb
|
46
|
+
- spec/mock_redis/lib/mock_redis/distributed.rb
|
47
|
+
- spec/mock_redis/lib/mock_redis/exceptions.rb
|
48
|
+
- spec/mock_redis/lib/mock_redis/expire_wrapper.rb
|
49
|
+
- spec/mock_redis/lib/mock_redis/hash_methods.rb
|
50
|
+
- spec/mock_redis/lib/mock_redis/list_methods.rb
|
51
|
+
- spec/mock_redis/lib/mock_redis/multi_db_wrapper.rb
|
52
|
+
- spec/mock_redis/lib/mock_redis/set_methods.rb
|
53
|
+
- spec/mock_redis/lib/mock_redis/string_methods.rb
|
54
|
+
- spec/mock_redis/lib/mock_redis/transaction_wrapper.rb
|
55
|
+
- spec/mock_redis/lib/mock_redis/undef_redis_methods.rb
|
56
|
+
- spec/mock_redis/lib/mock_redis/utility_methods.rb
|
57
|
+
- spec/mock_redis/lib/mock_redis/version.rb
|
58
|
+
- spec/mock_redis/lib/mock_redis/zset.rb
|
59
|
+
- spec/mock_redis/lib/mock_redis/zset_methods.rb
|
60
|
+
- spec/redis_helper_spec.rb
|
61
|
+
- spec/spec_helper.rb
|
62
|
+
homepage: http://rubygems.org/gems/redis_migrator
|
63
|
+
licenses: []
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.8.17
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: A tool to redistribute keys in your redis cluster when its topography has
|
86
|
+
changed
|
87
|
+
test_files:
|
88
|
+
- spec/migrator_spec.rb
|
89
|
+
- spec/mock_redis/lib/mock_redis.rb
|
90
|
+
- spec/mock_redis/lib/mock_redis/assertions.rb
|
91
|
+
- spec/mock_redis/lib/mock_redis/database.rb
|
92
|
+
- spec/mock_redis/lib/mock_redis/distributed.rb
|
93
|
+
- spec/mock_redis/lib/mock_redis/exceptions.rb
|
94
|
+
- spec/mock_redis/lib/mock_redis/expire_wrapper.rb
|
95
|
+
- spec/mock_redis/lib/mock_redis/hash_methods.rb
|
96
|
+
- spec/mock_redis/lib/mock_redis/list_methods.rb
|
97
|
+
- spec/mock_redis/lib/mock_redis/multi_db_wrapper.rb
|
98
|
+
- spec/mock_redis/lib/mock_redis/set_methods.rb
|
99
|
+
- spec/mock_redis/lib/mock_redis/string_methods.rb
|
100
|
+
- spec/mock_redis/lib/mock_redis/transaction_wrapper.rb
|
101
|
+
- spec/mock_redis/lib/mock_redis/undef_redis_methods.rb
|
102
|
+
- spec/mock_redis/lib/mock_redis/utility_methods.rb
|
103
|
+
- spec/mock_redis/lib/mock_redis/version.rb
|
104
|
+
- spec/mock_redis/lib/mock_redis/zset.rb
|
105
|
+
- spec/mock_redis/lib/mock_redis/zset_methods.rb
|
106
|
+
- spec/redis_helper_spec.rb
|
107
|
+
- spec/spec_helper.rb
|