redis-client 0.2.1 → 0.5.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 +4 -4
- data/CHANGELOG.md +19 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +2 -3
- data/README.md +71 -8
- data/Rakefile +43 -23
- data/lib/redis_client/command_builder.rb +91 -0
- data/lib/redis_client/config.rb +19 -50
- data/lib/redis_client/connection_mixin.rb +40 -0
- data/lib/redis_client/decorator.rb +84 -0
- data/lib/redis_client/pooled.rb +38 -30
- data/lib/redis_client/ruby_connection/buffered_io.rb +153 -0
- data/lib/redis_client/{resp3.rb → ruby_connection/resp3.rb} +0 -26
- data/lib/redis_client/{connection.rb → ruby_connection.rb} +26 -31
- data/lib/redis_client/version.rb +1 -1
- data/lib/redis_client.rb +183 -36
- data/redis-client.gemspec +2 -4
- metadata +12 -59
- data/.rubocop.yml +0 -190
- data/ext/redis_client/hiredis/export.clang +0 -2
- data/ext/redis_client/hiredis/export.gcc +0 -7
- data/ext/redis_client/hiredis/extconf.rb +0 -61
- data/ext/redis_client/hiredis/hiredis_connection.c +0 -708
- data/ext/redis_client/hiredis/vendor/.gitignore +0 -9
- data/ext/redis_client/hiredis/vendor/.travis.yml +0 -131
- data/ext/redis_client/hiredis/vendor/CHANGELOG.md +0 -364
- data/ext/redis_client/hiredis/vendor/CMakeLists.txt +0 -165
- data/ext/redis_client/hiredis/vendor/COPYING +0 -29
- data/ext/redis_client/hiredis/vendor/Makefile +0 -308
- data/ext/redis_client/hiredis/vendor/README.md +0 -664
- data/ext/redis_client/hiredis/vendor/adapters/ae.h +0 -130
- data/ext/redis_client/hiredis/vendor/adapters/glib.h +0 -156
- data/ext/redis_client/hiredis/vendor/adapters/ivykis.h +0 -84
- data/ext/redis_client/hiredis/vendor/adapters/libev.h +0 -179
- data/ext/redis_client/hiredis/vendor/adapters/libevent.h +0 -175
- data/ext/redis_client/hiredis/vendor/adapters/libuv.h +0 -117
- data/ext/redis_client/hiredis/vendor/adapters/macosx.h +0 -115
- data/ext/redis_client/hiredis/vendor/adapters/qt.h +0 -135
- data/ext/redis_client/hiredis/vendor/alloc.c +0 -86
- data/ext/redis_client/hiredis/vendor/alloc.h +0 -91
- data/ext/redis_client/hiredis/vendor/appveyor.yml +0 -24
- data/ext/redis_client/hiredis/vendor/async.c +0 -887
- data/ext/redis_client/hiredis/vendor/async.h +0 -147
- data/ext/redis_client/hiredis/vendor/async_private.h +0 -75
- data/ext/redis_client/hiredis/vendor/dict.c +0 -352
- data/ext/redis_client/hiredis/vendor/dict.h +0 -126
- data/ext/redis_client/hiredis/vendor/fmacros.h +0 -12
- data/ext/redis_client/hiredis/vendor/hiredis-config.cmake.in +0 -13
- data/ext/redis_client/hiredis/vendor/hiredis.c +0 -1174
- data/ext/redis_client/hiredis/vendor/hiredis.h +0 -336
- data/ext/redis_client/hiredis/vendor/hiredis.pc.in +0 -12
- data/ext/redis_client/hiredis/vendor/hiredis_ssl-config.cmake.in +0 -13
- data/ext/redis_client/hiredis/vendor/hiredis_ssl.h +0 -157
- data/ext/redis_client/hiredis/vendor/hiredis_ssl.pc.in +0 -12
- data/ext/redis_client/hiredis/vendor/net.c +0 -612
- data/ext/redis_client/hiredis/vendor/net.h +0 -56
- data/ext/redis_client/hiredis/vendor/read.c +0 -739
- data/ext/redis_client/hiredis/vendor/read.h +0 -129
- data/ext/redis_client/hiredis/vendor/sds.c +0 -1289
- data/ext/redis_client/hiredis/vendor/sds.h +0 -278
- data/ext/redis_client/hiredis/vendor/sdsalloc.h +0 -44
- data/ext/redis_client/hiredis/vendor/sockcompat.c +0 -248
- data/ext/redis_client/hiredis/vendor/sockcompat.h +0 -92
- data/ext/redis_client/hiredis/vendor/ssl.c +0 -544
- data/ext/redis_client/hiredis/vendor/test.c +0 -1401
- data/ext/redis_client/hiredis/vendor/test.sh +0 -78
- data/ext/redis_client/hiredis/vendor/win32.h +0 -56
- data/lib/redis_client/buffered_io.rb +0 -151
- data/lib/redis_client/hiredis_connection.rb +0 -80
data/lib/redis_client/pooled.rb
CHANGED
@@ -49,40 +49,48 @@ class RedisClient
|
|
49
49
|
pool.size
|
50
50
|
end
|
51
51
|
|
52
|
-
%w(pipelined
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
def #{method}(**kwargs, &block)
|
63
|
-
with { |r| r.#{method}(**kwargs, &block) }
|
64
|
-
end
|
65
|
-
RUBY
|
66
|
-
end
|
52
|
+
methods = %w(pipelined multi pubsub call call_once blocking_call)
|
53
|
+
iterable_methods = %w(scan sscan hscan zscan)
|
54
|
+
begin
|
55
|
+
methods.each do |method|
|
56
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
57
|
+
def #{method}(...)
|
58
|
+
with { |r| r.#{method}(...) }
|
59
|
+
end
|
60
|
+
RUBY
|
61
|
+
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
63
|
+
iterable_methods.each do |method|
|
64
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
65
|
+
def #{method}(...)
|
66
|
+
unless block_given?
|
67
|
+
return to_enum(__callee__, ...)
|
68
|
+
end
|
75
69
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
70
|
+
with { |r| r.#{method}(...) }
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
end
|
74
|
+
rescue SyntaxError
|
75
|
+
methods.each do |method|
|
76
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
77
|
+
def #{method}(*args, &block)
|
78
|
+
with { |r| r.#{method}(*args, &block) }
|
81
79
|
end
|
80
|
+
RUBY
|
81
|
+
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
iterable_methods.each do |method|
|
84
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
85
|
+
def #{method}(*args, &block)
|
86
|
+
unless block_given?
|
87
|
+
return to_enum(__callee__, *args)
|
88
|
+
end
|
89
|
+
|
90
|
+
with { |r| r.#{method}(*args, &block) }
|
91
|
+
end
|
92
|
+
RUBY
|
93
|
+
end
|
86
94
|
end
|
87
95
|
|
88
96
|
private
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "io/wait" unless IO.method_defined?(:wait_readable) && IO.method_defined?(:wait_writable)
|
4
|
+
|
5
|
+
class RedisClient
|
6
|
+
class RubyConnection
|
7
|
+
class BufferedIO
|
8
|
+
EOL = "\r\n".b.freeze
|
9
|
+
EOL_SIZE = EOL.bytesize
|
10
|
+
|
11
|
+
attr_accessor :read_timeout, :write_timeout
|
12
|
+
|
13
|
+
def initialize(io, read_timeout:, write_timeout:, chunk_size: 4096)
|
14
|
+
@io = io
|
15
|
+
@buffer = "".b
|
16
|
+
@offset = 0
|
17
|
+
@chunk_size = chunk_size
|
18
|
+
@read_timeout = read_timeout
|
19
|
+
@write_timeout = write_timeout
|
20
|
+
@blocking_reads = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def close
|
24
|
+
@io.to_io.close
|
25
|
+
end
|
26
|
+
|
27
|
+
def closed?
|
28
|
+
@io.to_io.closed?
|
29
|
+
end
|
30
|
+
|
31
|
+
def eof?
|
32
|
+
@offset >= @buffer.bytesize && @io.eof?
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_timeout(new_timeout)
|
36
|
+
new_timeout = false if new_timeout == 0
|
37
|
+
|
38
|
+
previous_read_timeout = @read_timeout
|
39
|
+
previous_blocking_reads = @blocking_reads
|
40
|
+
|
41
|
+
if new_timeout
|
42
|
+
@read_timeout = new_timeout
|
43
|
+
else
|
44
|
+
@blocking_reads = true
|
45
|
+
end
|
46
|
+
|
47
|
+
begin
|
48
|
+
yield
|
49
|
+
ensure
|
50
|
+
@read_timeout = previous_read_timeout
|
51
|
+
@blocking_reads = previous_blocking_reads
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def skip(offset)
|
56
|
+
ensure_remaining(offset)
|
57
|
+
@offset += offset
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def write(string)
|
62
|
+
total = remaining = string.bytesize
|
63
|
+
loop do
|
64
|
+
case bytes_written = @io.write_nonblock(string, exception: false)
|
65
|
+
when Integer
|
66
|
+
remaining -= bytes_written
|
67
|
+
if remaining > 0
|
68
|
+
string = string.byteslice(bytes_written..-1)
|
69
|
+
else
|
70
|
+
return total
|
71
|
+
end
|
72
|
+
when :wait_readable
|
73
|
+
@io.to_io.wait_readable(@read_timeout) or raise ReadTimeoutError
|
74
|
+
when :wait_writable
|
75
|
+
@io.to_io.wait_writable(@write_timeout) or raise WriteTimeoutError
|
76
|
+
when nil
|
77
|
+
raise Errno::ECONNRESET
|
78
|
+
else
|
79
|
+
raise "Unexpected `write_nonblock` return: #{bytes.inspect}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def getbyte
|
85
|
+
ensure_remaining(1)
|
86
|
+
byte = @buffer.getbyte(@offset)
|
87
|
+
@offset += 1
|
88
|
+
byte
|
89
|
+
end
|
90
|
+
|
91
|
+
def gets_chomp
|
92
|
+
fill_buffer(false) if @offset >= @buffer.bytesize
|
93
|
+
until eol_index = @buffer.index(EOL, @offset)
|
94
|
+
fill_buffer(false)
|
95
|
+
end
|
96
|
+
|
97
|
+
line = @buffer.byteslice(@offset, eol_index - @offset)
|
98
|
+
@offset = eol_index + EOL_SIZE
|
99
|
+
line
|
100
|
+
end
|
101
|
+
|
102
|
+
def read_chomp(bytes)
|
103
|
+
ensure_remaining(bytes + EOL_SIZE)
|
104
|
+
str = @buffer.byteslice(@offset, bytes)
|
105
|
+
@offset += bytes + EOL_SIZE
|
106
|
+
str
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def ensure_remaining(bytes)
|
112
|
+
needed = bytes - (@buffer.bytesize - @offset)
|
113
|
+
if needed > 0
|
114
|
+
fill_buffer(true, needed)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def fill_buffer(strict, size = @chunk_size)
|
119
|
+
remaining = size
|
120
|
+
empty_buffer = @offset >= @buffer.bytesize
|
121
|
+
|
122
|
+
loop do
|
123
|
+
bytes = if empty_buffer
|
124
|
+
@io.read_nonblock([remaining, @chunk_size].max, @buffer, exception: false)
|
125
|
+
else
|
126
|
+
@io.read_nonblock([remaining, @chunk_size].max, exception: false)
|
127
|
+
end
|
128
|
+
case bytes
|
129
|
+
when String
|
130
|
+
if empty_buffer
|
131
|
+
@offset = 0
|
132
|
+
empty_buffer = false
|
133
|
+
else
|
134
|
+
@buffer << bytes
|
135
|
+
end
|
136
|
+
remaining -= bytes.bytesize
|
137
|
+
return if !strict || remaining <= 0
|
138
|
+
when :wait_readable
|
139
|
+
unless @io.to_io.wait_readable(@read_timeout)
|
140
|
+
raise ReadTimeoutError unless @blocking_reads
|
141
|
+
end
|
142
|
+
when :wait_writable
|
143
|
+
@io.to_io.wait_writable(@write_timeout) or raise WriteTimeoutError
|
144
|
+
when nil
|
145
|
+
raise Errno::ECONNRESET
|
146
|
+
else
|
147
|
+
raise "Unexpected `read_nonblock` return: #{bytes.inspect}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -58,32 +58,6 @@ class RedisClient
|
|
58
58
|
String.new(encoding: Encoding::BINARY, capacity: 128)
|
59
59
|
end
|
60
60
|
|
61
|
-
def coerce_command!(command)
|
62
|
-
command = command.flat_map do |element|
|
63
|
-
case element
|
64
|
-
when Hash
|
65
|
-
element.flatten
|
66
|
-
when Set
|
67
|
-
element.to_a
|
68
|
-
else
|
69
|
-
element
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
command.map! do |element|
|
74
|
-
case element
|
75
|
-
when String
|
76
|
-
element
|
77
|
-
when Integer, Float, Symbol
|
78
|
-
element.to_s
|
79
|
-
else
|
80
|
-
raise TypeError, "Unsupported command argument type: #{element.class}"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
command
|
85
|
-
end
|
86
|
-
|
87
61
|
def dump_any(object, buffer)
|
88
62
|
method = DUMP_TYPES.fetch(object.class) do
|
89
63
|
raise TypeError, "Unsupported command argument type: #{object.class}"
|
@@ -2,47 +2,42 @@
|
|
2
2
|
|
3
3
|
require "socket"
|
4
4
|
require "openssl"
|
5
|
-
require "redis_client/
|
5
|
+
require "redis_client/connection_mixin"
|
6
|
+
require "redis_client/ruby_connection/buffered_io"
|
7
|
+
require "redis_client/ruby_connection/resp3"
|
6
8
|
|
7
9
|
class RedisClient
|
8
|
-
class
|
9
|
-
|
10
|
-
def call(command, timeout)
|
11
|
-
write(command)
|
12
|
-
result = read(timeout)
|
13
|
-
if result.is_a?(CommandError)
|
14
|
-
raise result
|
15
|
-
else
|
16
|
-
result
|
17
|
-
end
|
18
|
-
end
|
10
|
+
class RubyConnection
|
11
|
+
include ConnectionMixin
|
19
12
|
|
20
|
-
|
21
|
-
|
13
|
+
class << self
|
14
|
+
def ssl_context(ssl_params)
|
15
|
+
params = ssl_params.dup || {}
|
22
16
|
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
cert = params[:cert]
|
18
|
+
if cert.is_a?(String)
|
19
|
+
cert = File.read(cert) if File.exist?(cert)
|
20
|
+
params[:cert] = OpenSSL::X509::Certificate.new(cert)
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
exception ||= result
|
32
|
-
end
|
33
|
-
results[index] = result
|
23
|
+
key = params[:key]
|
24
|
+
if key.is_a?(String)
|
25
|
+
key = File.read(key) if File.exist?(key)
|
26
|
+
params[:key] = OpenSSL::PKey.read(key)
|
34
27
|
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
context = OpenSSL::SSL::SSLContext.new
|
30
|
+
context.set_params(params)
|
31
|
+
if context.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
32
|
+
if context.respond_to?(:verify_hostname) # Missing on JRuby
|
33
|
+
context.verify_hostname
|
34
|
+
end
|
40
35
|
end
|
36
|
+
|
37
|
+
context
|
41
38
|
end
|
42
39
|
end
|
43
40
|
|
44
|
-
include Common
|
45
|
-
|
46
41
|
SUPPORTS_RESOLV_TIMEOUT = Socket.method(:tcp).parameters.any? { |p| p.last == :resolv_timeout }
|
47
42
|
|
48
43
|
def initialize(config, connect_timeout:, read_timeout:, write_timeout:)
|
@@ -60,7 +55,7 @@ class RedisClient
|
|
60
55
|
end
|
61
56
|
|
62
57
|
if config.ssl
|
63
|
-
socket = OpenSSL::SSL::SSLSocket.new(socket, config.
|
58
|
+
socket = OpenSSL::SSL::SSLSocket.new(socket, config.ssl_context)
|
64
59
|
socket.hostname = config.host
|
65
60
|
loop do
|
66
61
|
case status = socket.connect_nonblock(exception: false)
|
data/lib/redis_client/version.rb
CHANGED