redis 3.0.7 → 3.1.0
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.
- checksums.yaml +13 -5
- data/.gitignore +2 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +29 -2
- data/Gemfile +4 -0
- data/README.md +15 -1
- data/Rakefile +12 -347
- data/lib/redis.rb +54 -0
- data/lib/redis/client.rb +33 -13
- data/lib/redis/distributed.rb +23 -0
- data/lib/redis/version.rb +1 -1
- data/test/bitpos_test.rb +69 -0
- data/test/commands_on_hyper_log_log_test.rb +21 -0
- data/test/distributed_commands_on_hyper_log_log_test.rb +22 -0
- data/test/fork_safety_test.rb +65 -0
- data/test/helper.rb +18 -6
- data/test/internals_test.rb +22 -6
- data/test/lint/hyper_log_log.rb +48 -0
- metadata +82 -12
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Njk4NjUzM2ZiOTk2NTU0Y2FkYzg5NzU4NDc0Zjg1MmJiMDUwYjFlMg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MTAxMTMzZmVjY2E2YjI1NzQ3Y2M1YTI5NDk3ZWQ5ZjVmZmExYTMwYg==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NjkwNTI4ZTg3OTVhNTkwYWViNGQzY2NmZGJiODQ1ZTc1MzNmNzdjNjE0NTkx
|
10
|
+
NzljZTdhZTg1ZjEyYTYxYTJjYmJkYmIwZjYzZTdkNmFlOTNmNDZlY2YzMTY1
|
11
|
+
MTgyZmRmZjNlNTEwNzZlYWJmM2Q3YTkxZTEyZDc1MjZhNWNlODc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDQ0NDIyZmVmMWVmMmE5ZGU4ZDQyYzAxODljYTEzODM2YjY5YzAyMWZjNzdh
|
14
|
+
NTEwMjcwZDM2OWRhYWY4ZjUzMTRmOWU5MTNjMDM3ZDM2YjM0YTRhMDc3NGY0
|
15
|
+
MjQ5ZTFhYjg5ODM5NDlmZjMyMDkxMTg1NmI3YjgyZWQwNmQzN2Y=
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -9,6 +9,7 @@ rvm:
|
|
9
9
|
- 1.9.2
|
10
10
|
- 1.9.3
|
11
11
|
- 2.0.0
|
12
|
+
- 2.1.0
|
12
13
|
- jruby-18mode
|
13
14
|
- jruby-19mode
|
14
15
|
|
@@ -17,6 +18,7 @@ gemfile:
|
|
17
18
|
|
18
19
|
env:
|
19
20
|
global:
|
21
|
+
- VERBOSE=true
|
20
22
|
- TIMEOUT=1
|
21
23
|
matrix:
|
22
24
|
- conn=ruby REDIS_BRANCH=2.6
|
@@ -51,5 +53,4 @@ notifications:
|
|
51
53
|
- irc.freenode.net#redis-rb
|
52
54
|
email:
|
53
55
|
- damian.janowski@gmail.com
|
54
|
-
- michel@soveran.com
|
55
56
|
- pcnoordhuis@gmail.com
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,33 @@
|
|
1
|
-
# (unreleased)
|
1
|
+
# 4.x (unreleased)
|
2
2
|
|
3
|
-
|
3
|
+
## Planned breaking changes:
|
4
|
+
* `Redis#client` will no longer expose the underlying `Redis::Client`;
|
5
|
+
it has not yet been determined how 4.0 will expose the underlying
|
6
|
+
functionality, but we will make every attempt to provide a final minor
|
7
|
+
release of 3.x that provides the new interfaces in order to facilitate
|
8
|
+
a smooth transition.
|
9
|
+
|
10
|
+
* Ruby 1.8.7 (and the 1.8 modes of JRuby and Rubinius) will no longer be
|
11
|
+
supported; 1.8.x entered end-of-life in June of 2012 and stopped receiving
|
12
|
+
security updates in June of 2013; continuing to support it would prevent
|
13
|
+
the use of newer features of Ruby.
|
14
|
+
|
15
|
+
# 3.1.x (unreleased)
|
16
|
+
|
17
|
+
* Added debug log sanitization (#428).
|
18
|
+
|
19
|
+
* Added support for HyperLogLog commands (Redis 2.8.9, #432).
|
20
|
+
|
21
|
+
* Added support for `BITPOS` command (Redis 2.9.11, #412).
|
22
|
+
|
23
|
+
* The client will now automatically reconnect after a fork (#414).
|
24
|
+
|
25
|
+
* If you want to disable the fork-safety check and prefer to share the
|
26
|
+
connection across child processes, you can now pass the `inherit_socket`
|
27
|
+
option (#409).
|
28
|
+
|
29
|
+
* If you want the client to attempt to reconnect more than once, you can now
|
30
|
+
pass the `reconnect_attempts` option (#347)
|
4
31
|
|
5
32
|
# 3.0.7
|
6
33
|
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
# redis-rb [![Build Status][travis-image]][travis-link]
|
1
|
+
# redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link]
|
2
2
|
|
3
3
|
[travis-image]: https://secure.travis-ci.org/redis/redis-rb.png?branch=master
|
4
4
|
[travis-link]: http://travis-ci.org/redis/redis-rb
|
5
5
|
[travis-home]: http://travis-ci.org/
|
6
|
+
[inchpages-image]: http://inch-pages.github.io/github/redis/redis-rb.png
|
7
|
+
[inchpages-link]: http://inch-pages.github.io/github/redis/redis-rb
|
6
8
|
|
7
9
|
A Ruby client library for [Redis][redis-home].
|
8
10
|
|
@@ -156,6 +158,18 @@ end
|
|
156
158
|
# => 1
|
157
159
|
```
|
158
160
|
|
161
|
+
## Expert-Mode Options
|
162
|
+
|
163
|
+
- `inherit_socket: true`: disable safety check that prevents a forked child
|
164
|
+
from sharing a socket with its parent; this is potentially useful in order to mitigate connection churn when:
|
165
|
+
- many short-lived forked children of one process need to talk
|
166
|
+
to redis, AND
|
167
|
+
- your own code prevents the parent process from using the redis
|
168
|
+
connection while a child is alive
|
169
|
+
|
170
|
+
Improper use of `inherit_socket` will result in corrupted and/or incorrect
|
171
|
+
responses.
|
172
|
+
|
159
173
|
## Alternate drivers
|
160
174
|
|
161
175
|
By default, redis-rb uses Ruby's socket library to talk with Redis.
|
data/Rakefile
CHANGED
@@ -1,12 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require 'rubygems/package_task'
|
3
|
-
require 'rake/testtask'
|
1
|
+
require "rake/testtask"
|
4
2
|
|
5
3
|
ENV["REDIS_BRANCH"] ||= "unstable"
|
6
4
|
|
7
|
-
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
8
|
-
require 'redis/version'
|
9
|
-
|
10
5
|
REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
|
11
6
|
REDIS_CNF = File.join(REDIS_DIR, "test.conf")
|
12
7
|
REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
|
@@ -34,6 +29,10 @@ task :start => BINARY do
|
|
34
29
|
abort "could not start redis-server"
|
35
30
|
end
|
36
31
|
end
|
32
|
+
|
33
|
+
at_exit do
|
34
|
+
Rake::Task["stop"].invoke
|
35
|
+
end
|
37
36
|
end
|
38
37
|
|
39
38
|
desc "Stop the Redis server"
|
@@ -44,12 +43,18 @@ task :stop do
|
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
46
|
+
desc "Clean up testing artifacts"
|
47
|
+
task :clean do
|
48
|
+
FileUtils.rm_f(BINARY)
|
49
|
+
end
|
50
|
+
|
47
51
|
file BINARY do
|
48
52
|
branch = ENV.fetch("REDIS_BRANCH")
|
49
53
|
|
50
54
|
sh <<-SH
|
51
55
|
mkdir -p tmp;
|
52
56
|
cd tmp;
|
57
|
+
rm -rf redis-#{branch};
|
53
58
|
wget https://github.com/antirez/redis/archive/#{branch}.tar.gz -O #{branch}.tar.gz;
|
54
59
|
tar xf #{branch}.tar.gz;
|
55
60
|
cd redis-#{branch};
|
@@ -58,346 +63,6 @@ file BINARY do
|
|
58
63
|
end
|
59
64
|
|
60
65
|
Rake::TestTask.new do |t|
|
61
|
-
t.options = "-v"
|
66
|
+
t.options = "-v" if $VERBOSE
|
62
67
|
t.test_files = FileList["test/*_test.rb"]
|
63
68
|
end
|
64
|
-
|
65
|
-
task :doc => ["doc:generate", "doc:prepare"]
|
66
|
-
|
67
|
-
namespace :doc do
|
68
|
-
task :generate do
|
69
|
-
require "shellwords"
|
70
|
-
|
71
|
-
`rm -rf doc`
|
72
|
-
|
73
|
-
current_branch = `git branch`[/^\* (.*)$/, 1]
|
74
|
-
|
75
|
-
begin
|
76
|
-
tags = `git tag -l`.split("\n").sort.reverse
|
77
|
-
|
78
|
-
tags.each do |tag|
|
79
|
-
`git checkout -q #{tag} 2>/dev/null`
|
80
|
-
|
81
|
-
unless $?.success?
|
82
|
-
$stderr.puts "Need a clean working copy. Please git-stash away."
|
83
|
-
exit 1
|
84
|
-
end
|
85
|
-
|
86
|
-
puts tag
|
87
|
-
|
88
|
-
`mkdir -p doc/#{tag}`
|
89
|
-
|
90
|
-
files = `git ls-tree -r HEAD lib`.split("\n").map do |line|
|
91
|
-
line[/\t(.*)$/, 1]
|
92
|
-
end
|
93
|
-
|
94
|
-
opts = [
|
95
|
-
"--title", "A Ruby client for Redis",
|
96
|
-
"--output", "doc/#{tag}",
|
97
|
-
"--no-cache",
|
98
|
-
"--no-save",
|
99
|
-
"-q",
|
100
|
-
*files
|
101
|
-
]
|
102
|
-
|
103
|
-
`yardoc #{Shellwords.shelljoin opts}`
|
104
|
-
end
|
105
|
-
ensure
|
106
|
-
`git checkout -q #{current_branch}`
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
task :prepare do
|
111
|
-
versions = `git tag -l`.split("\n").grep(/^v/).sort
|
112
|
-
latest_version = versions.last
|
113
|
-
|
114
|
-
File.open("doc/.htaccess", "w") do |file|
|
115
|
-
file.puts "RedirectMatch 302 ^/?$ /#{latest_version}"
|
116
|
-
end
|
117
|
-
|
118
|
-
File.open("doc/robots.txt", "w") do |file|
|
119
|
-
file.puts "User-Agent: *"
|
120
|
-
|
121
|
-
(versions - [latest_version]).each do |version|
|
122
|
-
file.puts "Disallow: /#{version}"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
google_analytics = <<-EOS
|
127
|
-
<script type="text/javascript">
|
128
|
-
|
129
|
-
var _gaq = _gaq || [];
|
130
|
-
_gaq.push(['_setAccount', 'UA-11356145-2']);
|
131
|
-
_gaq.push(['_trackPageview']);
|
132
|
-
|
133
|
-
(function() {
|
134
|
-
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
135
|
-
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
136
|
-
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
137
|
-
})();
|
138
|
-
|
139
|
-
</script>
|
140
|
-
EOS
|
141
|
-
|
142
|
-
Dir["doc/**/*.html"].each do |path|
|
143
|
-
lines = IO.readlines(path)
|
144
|
-
|
145
|
-
File.open(path, "w") do |file|
|
146
|
-
lines.each do |line|
|
147
|
-
if line.include?("</head>")
|
148
|
-
file.write(google_analytics)
|
149
|
-
end
|
150
|
-
|
151
|
-
file.write(line)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
task :deploy do
|
158
|
-
system "rsync --del -avz doc/ redis-rb.keyvalue.org:deploys/redis-rb.keyvalue.org/"
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
class Source
|
163
|
-
|
164
|
-
MATCHER = "(?:\\s{%d}#[^\\n]*\\n)*^\\s{%d}def ([a-z_?]+)(?:\(.*?\))?\\n.*?^\\s{%d}end\\n\\n"
|
165
|
-
|
166
|
-
def initialize(data, options = {})
|
167
|
-
@doc = parse(File.read(data), options)
|
168
|
-
end
|
169
|
-
|
170
|
-
def methods
|
171
|
-
@doc.select do |d|
|
172
|
-
d.is_a?(Method)
|
173
|
-
end.map do |d|
|
174
|
-
d.name
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def move(a, b)
|
179
|
-
ao = @doc.find { |m| m.is_a?(Method) && m.name == a }
|
180
|
-
bo = @doc.find { |m| m.is_a?(Method) && m.name == b }
|
181
|
-
ai = @doc.index(ao)
|
182
|
-
bi = @doc.index(bo)
|
183
|
-
|
184
|
-
@doc.delete_at(ai)
|
185
|
-
@doc.insert(bi, ao)
|
186
|
-
|
187
|
-
nil
|
188
|
-
end
|
189
|
-
|
190
|
-
def to_s
|
191
|
-
@doc.join
|
192
|
-
end
|
193
|
-
|
194
|
-
protected
|
195
|
-
|
196
|
-
def parse(data, options = {})
|
197
|
-
re = Regexp.new(MATCHER % ([options[:indent]] * 3), Regexp::MULTILINE)
|
198
|
-
tail = data.dup
|
199
|
-
doc = []
|
200
|
-
|
201
|
-
while match = re.match(tail)
|
202
|
-
doc << match.pre_match
|
203
|
-
doc << Method.new(match)
|
204
|
-
tail = match.post_match
|
205
|
-
end
|
206
|
-
|
207
|
-
doc << tail if tail
|
208
|
-
doc
|
209
|
-
end
|
210
|
-
|
211
|
-
class Method
|
212
|
-
|
213
|
-
def initialize(match)
|
214
|
-
@match = match
|
215
|
-
end
|
216
|
-
|
217
|
-
def name
|
218
|
-
@match[1]
|
219
|
-
end
|
220
|
-
|
221
|
-
def to_s
|
222
|
-
@match[0]
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
namespace :commands do
|
228
|
-
def redis_commands
|
229
|
-
$redis_commands ||= doc.keys.map do |key|
|
230
|
-
key.split(" ").first.downcase
|
231
|
-
end.uniq
|
232
|
-
end
|
233
|
-
|
234
|
-
def doc
|
235
|
-
$doc ||= begin
|
236
|
-
require "open-uri"
|
237
|
-
require "json"
|
238
|
-
|
239
|
-
JSON.parse(open("https://github.com/antirez/redis-doc/raw/master/commands.json").read)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
task :order do
|
244
|
-
require "json"
|
245
|
-
|
246
|
-
reference = if File.exist?(".order")
|
247
|
-
JSON.parse(File.read(".order"))
|
248
|
-
else
|
249
|
-
{}
|
250
|
-
end
|
251
|
-
|
252
|
-
buckets = {}
|
253
|
-
doc.each do |k, v|
|
254
|
-
buckets[v["group"]] ||= []
|
255
|
-
buckets[v["group"]] << k.split.first.downcase
|
256
|
-
buckets[v["group"]].uniq!
|
257
|
-
end
|
258
|
-
|
259
|
-
result = (reference.keys + (buckets.keys - reference.keys)).map do |g|
|
260
|
-
[g, reference[g] + (buckets[g] - reference[g])]
|
261
|
-
end
|
262
|
-
|
263
|
-
File.open(".order", "w") do |f|
|
264
|
-
f.write(JSON.pretty_generate(Hash[result]))
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def reorder(file, options = {})
|
269
|
-
require "json"
|
270
|
-
require "set"
|
271
|
-
|
272
|
-
STDERR.puts "reordering #{file}..."
|
273
|
-
|
274
|
-
reference = if File.exist?(".order")
|
275
|
-
JSON.parse(File.read(".order"))
|
276
|
-
else
|
277
|
-
{}
|
278
|
-
end
|
279
|
-
|
280
|
-
dst = Source.new(file, options)
|
281
|
-
|
282
|
-
src_methods = reference.map { |k, v| v }.flatten
|
283
|
-
dst_methods = dst.methods
|
284
|
-
|
285
|
-
src_set = Set.new(src_methods)
|
286
|
-
dst_set = Set.new(dst_methods)
|
287
|
-
|
288
|
-
intersection = src_set & dst_set
|
289
|
-
intersection.delete("initialize")
|
290
|
-
|
291
|
-
loop do
|
292
|
-
src_methods = reference.map { |k, v| v }.flatten
|
293
|
-
dst_methods = dst.methods
|
294
|
-
|
295
|
-
src_methods = src_methods.select do |m|
|
296
|
-
intersection.include?(m)
|
297
|
-
end
|
298
|
-
|
299
|
-
dst_methods = dst_methods.select do |m|
|
300
|
-
intersection.include?(m)
|
301
|
-
end
|
302
|
-
|
303
|
-
if src_methods == dst_methods
|
304
|
-
break
|
305
|
-
end
|
306
|
-
|
307
|
-
rv = yield(src_methods, dst_methods, dst)
|
308
|
-
break if rv == false
|
309
|
-
end
|
310
|
-
|
311
|
-
File.open(file, "w") do |f|
|
312
|
-
f.write(dst.to_s)
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
task :reorder do
|
317
|
-
blk = lambda do |src_methods, dst_methods, dst|
|
318
|
-
src_methods.zip(dst_methods).each do |a, b|
|
319
|
-
if a != b
|
320
|
-
dst.move(a, b)
|
321
|
-
break
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
reorder "lib/redis.rb", :indent => 2, &blk
|
327
|
-
reorder "lib/redis/distributed.rb", :indent => 4, &blk
|
328
|
-
end
|
329
|
-
|
330
|
-
def missing(file, options = {})
|
331
|
-
src = Source.new(file, options)
|
332
|
-
|
333
|
-
defined_methods = src.methods.map(&:downcase)
|
334
|
-
required_methods = redis_commands.map(&:downcase)
|
335
|
-
|
336
|
-
STDOUT.puts "missing in #{file}:"
|
337
|
-
STDOUT.puts (required_methods - defined_methods).inspect
|
338
|
-
end
|
339
|
-
|
340
|
-
task :missing do
|
341
|
-
missing "lib/redis.rb", :indent => 2
|
342
|
-
missing "lib/redis/distributed.rb", :indent => 4
|
343
|
-
end
|
344
|
-
|
345
|
-
def document(file)
|
346
|
-
source = File.read(file)
|
347
|
-
|
348
|
-
doc.each do |name, command|
|
349
|
-
source.sub!(/(?:^ *# .*\n)*(^ *#\n(^ *# .+?\n)*)*^( *)def #{name.downcase}(\(|$)/) do
|
350
|
-
extra_comments, indent, extra_args = $1, $3, $4
|
351
|
-
comment = "#{indent}# #{command["summary"].strip}."
|
352
|
-
|
353
|
-
IO.popen("par p#{2 + indent.size} 80", "r+") do |io|
|
354
|
-
io.puts comment
|
355
|
-
io.close_write
|
356
|
-
comment = io.read
|
357
|
-
end
|
358
|
-
|
359
|
-
"#{comment}#{extra_comments}#{indent}def #{name.downcase}#{extra_args}"
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
File.open(file, "w") { |f| f.write(source) }
|
364
|
-
end
|
365
|
-
|
366
|
-
task :doc do
|
367
|
-
document "lib/redis.rb"
|
368
|
-
document "lib/redis/distributed.rb"
|
369
|
-
end
|
370
|
-
|
371
|
-
task :verify do
|
372
|
-
require "redis"
|
373
|
-
require "stringio"
|
374
|
-
|
375
|
-
require "./test/helper"
|
376
|
-
|
377
|
-
OPTIONS[:logger] = Logger.new("./tmp/log")
|
378
|
-
|
379
|
-
Rake::Task["test:ruby"].invoke
|
380
|
-
|
381
|
-
redis = Redis.new
|
382
|
-
|
383
|
-
report = ["Command", "\033[0mDefined?\033[0m", "\033[0mTested?\033[0m"]
|
384
|
-
|
385
|
-
yes, no = "\033[1;32mYes\033[0m", "\033[1;31mNo\033[0m"
|
386
|
-
|
387
|
-
log = File.read("./tmp/log")
|
388
|
-
|
389
|
-
redis_commands.sort.each do |name, _|
|
390
|
-
defined, tested = redis.respond_to?(name), log[">> #{name.upcase}"]
|
391
|
-
|
392
|
-
next if defined && tested
|
393
|
-
|
394
|
-
report << name
|
395
|
-
report << (defined ? yes : no)
|
396
|
-
report << (tested ? yes : no)
|
397
|
-
end
|
398
|
-
|
399
|
-
IO.popen("rs 0 3", "w") do |io|
|
400
|
-
io.puts report.join("\n")
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|
data/lib/redis.rb
CHANGED
@@ -906,6 +906,27 @@ class Redis
|
|
906
906
|
end
|
907
907
|
end
|
908
908
|
|
909
|
+
# Return the position of the first bit set to 1 or 0 in a string.
|
910
|
+
#
|
911
|
+
# @param [String] key
|
912
|
+
# @param [Fixnum] bit whether to look for the first 1 or 0 bit
|
913
|
+
# @param [Fixnum] start start index
|
914
|
+
# @param [Fixnum] stop stop index
|
915
|
+
# @return [Fixnum] the position of the first 1/0 bit.
|
916
|
+
# -1 if looking for 1 and it is not found or start and stop are given.
|
917
|
+
def bitpos(key, bit, start=nil, stop=nil)
|
918
|
+
if stop and not start
|
919
|
+
raise(ArgumentError, 'stop parameter specified without start parameter')
|
920
|
+
end
|
921
|
+
|
922
|
+
synchronize do |client|
|
923
|
+
command = [:bitpos, key, bit]
|
924
|
+
command << start if start
|
925
|
+
command << stop if stop
|
926
|
+
client.call(command)
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
909
930
|
# Set the string value of a key and return its old value.
|
910
931
|
#
|
911
932
|
# @param [String] key
|
@@ -2415,6 +2436,39 @@ class Redis
|
|
2415
2436
|
end
|
2416
2437
|
end
|
2417
2438
|
|
2439
|
+
# Add one or more members to a HyperLogLog structure.
|
2440
|
+
#
|
2441
|
+
# @param [String] key
|
2442
|
+
# @param [String, Array<String>] member one member, or array of members
|
2443
|
+
# @return [Boolean] true if at least 1 HyperLogLog internal register was altered. false otherwise.
|
2444
|
+
def pfadd(key, member)
|
2445
|
+
synchronize do |client|
|
2446
|
+
client.call([:pfadd, key, member], &_boolify)
|
2447
|
+
end
|
2448
|
+
end
|
2449
|
+
|
2450
|
+
# Get the approximate cardinality of members added to HyperLogLog structure.
|
2451
|
+
#
|
2452
|
+
# @param [String] key
|
2453
|
+
# @return [Fixnum]
|
2454
|
+
def pfcount(key)
|
2455
|
+
synchronize do |client|
|
2456
|
+
client.call([:pfcount, key])
|
2457
|
+
end
|
2458
|
+
end
|
2459
|
+
|
2460
|
+
# Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
|
2461
|
+
# the observed Sets of the source HyperLogLog structures.
|
2462
|
+
#
|
2463
|
+
# @param [String] dest_key destination key
|
2464
|
+
# @param [String, Array<String>] source_key source key, or array of keys
|
2465
|
+
# @return [Boolean]
|
2466
|
+
def pfmerge(dest_key, *source_key)
|
2467
|
+
synchronize do |client|
|
2468
|
+
client.call([:pfmerge, dest_key, *source_key], &_boolify_set)
|
2469
|
+
end
|
2470
|
+
end
|
2471
|
+
|
2418
2472
|
def id
|
2419
2473
|
@original_client.id
|
2420
2474
|
end
|
data/lib/redis/client.rb
CHANGED
@@ -16,7 +16,9 @@ class Redis
|
|
16
16
|
:db => 0,
|
17
17
|
:driver => nil,
|
18
18
|
:id => nil,
|
19
|
-
:tcp_keepalive => 0
|
19
|
+
:tcp_keepalive => 0,
|
20
|
+
:reconnect_attempts => 1,
|
21
|
+
:inherit_socket => false
|
20
22
|
}
|
21
23
|
|
22
24
|
def options
|
@@ -59,6 +61,10 @@ class Redis
|
|
59
61
|
@options[:driver]
|
60
62
|
end
|
61
63
|
|
64
|
+
def inherit_socket?
|
65
|
+
@options[:inherit_socket]
|
66
|
+
end
|
67
|
+
|
62
68
|
attr_accessor :logger
|
63
69
|
attr_reader :connection
|
64
70
|
attr_reader :command_map
|
@@ -218,8 +224,11 @@ class Redis
|
|
218
224
|
|
219
225
|
def io
|
220
226
|
yield
|
221
|
-
rescue TimeoutError
|
222
|
-
|
227
|
+
rescue TimeoutError => e1
|
228
|
+
# Add a message to the exception without destroying the original stack
|
229
|
+
e2 = TimeoutError.new("Connection timed out")
|
230
|
+
e2.set_backtrace(e1.backtrace)
|
231
|
+
raise e2
|
223
232
|
rescue Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EBADF, Errno::EINVAL => e
|
224
233
|
raise ConnectionError, "Connection lost (%s)" % [e.class.name.split("::").last]
|
225
234
|
end
|
@@ -271,13 +280,23 @@ class Redis
|
|
271
280
|
|
272
281
|
begin
|
273
282
|
commands.each do |name, *args|
|
274
|
-
|
283
|
+
logged_args = args.map do |a|
|
284
|
+
case
|
285
|
+
when a.respond_to?(:inspect) then a.inspect
|
286
|
+
when a.respond_to?(:to_s) then a.to_s
|
287
|
+
else
|
288
|
+
# handle poorly-behaved descendants of BasicObject
|
289
|
+
klass = a.instance_exec { (class << self; self end).superclass }
|
290
|
+
"\#<#{klass}:#{a.__id__}>"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
@logger.debug("[Redis] command=#{name.to_s.upcase} args=#{logged_args.join(' ')}")
|
275
294
|
end
|
276
295
|
|
277
296
|
t1 = Time.now
|
278
297
|
yield
|
279
298
|
ensure
|
280
|
-
@logger.debug("Redis
|
299
|
+
@logger.debug("[Redis] call_time=%0.2f ms" % ((Time.now - t1) * 1000)) if t1
|
281
300
|
end
|
282
301
|
end
|
283
302
|
|
@@ -291,26 +310,27 @@ class Redis
|
|
291
310
|
end
|
292
311
|
|
293
312
|
def ensure_connected
|
294
|
-
|
313
|
+
attempts = 0
|
295
314
|
|
296
315
|
begin
|
316
|
+
attempts += 1
|
317
|
+
|
297
318
|
if connected?
|
298
|
-
|
319
|
+
unless inherit_socket? || Process.pid == @pid
|
299
320
|
raise InheritedError,
|
300
321
|
"Tried to use a connection from a child process without reconnecting. " +
|
301
|
-
"You need to reconnect to Redis after forking
|
322
|
+
"You need to reconnect to Redis after forking " +
|
323
|
+
"or set :inherit_socket to true."
|
302
324
|
end
|
303
325
|
else
|
304
326
|
connect
|
305
327
|
end
|
306
328
|
|
307
|
-
tries += 1
|
308
|
-
|
309
329
|
yield
|
310
|
-
rescue ConnectionError
|
330
|
+
rescue ConnectionError, InheritedError
|
311
331
|
disconnect
|
312
332
|
|
313
|
-
if
|
333
|
+
if attempts <= @options[:reconnect_attempts] && @reconnect
|
314
334
|
retry
|
315
335
|
else
|
316
336
|
raise
|
@@ -359,7 +379,7 @@ class Redis
|
|
359
379
|
|
360
380
|
# Use default when option is not specified or nil
|
361
381
|
defaults.keys.each do |key|
|
362
|
-
options[key]
|
382
|
+
options[key] = defaults[key] if options[key].nil?
|
363
383
|
end
|
364
384
|
|
365
385
|
if options[:path]
|
data/lib/redis/distributed.rb
CHANGED
@@ -323,6 +323,11 @@ class Redis
|
|
323
323
|
end
|
324
324
|
end
|
325
325
|
|
326
|
+
# Return the position of the first bit set to 1 or 0 in a string.
|
327
|
+
def bitpos(key, bit, start=nil, stop=nil)
|
328
|
+
node_for(key).bitpos(key, bit, start, stop)
|
329
|
+
end
|
330
|
+
|
326
331
|
# Set the string value of a key and return its old value.
|
327
332
|
def getset(key, value)
|
328
333
|
node_for(key).getset(key, value)
|
@@ -781,6 +786,24 @@ class Redis
|
|
781
786
|
on_each_node(:script, subcommand, *args)
|
782
787
|
end
|
783
788
|
|
789
|
+
# Add one or more members to a HyperLogLog structure.
|
790
|
+
def pfadd(key, member)
|
791
|
+
node_for(key).pfadd(key, member)
|
792
|
+
end
|
793
|
+
|
794
|
+
# Get the approximate cardinality of members added to HyperLogLog structure.
|
795
|
+
def pfcount(key)
|
796
|
+
node_for(key).pfcount(key)
|
797
|
+
end
|
798
|
+
|
799
|
+
# Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
|
800
|
+
# the observed Sets of the source HyperLogLog structures.
|
801
|
+
def pfmerge(dest_key, *source_key)
|
802
|
+
ensure_same_node(:pfmerge, [dest_key, *source_key]) do |node|
|
803
|
+
node.pfmerge(dest_key, *source_key)
|
804
|
+
end
|
805
|
+
end
|
806
|
+
|
784
807
|
def _eval(cmd, args)
|
785
808
|
script = args.shift
|
786
809
|
options = args.pop if args.last.is_a?(Hash)
|
data/lib/redis/version.rb
CHANGED
data/test/bitpos_test.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
unless defined?(Enumerator)
|
6
|
+
Enumerator = Enumerable::Enumerator
|
7
|
+
end
|
8
|
+
|
9
|
+
class TestBitpos < Test::Unit::TestCase
|
10
|
+
|
11
|
+
include Helper::Client
|
12
|
+
|
13
|
+
def test_bitpos_empty_zero
|
14
|
+
target_version "2.9.11" do
|
15
|
+
r.del "foo"
|
16
|
+
assert_equal 0, r.bitpos("foo", 0)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_bitpos_empty_one
|
21
|
+
target_version "2.9.11" do
|
22
|
+
r.del "foo"
|
23
|
+
assert_equal -1, r.bitpos("foo", 1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_bitpos_zero
|
28
|
+
target_version "2.9.11" do
|
29
|
+
r.set "foo", "\xff\xf0\x00"
|
30
|
+
assert_equal 12, r.bitpos("foo", 0)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_bitpos_one
|
35
|
+
target_version "2.9.11" do
|
36
|
+
r.set "foo", "\x00\x0f\x00"
|
37
|
+
assert_equal 12, r.bitpos("foo", 1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_bitpos_zero_end_is_given
|
42
|
+
target_version "2.9.11" do
|
43
|
+
r.set "foo", "\xff\xff\xff"
|
44
|
+
assert_equal 24, r.bitpos("foo", 0)
|
45
|
+
assert_equal 24, r.bitpos("foo", 0, 0)
|
46
|
+
assert_equal -1, r.bitpos("foo", 0, 0, -1)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_bitpos_one_intervals
|
51
|
+
target_version "2.9.11" do
|
52
|
+
r.set "foo", "\x00\xff\x00"
|
53
|
+
assert_equal 8, r.bitpos("foo", 1, 0, -1)
|
54
|
+
assert_equal 8, r.bitpos("foo", 1, 1, -1)
|
55
|
+
assert_equal -1, r.bitpos("foo", 1, 2, -1)
|
56
|
+
assert_equal -1, r.bitpos("foo", 1, 2, 200)
|
57
|
+
assert_equal 8, r.bitpos("foo", 1, 1, 1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_bitpos_raise_exception_if_stop_not_start
|
62
|
+
target_version "2.9.11" do
|
63
|
+
assert_raises(ArgumentError) do
|
64
|
+
r.bitpos("foo", 0, nil, 2)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
+
require "lint/hyper_log_log"
|
5
|
+
|
6
|
+
class TestCommandsOnHyperLogLog < Test::Unit::TestCase
|
7
|
+
|
8
|
+
include Helper::Client
|
9
|
+
include Lint::HyperLogLog
|
10
|
+
|
11
|
+
def test_pfmerge
|
12
|
+
target_version "2.8.9" do
|
13
|
+
r.pfadd "foo", "s1"
|
14
|
+
r.pfadd "bar", "s2"
|
15
|
+
|
16
|
+
assert_equal true, r.pfmerge("res", "foo", "bar")
|
17
|
+
assert_equal 2, r.pfcount("res")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
+
require "lint/hyper_log_log"
|
5
|
+
|
6
|
+
class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase
|
7
|
+
|
8
|
+
include Helper::Distributed
|
9
|
+
include Lint::HyperLogLog
|
10
|
+
|
11
|
+
def test_pfmerge
|
12
|
+
target_version "2.8.9" do
|
13
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
14
|
+
r.pfadd "foo", "s1"
|
15
|
+
r.pfadd "bar", "s2"
|
16
|
+
|
17
|
+
assert r.pfmerge("res", "foo", "bar")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class TestForkSafety < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Helper::Client
|
8
|
+
include Helper::Skipable
|
9
|
+
|
10
|
+
driver(:ruby, :hiredis) do
|
11
|
+
def test_fork_safety
|
12
|
+
redis = Redis.new(OPTIONS)
|
13
|
+
redis.set "foo", 1
|
14
|
+
|
15
|
+
child_pid = fork do
|
16
|
+
begin
|
17
|
+
# InheritedError triggers a reconnect,
|
18
|
+
# so we need to disable reconnects to force
|
19
|
+
# the exception bubble up
|
20
|
+
redis.without_reconnect do
|
21
|
+
redis.set "foo", 2
|
22
|
+
end
|
23
|
+
rescue Redis::InheritedError
|
24
|
+
exit 127
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
_, status = Process.wait2(child_pid)
|
29
|
+
|
30
|
+
assert_equal 127, status.exitstatus
|
31
|
+
assert_equal "1", redis.get("foo")
|
32
|
+
|
33
|
+
rescue NotImplementedError => error
|
34
|
+
raise unless error.message =~ /fork is not available/
|
35
|
+
return skip(error.message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_fork_safety_with_enabled_inherited_socket
|
39
|
+
redis = Redis.new(OPTIONS.merge(:inherit_socket => true))
|
40
|
+
redis.set "foo", 1
|
41
|
+
|
42
|
+
child_pid = fork do
|
43
|
+
begin
|
44
|
+
# InheritedError triggers a reconnect,
|
45
|
+
# so we need to disable reconnects to force
|
46
|
+
# the exception bubble up
|
47
|
+
redis.without_reconnect do
|
48
|
+
redis.set "foo", 2
|
49
|
+
end
|
50
|
+
rescue Redis::InheritedError
|
51
|
+
exit 127
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
_, status = Process.wait2(child_pid)
|
56
|
+
|
57
|
+
assert_equal 0, status.exitstatus
|
58
|
+
assert_equal "2", redis.get("foo")
|
59
|
+
|
60
|
+
rescue NotImplementedError => error
|
61
|
+
raise unless error.message =~ /fork is not available/
|
62
|
+
return skip(error.message)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/test/helper.rb
CHANGED
@@ -40,14 +40,13 @@ def init(redis)
|
|
40
40
|
Make sure Redis is running on localhost, port #{PORT}.
|
41
41
|
This testing suite connects to the database 15.
|
42
42
|
|
43
|
-
|
44
|
-
visit <http://redis.io/download/>.
|
43
|
+
Try this once:
|
45
44
|
|
46
|
-
|
47
|
-
rake start
|
45
|
+
$ rake clean
|
48
46
|
|
49
|
-
|
50
|
-
|
47
|
+
Then run the build again:
|
48
|
+
|
49
|
+
$ rake
|
51
50
|
|
52
51
|
EOS
|
53
52
|
exit 1
|
@@ -215,4 +214,17 @@ module Helper
|
|
215
214
|
Redis::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"]))
|
216
215
|
end
|
217
216
|
end
|
217
|
+
|
218
|
+
# Basic support for `skip` in 1.8.x
|
219
|
+
# Note: YOU MUST use `return skip(message)` in order to appropriately bail
|
220
|
+
# from a running test.
|
221
|
+
module Skipable
|
222
|
+
Skipped = Class.new(RuntimeError)
|
223
|
+
|
224
|
+
def skip(message = nil, bt = caller)
|
225
|
+
return super if defined?(super)
|
226
|
+
|
227
|
+
$stderr.puts("SKIPPED: #{self} #{message || 'no reason given'}")
|
228
|
+
end
|
229
|
+
end
|
218
230
|
end
|
data/test/internals_test.rb
CHANGED
@@ -9,8 +9,8 @@ class TestInternals < Test::Unit::TestCase
|
|
9
9
|
def test_logger
|
10
10
|
r.ping
|
11
11
|
|
12
|
-
assert log.string
|
13
|
-
|
12
|
+
assert log.string["[Redis] command=PING"]
|
13
|
+
assert log.string =~ /\[Redis\] call_time=\d+\.\d+ ms/
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_logger_with_pipelining
|
@@ -19,8 +19,8 @@ class TestInternals < Test::Unit::TestCase
|
|
19
19
|
r.get "foo"
|
20
20
|
end
|
21
21
|
|
22
|
-
assert log.string["SET foo bar"]
|
23
|
-
assert log.string["GET foo"]
|
22
|
+
assert log.string[" command=SET args=\"foo\" \"bar\""]
|
23
|
+
assert log.string[" command=GET args=\"foo\""]
|
24
24
|
end
|
25
25
|
|
26
26
|
def test_recovers_from_failed_commands
|
@@ -157,7 +157,7 @@ class TestInternals < Test::Unit::TestCase
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
def close_on_ping(seq)
|
160
|
+
def close_on_ping(seq, options = {})
|
161
161
|
$request = 0
|
162
162
|
|
163
163
|
command = lambda do
|
@@ -169,7 +169,7 @@ class TestInternals < Test::Unit::TestCase
|
|
169
169
|
rv
|
170
170
|
end
|
171
171
|
|
172
|
-
redis_mock(:ping => command, :timeout => 0.1) do |redis|
|
172
|
+
redis_mock({:ping => command}, {:timeout => 0.1}.merge(options)) do |redis|
|
173
173
|
yield(redis)
|
174
174
|
end
|
175
175
|
end
|
@@ -218,6 +218,22 @@ class TestInternals < Test::Unit::TestCase
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
+
def test_retry_with_custom_reconnect_attempts
|
222
|
+
close_on_ping([0, 1], :reconnect_attempts => 2) do |redis|
|
223
|
+
assert_equal "2", redis.ping
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_retry_with_custom_reconnect_attempts_can_still_fail
|
228
|
+
close_on_ping([0, 1, 2], :reconnect_attempts => 2) do |redis|
|
229
|
+
assert_raise Redis::ConnectionError do
|
230
|
+
redis.ping
|
231
|
+
end
|
232
|
+
|
233
|
+
assert !redis.client.connected?
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
221
237
|
def test_don_t_retry_when_second_read_in_pipeline_raises_econnreset
|
222
238
|
close_on_ping([1]) do |redis|
|
223
239
|
assert_raise Redis::ConnectionError do
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Lint
|
2
|
+
|
3
|
+
module HyperLogLog
|
4
|
+
|
5
|
+
def test_pfadd
|
6
|
+
target_version "2.8.9" do
|
7
|
+
assert_equal true, r.pfadd("foo", "s1")
|
8
|
+
assert_equal true, r.pfadd("foo", "s2")
|
9
|
+
assert_equal false, r.pfadd("foo", "s1")
|
10
|
+
|
11
|
+
assert_equal 2, r.pfcount("foo")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_variadic_pfadd
|
16
|
+
target_version "2.8.9" do
|
17
|
+
assert_equal true, r.pfadd("foo", ["s1", "s2"])
|
18
|
+
assert_equal true, r.pfadd("foo", ["s1", "s2", "s3"])
|
19
|
+
|
20
|
+
assert_equal 3, r.pfcount("foo")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_pfcount
|
25
|
+
target_version "2.8.9" do
|
26
|
+
assert_equal 0, r.pfcount("foo")
|
27
|
+
|
28
|
+
assert_equal true, r.pfadd("foo", "s1")
|
29
|
+
|
30
|
+
assert_equal 1, r.pfcount("foo")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_variadic_pfcount
|
35
|
+
target_version "2.8.9" do
|
36
|
+
assert_equal 0, r.pfcount(["foo", "bar"])
|
37
|
+
|
38
|
+
assert_equal true, r.pfadd("foo", "s1")
|
39
|
+
assert_equal true, r.pfadd("bar", "s1")
|
40
|
+
assert_equal true, r.pfadd("bar", "s2")
|
41
|
+
|
42
|
+
assert_equal 2, r.pfcount(["foo", "bar"])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -16,26 +16,25 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date: 2014-
|
19
|
+
date: 2014-06-06 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: rake
|
23
23
|
requirement: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - '>='
|
25
|
+
- - ! '>='
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
type: :development
|
29
29
|
prerelease: false
|
30
30
|
version_requirements: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - '>='
|
32
|
+
- - ! '>='
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
|
-
description:
|
36
|
-
|
37
|
-
|
38
|
-
client-side sharding, pipelining, and an obsession for performance.
|
35
|
+
description: ! " A Ruby client that tries to match Redis' API one-to-one, while
|
36
|
+
still\n providing an idiomatic interface. It features thread-safety,\n client-side
|
37
|
+
sharding, pipelining, and an obsession for performance.\n"
|
39
38
|
email:
|
40
39
|
- redis-db@googlegroups.com
|
41
40
|
executables: []
|
@@ -48,6 +47,7 @@ files:
|
|
48
47
|
- .travis/Gemfile
|
49
48
|
- .yardopts
|
50
49
|
- CHANGELOG.md
|
50
|
+
- Gemfile
|
51
51
|
- LICENSE
|
52
52
|
- README.md
|
53
53
|
- Rakefile
|
@@ -79,9 +79,11 @@ files:
|
|
79
79
|
- lib/redis/subscribe.rb
|
80
80
|
- lib/redis/version.rb
|
81
81
|
- redis.gemspec
|
82
|
+
- test/bitpos_test.rb
|
82
83
|
- test/blocking_commands_test.rb
|
83
84
|
- test/command_map_test.rb
|
84
85
|
- test/commands_on_hashes_test.rb
|
86
|
+
- test/commands_on_hyper_log_log_test.rb
|
85
87
|
- test/commands_on_lists_test.rb
|
86
88
|
- test/commands_on_sets_test.rb
|
87
89
|
- test/commands_on_sorted_sets_test.rb
|
@@ -91,6 +93,7 @@ files:
|
|
91
93
|
- test/db/.gitkeep
|
92
94
|
- test/distributed_blocking_commands_test.rb
|
93
95
|
- test/distributed_commands_on_hashes_test.rb
|
96
|
+
- test/distributed_commands_on_hyper_log_log_test.rb
|
94
97
|
- test/distributed_commands_on_lists_test.rb
|
95
98
|
- test/distributed_commands_on_sets_test.rb
|
96
99
|
- test/distributed_commands_on_sorted_sets_test.rb
|
@@ -109,11 +112,13 @@ files:
|
|
109
112
|
- test/distributed_transactions_test.rb
|
110
113
|
- test/encoding_test.rb
|
111
114
|
- test/error_replies_test.rb
|
115
|
+
- test/fork_safety_test.rb
|
112
116
|
- test/helper.rb
|
113
117
|
- test/helper_test.rb
|
114
118
|
- test/internals_test.rb
|
115
119
|
- test/lint/blocking_commands.rb
|
116
120
|
- test/lint/hashes.rb
|
121
|
+
- test/lint/hyper_log_log.rb
|
117
122
|
- test/lint/lists.rb
|
118
123
|
- test/lint/sets.rb
|
119
124
|
- test/lint/sorted_sets.rb
|
@@ -148,18 +153,83 @@ require_paths:
|
|
148
153
|
- lib
|
149
154
|
required_ruby_version: !ruby/object:Gem::Requirement
|
150
155
|
requirements:
|
151
|
-
- - '>='
|
156
|
+
- - ! '>='
|
152
157
|
- !ruby/object:Gem::Version
|
153
158
|
version: '0'
|
154
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
160
|
requirements:
|
156
|
-
- - '>='
|
161
|
+
- - ! '>='
|
157
162
|
- !ruby/object:Gem::Version
|
158
163
|
version: '0'
|
159
164
|
requirements: []
|
160
165
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.
|
166
|
+
rubygems_version: 2.2.2
|
162
167
|
signing_key:
|
163
168
|
specification_version: 4
|
164
169
|
summary: A Ruby client library for Redis
|
165
|
-
test_files:
|
170
|
+
test_files:
|
171
|
+
- test/bitpos_test.rb
|
172
|
+
- test/blocking_commands_test.rb
|
173
|
+
- test/command_map_test.rb
|
174
|
+
- test/commands_on_hashes_test.rb
|
175
|
+
- test/commands_on_hyper_log_log_test.rb
|
176
|
+
- test/commands_on_lists_test.rb
|
177
|
+
- test/commands_on_sets_test.rb
|
178
|
+
- test/commands_on_sorted_sets_test.rb
|
179
|
+
- test/commands_on_strings_test.rb
|
180
|
+
- test/commands_on_value_types_test.rb
|
181
|
+
- test/connection_handling_test.rb
|
182
|
+
- test/db/.gitkeep
|
183
|
+
- test/distributed_blocking_commands_test.rb
|
184
|
+
- test/distributed_commands_on_hashes_test.rb
|
185
|
+
- test/distributed_commands_on_hyper_log_log_test.rb
|
186
|
+
- test/distributed_commands_on_lists_test.rb
|
187
|
+
- test/distributed_commands_on_sets_test.rb
|
188
|
+
- test/distributed_commands_on_sorted_sets_test.rb
|
189
|
+
- test/distributed_commands_on_strings_test.rb
|
190
|
+
- test/distributed_commands_on_value_types_test.rb
|
191
|
+
- test/distributed_commands_requiring_clustering_test.rb
|
192
|
+
- test/distributed_connection_handling_test.rb
|
193
|
+
- test/distributed_internals_test.rb
|
194
|
+
- test/distributed_key_tags_test.rb
|
195
|
+
- test/distributed_persistence_control_commands_test.rb
|
196
|
+
- test/distributed_publish_subscribe_test.rb
|
197
|
+
- test/distributed_remote_server_control_commands_test.rb
|
198
|
+
- test/distributed_scripting_test.rb
|
199
|
+
- test/distributed_sorting_test.rb
|
200
|
+
- test/distributed_test.rb
|
201
|
+
- test/distributed_transactions_test.rb
|
202
|
+
- test/encoding_test.rb
|
203
|
+
- test/error_replies_test.rb
|
204
|
+
- test/fork_safety_test.rb
|
205
|
+
- test/helper.rb
|
206
|
+
- test/helper_test.rb
|
207
|
+
- test/internals_test.rb
|
208
|
+
- test/lint/blocking_commands.rb
|
209
|
+
- test/lint/hashes.rb
|
210
|
+
- test/lint/hyper_log_log.rb
|
211
|
+
- test/lint/lists.rb
|
212
|
+
- test/lint/sets.rb
|
213
|
+
- test/lint/sorted_sets.rb
|
214
|
+
- test/lint/strings.rb
|
215
|
+
- test/lint/value_types.rb
|
216
|
+
- test/persistence_control_commands_test.rb
|
217
|
+
- test/pipelining_commands_test.rb
|
218
|
+
- test/publish_subscribe_test.rb
|
219
|
+
- test/remote_server_control_commands_test.rb
|
220
|
+
- test/scanning_test.rb
|
221
|
+
- test/scripting_test.rb
|
222
|
+
- test/sorting_test.rb
|
223
|
+
- test/support/connection/hiredis.rb
|
224
|
+
- test/support/connection/ruby.rb
|
225
|
+
- test/support/connection/synchrony.rb
|
226
|
+
- test/support/redis_mock.rb
|
227
|
+
- test/support/wire/synchrony.rb
|
228
|
+
- test/support/wire/thread.rb
|
229
|
+
- test/synchrony_driver.rb
|
230
|
+
- test/test.conf
|
231
|
+
- test/thread_safety_test.rb
|
232
|
+
- test/transactions_test.rb
|
233
|
+
- test/unknown_commands_test.rb
|
234
|
+
- test/url_param_test.rb
|
235
|
+
has_rdoc:
|