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.

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
- if result == :wait_readable
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 == :wait_readable
33
- break
34
- elsif result == :wait_writable
35
- break
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
- def safe_options
46
- options.reject { |k, v| [:username, :password].include? k }
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
- attr_accessor :options, :server
88
+ # options - supports enhanced logging in the case of a timeout
89
+ attr_accessor :options
60
90
 
61
- def self.open(host, port, server, options = {})
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.server = server
66
- sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
67
- sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
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
- if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
84
- class Dalli::Socket::UNIX
85
- def initialize(*args)
86
- raise Dalli::DalliError, 'Unix sockets are not supported on Windows platform.'
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
- def self.open(path, server, options = {})
95
- Timeout.timeout(options[:socket_timeout]) do
96
- sock = new(path)
97
- sock.options = {path: path}.merge(options)
98
- sock.server = server
99
- sock
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
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dalli
4
- VERSION = "3.0.4"
4
+ VERSION = '3.1.0'
5
+
6
+ MIN_SUPPORTED_MEMCACHED_VERSION = '1.4'
5
7
  end
data/lib/dalli.rb CHANGED
@@ -1,33 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dalli/compressor"
4
- require "dalli/client"
5
- require "dalli/ring"
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, "dalli/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 "logger"
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'
@@ -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
- class Dalli < Abstract::Persisted
9
- attr_reader :pool
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
- :namespace => 'rack:session',
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 is intended to be a drop-in replacement for
31
- # Rack::Session::Memcache. It accepts additional options that control the
32
- # behavior of Rack::Session, Dalli::Client, and an optional
33
- # ConnectionPool. First and foremost, if you wish to instantiate your own
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
- # Whether you are using the `:cache` option or not, it is not recommend
46
- # to set `:expires_in`. Instead, use `:expire_after`, which will control
47
- # both the expiration of the client cookie as well as the expiration of
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 @default_options[:expire_after]
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 get_session(env, sid)
84
- with_block([nil, {}]) do |dc|
85
- unless sid and !sid.empty? and session = dc.get(sid)
86
- old_sid, sid, session = sid, generate_sid_with(dc), {}
87
- unless dc.add(sid, session, @default_ttl)
88
- sid = old_sid
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 set_session(env, session_id, new_session, options)
97
- return false unless session_id
82
+ def write_session(_req, sid, session, options)
83
+ return false unless sid
98
84
 
99
- with_block(false) do |dc|
100
- dc.set(session_id, new_session, ttl(options[:expire_after]))
101
- session_id
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 destroy_session(env, session_id, options)
106
- with_block do |dc|
107
- dc.delete(session_id)
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
- def find_session(req, sid)
113
- get_session req.env, sid
98
+ private
99
+
100
+ def memcached_key_from_sid(sid)
101
+ sid.private_id
114
102
  end
115
103
 
116
- def write_session(req, sid, session, options)
117
- set_session req.env, sid, session, options
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 delete_session(req, sid, options)
121
- destroy_session req.env, sid, options
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
- private
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 extract_dalli_options(options)
127
- raise "Rack::Session::Dalli no longer supports the :cache option." if options[:cache]
126
+ def build_data_source(options)
127
+ server_configurations, client_options, pool_options = extract_dalli_options(options)
128
128
 
129
- popts = {}
130
- # Filter out Rack::Session-specific options and apply our defaults
131
- mopts = DEFAULT_DALLI_OPTIONS.merge \
132
- options.reject {|k, _| DEFAULT_OPTIONS.key? k }
133
- mserv = mopts.delete :memcache_server
134
-
135
- if mopts[:pool_size] || mopts[:pool_timeout]
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
- [mserv, mopts, popts]
145
+ [server_configurations, client_options, retrieve_pool_options(options)]
142
146
  end
143
147
 
144
- def generate_sid_with(dc)
145
- while true
146
- sid = generate_sid
147
- break sid unless dc.get(sid)
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 with_block(default=nil, &block)
152
- @pool.with(&block)
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 $!.message =~ /undefined class/
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 $!.inspect
176
+ warn $ERROR_INFO.inspect
158
177
  end
159
- default
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
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-10-27 00:00:00.000000000 Z
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: connection_pool
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: '0'
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.30
161
+ rubygems_version: 3.2.31
89
162
  signing_key:
90
163
  specification_version: 4
91
164
  summary: High performance memcached client for Ruby