redis_migrator 0.0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/README.md +13 -1
- data/Rakefile +6 -0
- data/lib/redis_migrator/redis_helper.rb +5 -36
- data/lib/redis_migrator/redis_native_migrator.rb +27 -0
- data/lib/redis_migrator/redis_pipe_migrator.rb +66 -0
- data/lib/redis_migrator/redis_populator.rb +1 -1
- data/lib/redis_migrator.rb +19 -20
- data/migrator_benchmark.rb +1 -2
- data/redis_migrator.gemspec +8 -4
- data/spec/different_redis_type_migrator.rb +67 -0
- data/spec/pretested_migrator.rb +47 -0
- data/spec/redis_migrator_spec.rb +41 -0
- data/spec/redis_native_migrator_spec.rb +44 -0
- data/spec/redis_pipe_migrator_spec.rb +51 -0
- data/spec/shared_hosts_context.rb +10 -0
- data/spec/spec_helper.rb +9 -7
- metadata +85 -49
- data/spec/migrator_spec.rb +0 -63
- data/spec/mock_redis/lib/mock_redis/assertions.rb +0 -13
- data/spec/mock_redis/lib/mock_redis/database.rb +0 -432
- data/spec/mock_redis/lib/mock_redis/distributed.rb +0 -6
- data/spec/mock_redis/lib/mock_redis/exceptions.rb +0 -3
- data/spec/mock_redis/lib/mock_redis/expire_wrapper.rb +0 -25
- data/spec/mock_redis/lib/mock_redis/hash_methods.rb +0 -118
- data/spec/mock_redis/lib/mock_redis/list_methods.rb +0 -187
- data/spec/mock_redis/lib/mock_redis/multi_db_wrapper.rb +0 -86
- data/spec/mock_redis/lib/mock_redis/set_methods.rb +0 -126
- data/spec/mock_redis/lib/mock_redis/string_methods.rb +0 -203
- data/spec/mock_redis/lib/mock_redis/transaction_wrapper.rb +0 -80
- data/spec/mock_redis/lib/mock_redis/undef_redis_methods.rb +0 -11
- data/spec/mock_redis/lib/mock_redis/utility_methods.rb +0 -25
- data/spec/mock_redis/lib/mock_redis/version.rb +0 -3
- data/spec/mock_redis/lib/mock_redis/zset.rb +0 -110
- data/spec/mock_redis/lib/mock_redis/zset_methods.rb +0 -210
- data/spec/mock_redis/lib/mock_redis.rb +0 -119
- data/spec/redis_helper_spec.rb +0 -58
metadata
CHANGED
@@ -1,27 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_migrator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Artem Yankov
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: redis
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: 3.0.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: debugger
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mock_redis
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
25
83
|
description: Redis-migrator takes a list of nodes for your old cluster and list of
|
26
84
|
nodes for your new cluster and determines for which keys routes were changed. Then
|
27
85
|
it moves those keys to new nodes.
|
@@ -33,75 +91,53 @@ extra_rdoc_files: []
|
|
33
91
|
files:
|
34
92
|
- .gitignore
|
35
93
|
- .rspec
|
94
|
+
- Gemfile
|
36
95
|
- README.md
|
96
|
+
- Rakefile
|
37
97
|
- lib/redis_migrator.rb
|
38
98
|
- lib/redis_migrator/redis_helper.rb
|
99
|
+
- lib/redis_migrator/redis_native_migrator.rb
|
100
|
+
- lib/redis_migrator/redis_pipe_migrator.rb
|
39
101
|
- lib/redis_migrator/redis_populator.rb
|
40
102
|
- migrator_benchmark.rb
|
41
103
|
- redis_migrator.gemspec
|
42
|
-
- spec/
|
43
|
-
- spec/
|
44
|
-
- spec/
|
45
|
-
- spec/
|
46
|
-
- spec/
|
47
|
-
- spec/
|
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
|
104
|
+
- spec/different_redis_type_migrator.rb
|
105
|
+
- spec/pretested_migrator.rb
|
106
|
+
- spec/redis_migrator_spec.rb
|
107
|
+
- spec/redis_native_migrator_spec.rb
|
108
|
+
- spec/redis_pipe_migrator_spec.rb
|
109
|
+
- spec/shared_hosts_context.rb
|
61
110
|
- spec/spec_helper.rb
|
62
111
|
homepage: http://rubygems.org/gems/redis_migrator
|
63
112
|
licenses: []
|
113
|
+
metadata: {}
|
64
114
|
post_install_message:
|
65
115
|
rdoc_options: []
|
66
116
|
require_paths:
|
67
117
|
- lib
|
68
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
-
none: false
|
70
119
|
requirements:
|
71
120
|
- - ! '>='
|
72
121
|
- !ruby/object:Gem::Version
|
73
122
|
version: '0'
|
74
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
124
|
requirements:
|
77
125
|
- - ! '>='
|
78
126
|
- !ruby/object:Gem::Version
|
79
127
|
version: '0'
|
80
128
|
requirements: []
|
81
129
|
rubyforge_project:
|
82
|
-
rubygems_version:
|
130
|
+
rubygems_version: 2.2.2
|
83
131
|
signing_key:
|
84
|
-
specification_version:
|
132
|
+
specification_version: 4
|
85
133
|
summary: A tool to redistribute keys in your redis cluster when its topography has
|
86
134
|
changed
|
87
135
|
test_files:
|
88
|
-
- spec/
|
89
|
-
- spec/
|
90
|
-
- spec/
|
91
|
-
- spec/
|
92
|
-
- spec/
|
93
|
-
- spec/
|
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
|
136
|
+
- spec/different_redis_type_migrator.rb
|
137
|
+
- spec/pretested_migrator.rb
|
138
|
+
- spec/redis_migrator_spec.rb
|
139
|
+
- spec/redis_native_migrator_spec.rb
|
140
|
+
- spec/redis_pipe_migrator_spec.rb
|
141
|
+
- spec/shared_hosts_context.rb
|
107
142
|
- spec/spec_helper.rb
|
143
|
+
has_rdoc:
|
data/spec/migrator_spec.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
describe Redis::Migrator do
|
2
|
-
|
3
|
-
before do
|
4
|
-
Redis.should_receive(:new).any_number_of_times {|options|
|
5
|
-
MockRedis.new(options)
|
6
|
-
}
|
7
|
-
|
8
|
-
@migrator = Redis::Migrator.new(["redis://localhost:6379", "redis://localhost:6378"],
|
9
|
-
["redis://localhost:6379", "redis://localhost:6378", "redis://localhost:6377"])
|
10
|
-
|
11
|
-
#populate old cluster with some keys
|
12
|
-
('a'..'z').to_a.each do |key|
|
13
|
-
(1..5).to_a.each {|val| @migrator.old_cluster.sadd(key, val)}
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe Redis::Migrator, "#changed_keys" do
|
18
|
-
it "should show keys which need migration" do
|
19
|
-
@migrator.changed_keys.should == {"redis://localhost:6377/0" => ["h", "q", "s", "y", "j", "m", "n", "o"]}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe Redis::Migrator, "#migrate_keys" do
|
24
|
-
let(:keys) { ["q", "s", "j"] }
|
25
|
-
let(:node) { {:host => "localhost", :port => 6378, :db => 1} }
|
26
|
-
|
27
|
-
before do
|
28
|
-
Redis::Distributed.should_receive(:new).and_return(@migrator.old_cluster)
|
29
|
-
|
30
|
-
@pipe = PipeMock.new(@migrator.new_cluster)
|
31
|
-
IO.should_receive(:popen).with("redis-cli -h localhost -p 6378 -n 1 --pipe", IO::RDWR).and_return(@pipe)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should copy given keys to a new cluster" do
|
35
|
-
@migrator.migrate_keys(node, keys)
|
36
|
-
(@migrator.new_cluster.keys("*") & keys).sort.should == ["j", "q", "s"]
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should remove copied keys from the old redis node" do
|
40
|
-
@migrator.migrate_keys(node, keys)
|
41
|
-
(@migrator.old_cluster.keys("*") & keys).sort.should == []
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should keep keys on old node if asked" do
|
45
|
-
@migrator.migrate_keys(node, keys, :do_not_remove => true)
|
46
|
-
(@migrator.old_cluster.keys("*") & keys).sort.should == ["j", "q", "s"]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe Redis::Migrator, "#copy_key" do
|
51
|
-
|
52
|
-
it "should return FALSE for unknown key" do
|
53
|
-
@migrator.copy_key(nil, "some_key").should == false
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should call copy_set if given key is set" do
|
57
|
-
@migrator.should_receive(:copy_set).with(nil, "a")
|
58
|
-
@migrator.copy_key(nil, "a")
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
@@ -1,432 +0,0 @@
|
|
1
|
-
require 'mock_redis/assertions'
|
2
|
-
require 'mock_redis/exceptions'
|
3
|
-
require 'mock_redis/hash_methods'
|
4
|
-
require 'mock_redis/list_methods'
|
5
|
-
require 'mock_redis/set_methods'
|
6
|
-
require 'mock_redis/string_methods'
|
7
|
-
require 'mock_redis/zset_methods'
|
8
|
-
|
9
|
-
class MockRedis
|
10
|
-
class Database
|
11
|
-
include HashMethods
|
12
|
-
include ListMethods
|
13
|
-
include SetMethods
|
14
|
-
include StringMethods
|
15
|
-
include ZsetMethods
|
16
|
-
|
17
|
-
attr_reader :data, :expire_times
|
18
|
-
|
19
|
-
def initialize(*args)
|
20
|
-
@data = {}
|
21
|
-
@expire_times = []
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize_copy(source)
|
25
|
-
@data = @data.clone
|
26
|
-
@data.keys.each {|k| @data[k] = @data[k].clone}
|
27
|
-
@expire_times = @expire_times.map{|x| x.clone}
|
28
|
-
end
|
29
|
-
|
30
|
-
# Redis commands go below this line and above 'private'
|
31
|
-
|
32
|
-
def auth(_) 'OK' end
|
33
|
-
|
34
|
-
def bgrewriteaof() "Background append only file rewriting started" end
|
35
|
-
|
36
|
-
def bgsave() "Background saving started" end
|
37
|
-
|
38
|
-
def dbsize
|
39
|
-
data.keys.length
|
40
|
-
end
|
41
|
-
|
42
|
-
def del(*keys)
|
43
|
-
keys.
|
44
|
-
find_all{|key| data[key]}.
|
45
|
-
each {|k| persist(k)}.
|
46
|
-
each {|k| data.delete(k)}.
|
47
|
-
length
|
48
|
-
end
|
49
|
-
|
50
|
-
def echo(msg)
|
51
|
-
msg.to_s
|
52
|
-
end
|
53
|
-
|
54
|
-
def expire(key, seconds)
|
55
|
-
expireat(key, Time.now.to_i + seconds.to_i)
|
56
|
-
end
|
57
|
-
|
58
|
-
def expireat(key, timestamp)
|
59
|
-
unless looks_like_integer?(timestamp.to_s)
|
60
|
-
raise RuntimeError, "ERR value is not an integer or out of range"
|
61
|
-
end
|
62
|
-
|
63
|
-
if exists(key)
|
64
|
-
set_expiration(key, Time.at(timestamp.to_i))
|
65
|
-
true
|
66
|
-
else
|
67
|
-
false
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def exists(key)
|
72
|
-
data.has_key?(key)
|
73
|
-
end
|
74
|
-
|
75
|
-
def flushdb
|
76
|
-
data.keys.each {|k| del(k)}
|
77
|
-
'OK'
|
78
|
-
end
|
79
|
-
|
80
|
-
def info
|
81
|
-
astats = [
|
82
|
-
["2", "2699"],
|
83
|
-
["6", "1"],
|
84
|
-
["7", "1"],
|
85
|
-
["8", "17197"],
|
86
|
-
["9", "109875"],
|
87
|
-
["10", "94348"],
|
88
|
-
["11", "32580"],
|
89
|
-
["12", "52347"],
|
90
|
-
["13", "86475"],
|
91
|
-
["14", "58175"],
|
92
|
-
["15", "53408"],
|
93
|
-
["16", "876949"],
|
94
|
-
["17", "71157"],
|
95
|
-
["18", "5104"],
|
96
|
-
["19", "2705"],
|
97
|
-
["20", "2903"],
|
98
|
-
["21", "1024"],
|
99
|
-
["22", "2546"],
|
100
|
-
["23", "952"],
|
101
|
-
["24", "186080"],
|
102
|
-
["25", "611"],
|
103
|
-
["26", "40936"],
|
104
|
-
["27", "960"],
|
105
|
-
["28", "1323"],
|
106
|
-
["29", "14216"],
|
107
|
-
["30", "52412"],
|
108
|
-
["31", "21130"],
|
109
|
-
["32", "47959"],
|
110
|
-
["33", "6891"],
|
111
|
-
["34", "9712"],
|
112
|
-
["35", "3366"],
|
113
|
-
["36", "5737"],
|
114
|
-
["37", "11274"],
|
115
|
-
["38", "8057"],
|
116
|
-
["39", "2957"],
|
117
|
-
["40", "51200"],
|
118
|
-
["42", "8220"],
|
119
|
-
["43", "8278"],
|
120
|
-
["44", "6539"],
|
121
|
-
["45", "764"],
|
122
|
-
["47", "1018"],
|
123
|
-
["48", "19250"],
|
124
|
-
["49", "713"],
|
125
|
-
["51", "51"],
|
126
|
-
["53", "2"],
|
127
|
-
["55", "3922"],
|
128
|
-
["56", "153"],
|
129
|
-
["57", "614"],
|
130
|
-
["58", "1"],
|
131
|
-
["59", "1775"],
|
132
|
-
["61", "32865"],
|
133
|
-
["63", "2530"],
|
134
|
-
["64", "565"],
|
135
|
-
["65", "1322"],
|
136
|
-
["67", "1572"],
|
137
|
-
["69", "1421"],
|
138
|
-
["71", "1220"],
|
139
|
-
["72", "241"],
|
140
|
-
["73", "5432"],
|
141
|
-
["74", "1122"],
|
142
|
-
["75", "2555"],
|
143
|
-
["77", "1539"],
|
144
|
-
["78", "612"],
|
145
|
-
["79", "902"],
|
146
|
-
["81", "1678"],
|
147
|
-
["83", "51"],
|
148
|
-
["84", "612"],
|
149
|
-
["85", "706"],
|
150
|
-
["87", "410"],
|
151
|
-
["88", "5435"],
|
152
|
-
["89", "813"],
|
153
|
-
["90", "612"],
|
154
|
-
["93", "153"],
|
155
|
-
["94", "612"],
|
156
|
-
["96", "159"],
|
157
|
-
["97", "306"],
|
158
|
-
["99", "153"],
|
159
|
-
["101", "456"],
|
160
|
-
["103", "741"],
|
161
|
-
["105", "447"],
|
162
|
-
["107", "754"],
|
163
|
-
["109", "414"],
|
164
|
-
["111", "475"],
|
165
|
-
["113", "757"],
|
166
|
-
["115", "287"],
|
167
|
-
["117", "420"],
|
168
|
-
["118", "765"],
|
169
|
-
["119", "642"],
|
170
|
-
["120", "159"],
|
171
|
-
["121", "926"],
|
172
|
-
["122", "612"],
|
173
|
-
["123", "251"],
|
174
|
-
["125", "390"],
|
175
|
-
["127", "354"],
|
176
|
-
["128", "617"],
|
177
|
-
["129", "528"],
|
178
|
-
["131", "298"],
|
179
|
-
["132", "612"],
|
180
|
-
["133", "809"],
|
181
|
-
["135", "244"],
|
182
|
-
["136", "306"],
|
183
|
-
["137", "504"],
|
184
|
-
["139", "201"],
|
185
|
-
["141", "1124"],
|
186
|
-
["143", "139"],
|
187
|
-
["144", "159"],
|
188
|
-
["145", "1322"],
|
189
|
-
["147", "410"],
|
190
|
-
["149", "253"],
|
191
|
-
["151", "304"],
|
192
|
-
["153", "312"],
|
193
|
-
["155", "249"],
|
194
|
-
["157", "306"],
|
195
|
-
["159", "348"],
|
196
|
-
["161", "255"],
|
197
|
-
["163", "458"],
|
198
|
-
["165", "5"],
|
199
|
-
["167", "306"],
|
200
|
-
["168", "47"],
|
201
|
-
["169", "214"],
|
202
|
-
["171", "250"],
|
203
|
-
["173", "5"],
|
204
|
-
["177", "10"],
|
205
|
-
["179", "158"],
|
206
|
-
["181", "5"],
|
207
|
-
["183", "10"],
|
208
|
-
["185", "51"],
|
209
|
-
["187", "49"],
|
210
|
-
["191", "5"],
|
211
|
-
["192", "47"],
|
212
|
-
["193", "51"],
|
213
|
-
["197", "112"],
|
214
|
-
["199", "5"],
|
215
|
-
["201", "5"],
|
216
|
-
["203", "5"],
|
217
|
-
["209", "5"],
|
218
|
-
["213", "51"],
|
219
|
-
["217", "102"],
|
220
|
-
["225", "357"],
|
221
|
-
["229", "51"],
|
222
|
-
["233", "204"],
|
223
|
-
["237", "51"],
|
224
|
-
["239", "1"],
|
225
|
-
["247", "46"],
|
226
|
-
["255", "102"],
|
227
|
-
[">=256", "6201"],
|
228
|
-
]
|
229
|
-
|
230
|
-
{
|
231
|
-
"allocation_stats" => astats.map {|(a,b)| "#{a}=#{b}"}.join(','),
|
232
|
-
"aof_enabled" => "0",
|
233
|
-
"arch_bits" => "64",
|
234
|
-
"bgrewriteaof_in_progress" => "0",
|
235
|
-
"bgsave_in_progress" => "0",
|
236
|
-
"blocked_clients" => "0",
|
237
|
-
"changes_since_last_save" => "0",
|
238
|
-
"client_biggest_input_buf" => "0",
|
239
|
-
"client_longest_output_list" => "0",
|
240
|
-
"connected_clients" => "1",
|
241
|
-
"connected_slaves" => "0",
|
242
|
-
"db0" => "keys=8,expires=0",
|
243
|
-
"evicted_keys" => "0",
|
244
|
-
"expired_keys" => "0",
|
245
|
-
"hash_max_zipmap_entries" => "512",
|
246
|
-
"hash_max_zipmap_value" => "64",
|
247
|
-
"keyspace_hits" => "62645",
|
248
|
-
"keyspace_misses" => "29757",
|
249
|
-
"last_save_time" => "1310596333",
|
250
|
-
"loading" => "0",
|
251
|
-
"lru_clock" => "1036434",
|
252
|
-
"mem_fragmentation_ratio" => "2.04",
|
253
|
-
"multiplexing_api" => "kqueue",
|
254
|
-
"process_id" => "14508",
|
255
|
-
"pubsub_channels" => "0",
|
256
|
-
"pubsub_patterns" => "0",
|
257
|
-
"redis_git_dirty" => "0",
|
258
|
-
"redis_git_sha1" => "00000000",
|
259
|
-
"redis_version" => "2.2.11",
|
260
|
-
"role" => "master",
|
261
|
-
"total_commands_processed" => "196800",
|
262
|
-
"total_connections_received" => "4359",
|
263
|
-
"uptime_in_days" => "0",
|
264
|
-
"uptime_in_seconds" => "84215",
|
265
|
-
"use_tcmalloc" => "0",
|
266
|
-
"used_cpu_sys" => "5.54",
|
267
|
-
"used_cpu_sys_childrens" => "0.00",
|
268
|
-
"used_cpu_user" => "7.65",
|
269
|
-
"used_cpu_user_childrens" => "0.02",
|
270
|
-
"used_memory" => "931456",
|
271
|
-
"used_memory_human" => "909.62K",
|
272
|
-
"used_memory_rss" => "1904640",
|
273
|
-
"vm_enabled" => "0",
|
274
|
-
}
|
275
|
-
end
|
276
|
-
|
277
|
-
def keys(format)
|
278
|
-
data.keys.grep(redis_pattern_to_ruby_regex(format))
|
279
|
-
end
|
280
|
-
|
281
|
-
def lastsave
|
282
|
-
Time.now.to_i
|
283
|
-
end
|
284
|
-
|
285
|
-
def persist(key)
|
286
|
-
if exists(key) && has_expiration?(key)
|
287
|
-
remove_expiration(key)
|
288
|
-
true
|
289
|
-
else
|
290
|
-
false
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
def ping
|
295
|
-
'PONG'
|
296
|
-
end
|
297
|
-
|
298
|
-
def quit
|
299
|
-
'OK'
|
300
|
-
end
|
301
|
-
|
302
|
-
def randomkey
|
303
|
-
data.keys[rand(data.length)]
|
304
|
-
end
|
305
|
-
|
306
|
-
def rename(key, newkey)
|
307
|
-
if key == newkey
|
308
|
-
raise RuntimeError, "ERR source and destination objects are the same"
|
309
|
-
end
|
310
|
-
data[newkey] = data.delete(key)
|
311
|
-
'OK'
|
312
|
-
end
|
313
|
-
|
314
|
-
def renamenx(key, newkey)
|
315
|
-
if key == newkey
|
316
|
-
raise RuntimeError, "ERR source and destination objects are the same"
|
317
|
-
end
|
318
|
-
if exists(newkey)
|
319
|
-
false
|
320
|
-
else
|
321
|
-
rename(key, newkey)
|
322
|
-
true
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def save
|
327
|
-
'OK'
|
328
|
-
end
|
329
|
-
|
330
|
-
def ttl(key)
|
331
|
-
if has_expiration?(key)
|
332
|
-
expiration(key).to_i - Time.now.to_i
|
333
|
-
else
|
334
|
-
-1
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
def type(key)
|
339
|
-
if !exists(key)
|
340
|
-
'none'
|
341
|
-
elsif hashy?(key)
|
342
|
-
'hash'
|
343
|
-
elsif stringy?(key)
|
344
|
-
'string'
|
345
|
-
elsif listy?(key)
|
346
|
-
'list'
|
347
|
-
elsif sety?(key)
|
348
|
-
'set'
|
349
|
-
elsif zsety?(key)
|
350
|
-
'zset'
|
351
|
-
else
|
352
|
-
raise ArgumentError, "Not sure how #{data[key].inspect} got in here"
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
private
|
357
|
-
|
358
|
-
def assert_valid_timeout(timeout)
|
359
|
-
if !looks_like_integer?(timeout.to_s)
|
360
|
-
raise RuntimeError, "ERR timeout is not an integer or out of range"
|
361
|
-
elsif timeout < 0
|
362
|
-
raise RuntimeError, "ERR timeout is negative"
|
363
|
-
end
|
364
|
-
timeout
|
365
|
-
end
|
366
|
-
|
367
|
-
def can_incr?(value)
|
368
|
-
value.nil? || looks_like_integer?(value)
|
369
|
-
end
|
370
|
-
|
371
|
-
def extract_timeout(arglist)
|
372
|
-
timeout = assert_valid_timeout(arglist.last)
|
373
|
-
[arglist[0..-2], arglist.last]
|
374
|
-
end
|
375
|
-
|
376
|
-
def expiration(key)
|
377
|
-
expire_times.find {|(_,k)| k == key}.first
|
378
|
-
end
|
379
|
-
|
380
|
-
def has_expiration?(key)
|
381
|
-
expire_times.any? {|(_,k)| k == key}
|
382
|
-
end
|
383
|
-
|
384
|
-
def looks_like_integer?(str)
|
385
|
-
str =~ /^-?\d+$/
|
386
|
-
end
|
387
|
-
|
388
|
-
def redis_pattern_to_ruby_regex(pattern)
|
389
|
-
Regexp.new(
|
390
|
-
"^#{pattern}$".
|
391
|
-
gsub(/([^\\])\?/, "\\1.").
|
392
|
-
gsub(/([^\\])\*/, "\\1.+"))
|
393
|
-
end
|
394
|
-
|
395
|
-
def remove_expiration(key)
|
396
|
-
expire_times.delete_if do |(t, k)|
|
397
|
-
key == k
|
398
|
-
end
|
399
|
-
end
|
400
|
-
|
401
|
-
def set_expiration(key, time)
|
402
|
-
remove_expiration(key)
|
403
|
-
|
404
|
-
expire_times << [time, key]
|
405
|
-
expire_times.sort! do |a, b|
|
406
|
-
a.first <=> b.first
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
def zero_pad(string, desired_length)
|
411
|
-
padding = "\000" * [(desired_length - string.length), 0].max
|
412
|
-
string + padding
|
413
|
-
end
|
414
|
-
|
415
|
-
public
|
416
|
-
# This method isn't private, but it also isn't a Redis command, so
|
417
|
-
# it doesn't belong up above with all the Redis commands.
|
418
|
-
def expire_keys
|
419
|
-
now = Time.now
|
420
|
-
|
421
|
-
to_delete = expire_times.take_while do |(time, key)|
|
422
|
-
time <= now
|
423
|
-
end
|
424
|
-
|
425
|
-
to_delete.each do |(time, key)|
|
426
|
-
del(key)
|
427
|
-
end
|
428
|
-
|
429
|
-
expire_times.slice!(0, to_delete.length)
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|