dalli 3.0.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dalli might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +11 -5
- data/History.md +21 -0
- data/README.md +25 -134
- data/lib/dalli/cas/client.rb +2 -0
- data/lib/dalli/client.rb +85 -228
- data/lib/dalli/compressor.rb +13 -4
- data/lib/dalli/key_manager.rb +113 -0
- data/lib/dalli/options.rb +5 -5
- data/lib/dalli/pipelined_getter.rb +175 -0
- data/lib/dalli/protocol/binary/request_formatter.rb +109 -0
- data/lib/dalli/protocol/binary/response_header.rb +36 -0
- data/lib/dalli/protocol/binary/response_processor.rb +178 -0
- data/lib/dalli/protocol/binary/sasl_authentication.rb +60 -0
- data/lib/dalli/protocol/binary.rb +312 -456
- data/lib/dalli/protocol/response_buffer.rb +50 -0
- data/lib/dalli/protocol/server_config_parser.rb +23 -6
- data/lib/dalli/protocol/value_marshaller.rb +59 -0
- data/lib/dalli/protocol/value_serializer.rb +91 -0
- data/lib/dalli/protocol.rb +2 -3
- data/lib/dalli/ring.rb +95 -35
- data/lib/dalli/server.rb +2 -2
- data/lib/dalli/servers_arg_normalizer.rb +54 -0
- data/lib/dalli/socket.rb +101 -55
- data/lib/dalli/version.rb +3 -1
- data/lib/dalli.rb +38 -14
- data/lib/rack/session/dalli.rb +95 -76
- metadata +79 -6
data/lib/dalli/socket.rb
CHANGED
@@ -4,99 +4,145 @@ require 'openssl'
|
|
4
4
|
require 'rbconfig'
|
5
5
|
|
6
6
|
module Dalli
|
7
|
+
##
|
8
|
+
# Various socket implementations used by Dalli.
|
9
|
+
##
|
7
10
|
module Socket
|
11
|
+
##
|
12
|
+
# Common methods for all socket implementations.
|
13
|
+
##
|
8
14
|
module InstanceMethods
|
9
|
-
|
10
15
|
def readfull(count)
|
11
|
-
value = +
|
16
|
+
value = +''
|
12
17
|
loop do
|
13
18
|
result = read_nonblock(count - value.bytesize, exception: false)
|
14
|
-
|
15
|
-
raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select([self], nil, nil, options[:socket_timeout])
|
16
|
-
elsif result == :wait_writable
|
17
|
-
raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select(nil, [self], nil, options[:socket_timeout])
|
18
|
-
elsif result
|
19
|
-
value << result
|
20
|
-
else
|
21
|
-
raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
|
22
|
-
end
|
19
|
+
value << result if append_to_buffer?(result)
|
23
20
|
break if value.bytesize == count
|
24
21
|
end
|
25
22
|
value
|
26
23
|
end
|
27
24
|
|
28
25
|
def read_available
|
29
|
-
value = +
|
26
|
+
value = +''
|
30
27
|
loop do
|
31
28
|
result = read_nonblock(8196, exception: false)
|
32
|
-
if result
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
elsif result
|
37
|
-
value << result
|
38
|
-
else
|
39
|
-
raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
|
40
|
-
end
|
29
|
+
break if WAIT_RCS.include?(result)
|
30
|
+
raise Errno::ECONNRESET, "Connection reset: #{logged_options.inspect}" unless result
|
31
|
+
|
32
|
+
value << result
|
41
33
|
end
|
42
34
|
value
|
43
35
|
end
|
44
36
|
|
45
|
-
|
46
|
-
|
37
|
+
WAIT_RCS = %i[wait_writable wait_readable].freeze
|
38
|
+
|
39
|
+
def append_to_buffer?(result)
|
40
|
+
raise Timeout::Error, "IO timeout: #{logged_options.inspect}" if nonblock_timed_out?(result)
|
41
|
+
raise Errno::ECONNRESET, "Connection reset: #{logged_options.inspect}" unless result
|
42
|
+
|
43
|
+
!WAIT_RCS.include?(result)
|
44
|
+
end
|
45
|
+
|
46
|
+
def nonblock_timed_out?(result)
|
47
|
+
return true if result == :wait_readable && !wait_readable(options[:socket_timeout])
|
48
|
+
|
49
|
+
# TODO: Do we actually need this? Looks to be only used in read_nonblock
|
50
|
+
result == :wait_writable && !wait_writable(options[:socket_timeout])
|
51
|
+
end
|
52
|
+
|
53
|
+
FILTERED_OUT_OPTIONS = %i[username password].freeze
|
54
|
+
def logged_options
|
55
|
+
options.reject { |k, _| FILTERED_OUT_OPTIONS.include? k }
|
47
56
|
end
|
48
57
|
end
|
49
58
|
|
59
|
+
##
|
60
|
+
# Wraps the below TCP socket class in the case where the client
|
61
|
+
# has configured a TLS/SSL connection between Dalli and the
|
62
|
+
# Memcached server.
|
63
|
+
##
|
50
64
|
class SSLSocket < ::OpenSSL::SSL::SSLSocket
|
51
65
|
include Dalli::Socket::InstanceMethods
|
52
66
|
def options
|
53
67
|
io.options
|
54
68
|
end
|
69
|
+
|
70
|
+
unless method_defined?(:wait_readable)
|
71
|
+
def wait_readable(timeout = nil)
|
72
|
+
to_io.wait_readable(timeout)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
unless method_defined?(:wait_writable)
|
77
|
+
def wait_writable(timeout = nil)
|
78
|
+
to_io.wait_writable(timeout)
|
79
|
+
end
|
80
|
+
end
|
55
81
|
end
|
56
82
|
|
83
|
+
##
|
84
|
+
# A standard TCP socket between the Dalli client and the Memcached server.
|
85
|
+
##
|
57
86
|
class TCP < TCPSocket
|
58
87
|
include Dalli::Socket::InstanceMethods
|
59
|
-
|
88
|
+
# options - supports enhanced logging in the case of a timeout
|
89
|
+
attr_accessor :options
|
60
90
|
|
61
|
-
def self.open(host, port,
|
91
|
+
def self.open(host, port, options = {})
|
62
92
|
Timeout.timeout(options[:socket_timeout]) do
|
63
93
|
sock = new(host, port)
|
64
|
-
sock.options = {host: host, port: port}.merge(options)
|
65
|
-
sock
|
66
|
-
|
67
|
-
sock
|
68
|
-
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
|
69
|
-
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
|
70
|
-
|
71
|
-
return sock unless options[:ssl_context]
|
72
|
-
|
73
|
-
ssl_socket = Dalli::Socket::SSLSocket.new(sock, options[:ssl_context])
|
74
|
-
ssl_socket.hostname = host
|
75
|
-
ssl_socket.sync_close = true
|
76
|
-
ssl_socket.connect
|
77
|
-
ssl_socket
|
94
|
+
sock.options = { host: host, port: port }.merge(options)
|
95
|
+
init_socket_options(sock, options)
|
96
|
+
|
97
|
+
options[:ssl_context] ? wrapping_ssl_socket(sock, host, options[:ssl_context]) : sock
|
78
98
|
end
|
79
99
|
end
|
80
|
-
end
|
81
|
-
end
|
82
100
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
101
|
+
def self.init_socket_options(sock, options)
|
102
|
+
sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
|
103
|
+
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
|
104
|
+
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
|
105
|
+
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.wrapping_ssl_socket(tcp_socket, host, ssl_context)
|
109
|
+
ssl_socket = Dalli::Socket::SSLSocket.new(tcp_socket, ssl_context)
|
110
|
+
ssl_socket.hostname = host
|
111
|
+
ssl_socket.sync_close = true
|
112
|
+
ssl_socket.connect
|
113
|
+
ssl_socket
|
87
114
|
end
|
88
115
|
end
|
89
|
-
else
|
90
|
-
class Dalli::Socket::UNIX < UNIXSocket
|
91
|
-
include Dalli::Socket::InstanceMethods
|
92
|
-
attr_accessor :options, :server
|
93
116
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
117
|
+
if /mingw|mswin/.match?(RbConfig::CONFIG['host_os'])
|
118
|
+
##
|
119
|
+
# UNIX domain sockets are not supported on Windows platforms.
|
120
|
+
##
|
121
|
+
class UNIX
|
122
|
+
def initialize(*_args)
|
123
|
+
raise Dalli::DalliError, 'Unix sockets are not supported on Windows platform.'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
else
|
127
|
+
|
128
|
+
##
|
129
|
+
# UNIX represents a UNIX domain socket, which is an interprocess communication
|
130
|
+
# mechanism between processes on the same host. Used when the Memcached server
|
131
|
+
# is running on the same machine as the Dalli client.
|
132
|
+
##
|
133
|
+
class UNIX < UNIXSocket
|
134
|
+
include Dalli::Socket::InstanceMethods
|
135
|
+
|
136
|
+
# options - supports enhanced logging in the case of a timeout
|
137
|
+
# server - used to support IO.select in the pipelined getter
|
138
|
+
attr_accessor :options
|
139
|
+
|
140
|
+
def self.open(path, options = {})
|
141
|
+
Timeout.timeout(options[:socket_timeout]) do
|
142
|
+
sock = new(path)
|
143
|
+
sock.options = { path: path }.merge(options)
|
144
|
+
sock
|
145
|
+
end
|
100
146
|
end
|
101
147
|
end
|
102
148
|
end
|
data/lib/dalli/version.rb
CHANGED
data/lib/dalli.rb
CHANGED
@@ -1,33 +1,38 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require "dalli/protocol"
|
7
|
-
require "dalli/protocol/binary"
|
8
|
-
require "dalli/protocol/server_config_parser"
|
9
|
-
require "dalli/protocol/ttl_sanitizer"
|
10
|
-
require 'dalli/protocol/value_compressor'
|
11
|
-
require "dalli/socket"
|
12
|
-
require "dalli/version"
|
13
|
-
require "dalli/options"
|
14
|
-
|
3
|
+
##
|
4
|
+
# Namespace for all Dalli code.
|
5
|
+
##
|
15
6
|
module Dalli
|
16
|
-
autoload :Server,
|
7
|
+
autoload :Server, 'dalli/server'
|
17
8
|
|
18
9
|
# generic error
|
19
10
|
class DalliError < RuntimeError; end
|
11
|
+
|
20
12
|
# socket/server communication error
|
21
13
|
class NetworkError < DalliError; end
|
14
|
+
|
22
15
|
# no server available/alive error
|
23
16
|
class RingError < DalliError; end
|
17
|
+
|
24
18
|
# application error in marshalling serialization
|
25
19
|
class MarshalError < DalliError; end
|
20
|
+
|
26
21
|
# application error in marshalling deserialization or decompression
|
27
22
|
class UnmarshalError < DalliError; end
|
23
|
+
|
28
24
|
# payload too big for memcached
|
29
25
|
class ValueOverMaxSize < DalliError; end
|
30
26
|
|
27
|
+
# operation is not permitted in a multi block
|
28
|
+
class NotPermittedMultiOpError < DalliError; end
|
29
|
+
|
30
|
+
# Implements the NullObject pattern to store an application-defined value for 'Key not found' responses.
|
31
|
+
class NilObject; end # rubocop:disable Lint/EmptyClass
|
32
|
+
NOT_FOUND = NilObject.new
|
33
|
+
|
34
|
+
MULTI_KEY = :dalli_multi
|
35
|
+
|
31
36
|
def self.logger
|
32
37
|
@logger ||= (rails_logger || default_logger)
|
33
38
|
end
|
@@ -38,7 +43,7 @@ module Dalli
|
|
38
43
|
end
|
39
44
|
|
40
45
|
def self.default_logger
|
41
|
-
require
|
46
|
+
require 'logger'
|
42
47
|
l = Logger.new($stdout)
|
43
48
|
l.level = Logger::INFO
|
44
49
|
l
|
@@ -48,3 +53,22 @@ module Dalli
|
|
48
53
|
@logger = logger
|
49
54
|
end
|
50
55
|
end
|
56
|
+
|
57
|
+
require_relative 'dalli/version'
|
58
|
+
|
59
|
+
require_relative 'dalli/compressor'
|
60
|
+
require_relative 'dalli/client'
|
61
|
+
require_relative 'dalli/key_manager'
|
62
|
+
require_relative 'dalli/pipelined_getter'
|
63
|
+
require_relative 'dalli/ring'
|
64
|
+
require_relative 'dalli/protocol'
|
65
|
+
require_relative 'dalli/protocol/binary'
|
66
|
+
require_relative 'dalli/protocol/response_buffer'
|
67
|
+
require_relative 'dalli/protocol/server_config_parser'
|
68
|
+
require_relative 'dalli/protocol/ttl_sanitizer'
|
69
|
+
require_relative 'dalli/protocol/value_compressor'
|
70
|
+
require_relative 'dalli/protocol/value_marshaller'
|
71
|
+
require_relative 'dalli/protocol/value_serializer'
|
72
|
+
require_relative 'dalli/servers_arg_normalizer'
|
73
|
+
require_relative 'dalli/socket'
|
74
|
+
require_relative 'dalli/options'
|
data/lib/rack/session/dalli.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'rack/session/abstract/id'
|
3
4
|
require 'dalli'
|
4
5
|
require 'connection_pool'
|
6
|
+
require 'English'
|
5
7
|
|
6
8
|
module Rack
|
7
9
|
module Session
|
8
|
-
|
9
|
-
|
10
|
+
# Rack::Session::Dalli provides memcached based session management.
|
11
|
+
class Dalli < Abstract::PersistedSecure
|
12
|
+
attr_reader :data
|
10
13
|
|
14
|
+
# Don't freeze this until we fix the specs/implementation
|
15
|
+
# rubocop:disable Style/MutableConstant
|
11
16
|
DEFAULT_DALLI_OPTIONS = {
|
12
|
-
:
|
13
|
-
:memcache_server => 'localhost:11211'
|
17
|
+
namespace: 'rack:session'
|
14
18
|
}
|
19
|
+
# rubocop:enable Style/MutableConstant
|
15
20
|
|
16
21
|
# Brings in a new Rack::Session::Dalli middleware with the given
|
17
22
|
# `:memcache_server`. The server is either a hostname, or a
|
@@ -27,25 +32,14 @@ module Rack
|
|
27
32
|
# ENV['MEMCACHE_SERVERS'] and use that value if it is available, or fall
|
28
33
|
# back to the same default behavior described above.
|
29
34
|
#
|
30
|
-
# Rack::Session::Dalli
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# Dalli::Client (or ConnectionPool) and use that instead of letting
|
35
|
-
# Rack::Session::Dalli instantiate it on your behalf, simply pass it in
|
36
|
-
# as the `:cache` option. Please note that you will be responsible for
|
37
|
-
# setting the namespace and any other options on Dalli::Client.
|
38
|
-
#
|
39
|
-
# Secondly, if you're not using the `:cache` option, Rack::Session::Dalli
|
40
|
-
# accepts the same options as Dalli::Client, so it's worth reviewing its
|
41
|
-
# documentation. Perhaps most importantly, if you don't specify a
|
42
|
-
# `:namespace` option, Rack::Session::Dalli will default to using
|
43
|
-
# "rack:session".
|
35
|
+
# Rack::Session::Dalli accepts the same options as Dalli::Client, so
|
36
|
+
# it's worth reviewing its documentation. Perhaps most importantly,
|
37
|
+
# if you don't specify a `:namespace` option, Rack::Session::Dalli
|
38
|
+
# will default to using 'rack:session'.
|
44
39
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
# the corresponding entry in memcached.
|
40
|
+
# It is not recommended to set `:expires_in`. Instead, use `:expire_after`,
|
41
|
+
# which will control both the expiration of the client cookie as well
|
42
|
+
# as the expiration of the corresponding entry in memcached.
|
49
43
|
#
|
50
44
|
# Rack::Session::Dalli also accepts a host of options that control how
|
51
45
|
# the sessions and session cookies are managed, including the
|
@@ -67,96 +61,121 @@ module Rack
|
|
67
61
|
# for more information about it and its default options (which would only
|
68
62
|
# be applicable if you supplied one of the two options, but not both).
|
69
63
|
#
|
70
|
-
def initialize(app, options={})
|
64
|
+
def initialize(app, options = {})
|
71
65
|
# Parent uses DEFAULT_OPTIONS to build @default_options for Rack::Session
|
72
66
|
super
|
73
67
|
|
74
68
|
# Determine the default TTL for newly-created sessions
|
75
|
-
@default_ttl = ttl
|
76
|
-
|
77
|
-
# Normalize and validate passed options
|
78
|
-
mserv, mopts, popts = extract_dalli_options(options)
|
79
|
-
|
80
|
-
@pool = ConnectionPool.new(popts || {}) { ::Dalli::Client.new(mserv, mopts) }
|
69
|
+
@default_ttl = ttl(@default_options[:expire_after])
|
70
|
+
@data = build_data_source(options)
|
81
71
|
end
|
82
72
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
redo # generate a new sid and try again
|
90
|
-
end
|
91
|
-
end
|
92
|
-
[sid, session]
|
73
|
+
def find_session(_req, sid)
|
74
|
+
with_dalli_client([nil, {}]) do |dc|
|
75
|
+
existing_session = existing_session_for_sid(dc, sid)
|
76
|
+
return [sid, existing_session] unless existing_session.nil?
|
77
|
+
|
78
|
+
[create_sid_with_empty_session(dc), {}]
|
93
79
|
end
|
94
80
|
end
|
95
81
|
|
96
|
-
def
|
97
|
-
return false unless
|
82
|
+
def write_session(_req, sid, session, options)
|
83
|
+
return false unless sid
|
98
84
|
|
99
|
-
|
100
|
-
dc.set(
|
101
|
-
|
85
|
+
with_dalli_client(false) do |dc|
|
86
|
+
dc.set(memcached_key_from_sid(sid), session, ttl(options[:expire_after]))
|
87
|
+
sid
|
102
88
|
end
|
103
89
|
end
|
104
90
|
|
105
|
-
def
|
106
|
-
|
107
|
-
dc.delete(
|
91
|
+
def delete_session(_req, sid, options)
|
92
|
+
with_dalli_client do |dc|
|
93
|
+
dc.delete(memcached_key_from_sid(sid))
|
108
94
|
generate_sid_with(dc) unless options[:drop]
|
109
95
|
end
|
110
96
|
end
|
111
97
|
|
112
|
-
|
113
|
-
|
98
|
+
private
|
99
|
+
|
100
|
+
def memcached_key_from_sid(sid)
|
101
|
+
sid.private_id
|
114
102
|
end
|
115
103
|
|
116
|
-
def
|
117
|
-
|
104
|
+
def existing_session_for_sid(client, sid)
|
105
|
+
return nil unless sid && !sid.empty?
|
106
|
+
|
107
|
+
client.get(memcached_key_from_sid(sid))
|
118
108
|
end
|
119
109
|
|
120
|
-
def
|
121
|
-
|
110
|
+
def create_sid_with_empty_session(client)
|
111
|
+
loop do
|
112
|
+
sid = generate_sid_with(client)
|
113
|
+
|
114
|
+
break sid if client.add(memcached_key_from_sid(sid), {}, @default_ttl)
|
115
|
+
end
|
122
116
|
end
|
123
117
|
|
124
|
-
|
118
|
+
def generate_sid_with(client)
|
119
|
+
loop do
|
120
|
+
raw_sid = generate_sid
|
121
|
+
sid = raw_sid.is_a?(String) ? Rack::Session::SessionId.new(raw_sid) : raw_sid
|
122
|
+
break sid unless client.get(memcached_key_from_sid(sid))
|
123
|
+
end
|
124
|
+
end
|
125
125
|
|
126
|
-
def
|
127
|
-
|
126
|
+
def build_data_source(options)
|
127
|
+
server_configurations, client_options, pool_options = extract_dalli_options(options)
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
popts[:size] = mopts.delete :pool_size if mopts[:pool_size]
|
137
|
-
popts[:timeout] = mopts.delete :pool_timeout if mopts[:pool_timeout]
|
138
|
-
mopts[:threadsafe] = true
|
129
|
+
if pool_options.empty?
|
130
|
+
::Dalli::Client.new(server_configurations, client_options)
|
131
|
+
else
|
132
|
+
ensure_connection_pool_added!
|
133
|
+
ConnectionPool.new(pool_options) do
|
134
|
+
::Dalli::Client.new(server_configurations, client_options.merge(threadsafe: false))
|
135
|
+
end
|
139
136
|
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def extract_dalli_options(options)
|
140
|
+
raise 'Rack::Session::Dalli no longer supports the :cache option.' if options[:cache]
|
141
|
+
|
142
|
+
client_options = retrieve_client_options(options)
|
143
|
+
server_configurations = client_options.delete(:memcache_server)
|
140
144
|
|
141
|
-
[
|
145
|
+
[server_configurations, client_options, retrieve_pool_options(options)]
|
142
146
|
end
|
143
147
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
+
def retrieve_client_options(options)
|
149
|
+
# Filter out Rack::Session-specific options and apply our defaults
|
150
|
+
filtered_opts = options.reject { |k, _| DEFAULT_OPTIONS.key? k }
|
151
|
+
DEFAULT_DALLI_OPTIONS.merge(filtered_opts)
|
152
|
+
end
|
153
|
+
|
154
|
+
def retrieve_pool_options(options)
|
155
|
+
{}.tap do |pool_options|
|
156
|
+
pool_options[:size] = options.delete(:pool_size) if options[:pool_size]
|
157
|
+
pool_options[:timeout] = options.delete(:pool_timeout) if options[:pool_timeout]
|
148
158
|
end
|
149
159
|
end
|
150
160
|
|
151
|
-
def
|
152
|
-
|
161
|
+
def ensure_connection_pool_added!
|
162
|
+
require 'connection_pool'
|
163
|
+
rescue LoadError => e
|
164
|
+
warn "You don't have connection_pool installed in your application. "\
|
165
|
+
'Please add it to your Gemfile and run bundle install'
|
166
|
+
raise e
|
167
|
+
end
|
168
|
+
|
169
|
+
def with_dalli_client(result_on_error = nil, &block)
|
170
|
+
@data.with(&block)
|
153
171
|
rescue ::Dalli::DalliError, Errno::ECONNREFUSED
|
154
|
-
raise if
|
172
|
+
raise if /undefined class/.match?($ERROR_INFO.message)
|
173
|
+
|
155
174
|
if $VERBOSE
|
156
175
|
warn "#{self} is unable to find memcached server."
|
157
|
-
warn
|
176
|
+
warn $ERROR_INFO.inspect
|
158
177
|
end
|
159
|
-
|
178
|
+
result_on_error
|
160
179
|
end
|
161
180
|
|
162
181
|
def ttl(expire_after)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dalli
|
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
|
- Peter M. Goldstein
|
@@ -9,10 +9,44 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-12-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: connection_pool
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: rack
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '2.0'
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.2.0
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - "~>"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '2.0'
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.0
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rubocop
|
16
50
|
requirement: !ruby/object:Gem::Requirement
|
17
51
|
requirements:
|
18
52
|
- - ">="
|
@@ -26,7 +60,35 @@ dependencies:
|
|
26
60
|
- !ruby/object:Gem::Version
|
27
61
|
version: '0'
|
28
62
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
63
|
+
name: rubocop-minitest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rubocop-performance
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: rubocop-rake
|
30
92
|
requirement: !ruby/object:Gem::Requirement
|
31
93
|
requirements:
|
32
94
|
- - ">="
|
@@ -55,21 +117,32 @@ files:
|
|
55
117
|
- lib/dalli/cas/client.rb
|
56
118
|
- lib/dalli/client.rb
|
57
119
|
- lib/dalli/compressor.rb
|
120
|
+
- lib/dalli/key_manager.rb
|
58
121
|
- lib/dalli/options.rb
|
122
|
+
- lib/dalli/pipelined_getter.rb
|
59
123
|
- lib/dalli/protocol.rb
|
60
124
|
- lib/dalli/protocol/binary.rb
|
125
|
+
- lib/dalli/protocol/binary/request_formatter.rb
|
126
|
+
- lib/dalli/protocol/binary/response_header.rb
|
127
|
+
- lib/dalli/protocol/binary/response_processor.rb
|
128
|
+
- lib/dalli/protocol/binary/sasl_authentication.rb
|
129
|
+
- lib/dalli/protocol/response_buffer.rb
|
61
130
|
- lib/dalli/protocol/server_config_parser.rb
|
62
131
|
- lib/dalli/protocol/ttl_sanitizer.rb
|
63
132
|
- lib/dalli/protocol/value_compressor.rb
|
133
|
+
- lib/dalli/protocol/value_marshaller.rb
|
134
|
+
- lib/dalli/protocol/value_serializer.rb
|
64
135
|
- lib/dalli/ring.rb
|
65
136
|
- lib/dalli/server.rb
|
137
|
+
- lib/dalli/servers_arg_normalizer.rb
|
66
138
|
- lib/dalli/socket.rb
|
67
139
|
- lib/dalli/version.rb
|
68
140
|
- lib/rack/session/dalli.rb
|
69
141
|
homepage: https://github.com/petergoldstein/dalli
|
70
142
|
licenses:
|
71
143
|
- MIT
|
72
|
-
metadata:
|
144
|
+
metadata:
|
145
|
+
rubygems_mfa_required: 'true'
|
73
146
|
post_install_message:
|
74
147
|
rdoc_options: []
|
75
148
|
require_paths:
|
@@ -78,14 +151,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
151
|
requirements:
|
79
152
|
- - ">="
|
80
153
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
154
|
+
version: '2.5'
|
82
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
156
|
requirements:
|
84
157
|
- - ">="
|
85
158
|
- !ruby/object:Gem::Version
|
86
159
|
version: '0'
|
87
160
|
requirements: []
|
88
|
-
rubygems_version: 3.2.
|
161
|
+
rubygems_version: 3.2.31
|
89
162
|
signing_key:
|
90
163
|
specification_version: 4
|
91
164
|
summary: High performance memcached client for Ruby
|