dalli 3.1.1 → 3.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89dd04ff2b4fd6812f2fae613cc984c7d34029a2637ebf5c11d5398361fa7993
4
- data.tar.gz: caf5ad6315ddb803ba61418d189c99ce7849f1acced49cf6e32e78e5ca35817f
3
+ metadata.gz: '0905b56adf194401de7755ab22ebef6b57f6e673e8332f7cb99b3ef9ed1dde63'
4
+ data.tar.gz: dac2014c748ef0c55fe171af0cec8dec807ae2468f758338c8968135acd47b92
5
5
  SHA512:
6
- metadata.gz: e425b9704308ce7f3737c7e07dcd2699448ba173fd8fa3ac1e9d3d8867890ce1029dd69f98fb4856bab6c8d81685d34be1c41a192039fccb631c2d4b4749b85a
7
- data.tar.gz: 0afdb9aa3fde689a6b84b72aa44aa228e23994f747cce60f8a3471f250a7fa60fdbb3481e4ab4f2665de80be4799b3294f308bb86efa815867e121cd7dc223c9
6
+ metadata.gz: 85d8382dfd13c2353a61c74525e17bd81e000308e8d476851ed25fdb6ef81e9aff4276eb0b1484e30c83001301a3500140cb46a595081e1b21f0801ea32d7e28
7
+ data.tar.gz: 7f0adfc09e31d435bbb3f6cff2f65392a58f81697e7025ca71d9423f9a536d9c984ed7ba0742d0c0f5de0e865a7ebd2dc5548a0406c86d7f1fe0c8135c7af363
data/History.md CHANGED
@@ -4,6 +4,16 @@ Dalli Changelog
4
4
  Unreleased
5
5
  ==========
6
6
 
7
+ 3.1.3
8
+ ==========
9
+
10
+ - Restore falsey behavior on delete/delete_cas for nonexistent key (petergoldstein)
11
+
12
+ 3.1.2
13
+ ==========
14
+
15
+ - Make quiet? / multi? public on Dalli::Protocol::Binary (petergoldstein)
16
+
7
17
  3.1.1
8
18
  ==========
9
19
 
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'socket'
5
+ require 'timeout'
6
+
7
+ module Dalli
8
+ module Protocol
9
+ ##
10
+ # Base class for a single Memcached server, containing logic common to all
11
+ # protocols. Contains logic for managing connection state to the server and value
12
+ # handling.
13
+ ##
14
+ class Base
15
+ extend Forwardable
16
+
17
+ attr_accessor :weight, :options
18
+
19
+ def_delegators :@value_marshaller, :serializer, :compressor, :compression_min_size, :compress_by_default?
20
+ def_delegators :@connection_manager, :name, :sock, :hostname, :port, :close, :connected?, :socket_timeout,
21
+ :socket_type, :up!, :down!, :write, :reconnect_down_server?, :raise_down_error
22
+
23
+ def initialize(attribs, client_options = {})
24
+ hostname, port, socket_type, @weight, user_creds = ServerConfigParser.parse(attribs)
25
+ @options = client_options.merge(user_creds)
26
+ @value_marshaller = ValueMarshaller.new(@options)
27
+ @connection_manager = ConnectionManager.new(hostname, port, socket_type, @options)
28
+ end
29
+
30
+ # Chokepoint method for error handling and ensuring liveness
31
+ def request(opkey, *args)
32
+ verify_state(opkey)
33
+
34
+ begin
35
+ send(opkey, *args)
36
+ rescue Dalli::MarshalError => e
37
+ log_marshal_err(args.first, e)
38
+ raise
39
+ rescue Dalli::DalliError
40
+ raise
41
+ rescue StandardError => e
42
+ log_unexpected_err(e)
43
+ down!
44
+ end
45
+ end
46
+
47
+ ##
48
+ # Boolean method used by clients of this class to determine if this
49
+ # particular memcached instance is available for use.
50
+ def alive?
51
+ ensure_connected!
52
+ rescue Dalli::NetworkError
53
+ # ensure_connected! raises a NetworkError if connection fails. We
54
+ # want to capture that error and convert it to a boolean value here.
55
+ false
56
+ end
57
+
58
+ def lock!; end
59
+
60
+ def unlock!; end
61
+
62
+ # Start reading key/value pairs from this connection. This is usually called
63
+ # after a series of GETKQ commands. A NOOP is sent, and the server begins
64
+ # flushing responses for kv pairs that were found.
65
+ #
66
+ # Returns nothing.
67
+ def pipeline_response_setup
68
+ verify_state(:getkq)
69
+ write_noop
70
+ response_buffer.reset
71
+ @connection_manager.start_request!
72
+ end
73
+
74
+ # Attempt to receive and parse as many key/value pairs as possible
75
+ # from this server. After #pipeline_response_setup, this should be invoked
76
+ # repeatedly whenever this server's socket is readable until
77
+ # #pipeline_complete?.
78
+ #
79
+ # Returns a Hash of kv pairs received.
80
+ def pipeline_next_responses
81
+ reconnect_on_pipeline_complete!
82
+ values = {}
83
+
84
+ response_buffer.read
85
+
86
+ resp_header, key, value = pipeline_response
87
+ # resp_header is not nil only if we have a full response to parse
88
+ # in the buffer
89
+ while resp_header
90
+ # If the status is ok and key is nil, then this is the response
91
+ # to the noop at the end of the pipeline
92
+ finish_pipeline && break if resp_header.ok? && key.nil?
93
+
94
+ # If the status is ok and the key is not nil, then this is a
95
+ # getkq response with a value that we want to set in the response hash
96
+ values[key] = [value, resp_header.cas] unless key.nil?
97
+
98
+ # Get the next response from the buffer
99
+ resp_header, key, value = pipeline_response
100
+ end
101
+
102
+ values
103
+ rescue SystemCallError, Timeout::Error, EOFError => e
104
+ @connection_manager.error_on_request!(e)
105
+ end
106
+
107
+ # Abort current pipelined get. Generally used to signal an external
108
+ # timeout during pipelined get. The underlying socket is
109
+ # disconnected, and the exception is swallowed.
110
+ #
111
+ # Returns nothing.
112
+ def pipeline_abort
113
+ response_buffer.clear
114
+ @connection_manager.abort_request!
115
+ return true unless connected?
116
+
117
+ # Closes the connection, which ensures that our connection
118
+ # is in a clean state for future requests
119
+ @connection_manager.error_on_request!('External timeout')
120
+ rescue NetworkError
121
+ true
122
+ end
123
+
124
+ # Did the last call to #pipeline_response_setup complete successfully?
125
+ def pipeline_complete?
126
+ !response_buffer.in_progress?
127
+ end
128
+
129
+ def username
130
+ @options[:username] || ENV['MEMCACHE_USERNAME']
131
+ end
132
+
133
+ def password
134
+ @options[:password] || ENV['MEMCACHE_PASSWORD']
135
+ end
136
+
137
+ def require_auth?
138
+ !username.nil?
139
+ end
140
+
141
+ def quiet?
142
+ Thread.current[::Dalli::QUIET]
143
+ end
144
+ alias multi? quiet?
145
+
146
+ # NOTE: Additional public methods should be overridden in Dalli::Threadsafe
147
+
148
+ private
149
+
150
+ ##
151
+ # Checks to see if we can execute the specified operation. Checks
152
+ # whether the connection is in use, and whether the command is allowed
153
+ ##
154
+ def verify_state(opkey)
155
+ @connection_manager.confirm_ready!
156
+ verify_allowed_quiet!(opkey) if quiet?
157
+
158
+ # The ensure_connected call has the side effect of connecting the
159
+ # underlying socket if it is not connected, or there's been a disconnect
160
+ # because of timeout or other error. Method raises an error
161
+ # if it can't connect
162
+ raise_down_error unless ensure_connected!
163
+ end
164
+
165
+ # The socket connection to the underlying server is initialized as a side
166
+ # effect of this call. In fact, this is the ONLY place where that
167
+ # socket connection is initialized.
168
+ #
169
+ # Both this method and connect need to be in this class so we can do auth
170
+ # as required
171
+ #
172
+ # Since this is invoked exclusively in verify_state!, we don't need to worry about
173
+ # thread safety. Using it elsewhere may require revisiting that assumption.
174
+ def ensure_connected!
175
+ return true if connected?
176
+ return false unless reconnect_down_server?
177
+
178
+ connect # This call needs to be in this class so we can do auth
179
+ connected?
180
+ end
181
+
182
+ def cache_nils?(opts)
183
+ return false unless opts.is_a?(Hash)
184
+
185
+ opts[:cache_nils] ? true : false
186
+ end
187
+
188
+ def connect
189
+ @connection_manager.establish_connection
190
+ authenticate_connection if require_auth?
191
+ @version = version # Connect socket if not authed
192
+ up!
193
+ rescue Dalli::DalliError
194
+ raise
195
+ end
196
+
197
+ def pipelined_get(keys)
198
+ req = +''
199
+ keys.each do |key|
200
+ req << quiet_get_request(key)
201
+ end
202
+ # Could send noop here instead of in pipeline_response_setup
203
+ write(req)
204
+ end
205
+
206
+ def response_buffer
207
+ @response_buffer ||= ResponseBuffer.new(@connection_manager, response_processor)
208
+ end
209
+
210
+ def pipeline_response
211
+ response_buffer.process_single_getk_response
212
+ end
213
+
214
+ # Called after the noop response is received at the end of a set
215
+ # of pipelined gets
216
+ def finish_pipeline
217
+ response_buffer.clear
218
+ @connection_manager.finish_request!
219
+
220
+ true # to simplify response
221
+ end
222
+
223
+ def reconnect_on_pipeline_complete!
224
+ @connection_manager.reconnect! 'pipelined get has completed' if pipeline_complete?
225
+ end
226
+
227
+ def log_marshal_err(key, err)
228
+ Dalli.logger.error "Marshalling error for key '#{key}': #{err.message}"
229
+ Dalli.logger.error 'You are trying to cache a Ruby object which cannot be serialized to memcached.'
230
+ end
231
+
232
+ def log_unexpected_err(err)
233
+ Dalli.logger.error "Unexpected exception during Dalli request: #{err.class.name}: #{err.message}"
234
+ Dalli.logger.error err.backtrace.join("\n\t")
235
+ end
236
+ end
237
+ end
238
+ end
@@ -89,6 +89,14 @@ module Dalli
89
89
  resp_header.cas
90
90
  end
91
91
 
92
+ def delete_response
93
+ resp_header, = read_response
94
+ return false if resp_header.not_found? || resp_header.not_stored?
95
+
96
+ raise_on_not_ok!(resp_header)
97
+ true
98
+ end
99
+
92
100
  def no_body_response
93
101
  resp_header, = read_response
94
102
  return false if resp_header.not_stored? # Not stored, possible status for append/prepend
@@ -10,7 +10,7 @@ module Dalli
10
10
  def perform_auth_negotiation
11
11
  write(RequestFormatter.standard_request(opkey: :auth_negotiation))
12
12
 
13
- status, content = @response_processor.auth_response
13
+ status, content = response_processor.auth_response
14
14
  return [status, []] if content.nil?
15
15
 
16
16
  # Substitute spaces for the \x00 returned by
@@ -4,11 +4,6 @@ require 'forwardable'
4
4
  require 'socket'
5
5
  require 'timeout'
6
6
 
7
- require_relative 'binary/request_formatter'
8
- require_relative 'binary/response_header'
9
- require_relative 'binary/response_processor'
10
- require_relative 'binary/sasl_authentication'
11
-
12
7
  module Dalli
13
8
  module Protocol
14
9
  ##
@@ -16,170 +11,13 @@ module Dalli
16
11
  # protocol. Contains logic for managing connection state to the server (retries, etc),
17
12
  # formatting requests to the server, and unpacking responses.
18
13
  ##
19
- class Binary
20
- extend Forwardable
21
-
22
- attr_accessor :weight, :options
23
-
24
- def_delegators :@value_marshaller, :serializer, :compressor, :compression_min_size, :compress_by_default?
25
- def_delegators :@connection_manager, :name, :sock, :hostname, :port, :close, :connected?, :socket_timeout,
26
- :socket_type, :up!, :down!, :write, :reconnect_down_server?, :raise_down_error
27
-
28
- def initialize(attribs, client_options = {})
29
- hostname, port, socket_type, @weight, user_creds = ServerConfigParser.parse(attribs)
30
- @options = client_options.merge(user_creds)
31
- @value_marshaller = ValueMarshaller.new(@options)
32
- @connection_manager = ConnectionManager.new(hostname, port, socket_type, @options)
33
- @response_processor = ResponseProcessor.new(@connection_manager, @value_marshaller)
34
- end
35
-
36
- # Chokepoint method for error handling and ensuring liveness
37
- def request(opkey, *args)
38
- verify_state(opkey)
39
-
40
- begin
41
- send(opkey, *args)
42
- rescue Dalli::MarshalError => e
43
- log_marshal_err(args.first, e)
44
- raise
45
- rescue Dalli::DalliError
46
- raise
47
- rescue StandardError => e
48
- log_unexpected_err(e)
49
- down!
50
- end
51
- end
52
-
53
- ##
54
- # Boolean method used by clients of this class to determine if this
55
- # particular memcached instance is available for use.
56
- def alive?
57
- ensure_connected!
58
- rescue Dalli::NetworkError
59
- # ensure_connected! raises a NetworkError if connection fails. We
60
- # want to capture that error and convert it to a boolean value here.
61
- false
62
- end
63
-
64
- def lock!; end
65
-
66
- def unlock!; end
67
-
68
- # Start reading key/value pairs from this connection. This is usually called
69
- # after a series of GETKQ commands. A NOOP is sent, and the server begins
70
- # flushing responses for kv pairs that were found.
71
- #
72
- # Returns nothing.
73
- def pipeline_response_setup
74
- verify_state(:getkq)
75
- write_noop
76
- response_buffer.reset
77
- @connection_manager.start_request!
78
- end
79
-
80
- # Attempt to receive and parse as many key/value pairs as possible
81
- # from this server. After #pipeline_response_setup, this should be invoked
82
- # repeatedly whenever this server's socket is readable until
83
- # #pipeline_complete?.
84
- #
85
- # Returns a Hash of kv pairs received.
86
- def pipeline_next_responses
87
- reconnect_on_pipeline_complete!
88
- values = {}
89
-
90
- response_buffer.read
91
-
92
- resp_header, key, value = pipeline_response
93
- # resp_header is not nil only if we have a full response to parse
94
- # in the buffer
95
- while resp_header
96
- # If the status is ok and key is nil, then this is the response
97
- # to the noop at the end of the pipeline
98
- finish_pipeline && break if resp_header.ok? && key.nil?
99
-
100
- # If the status is ok and the key is not nil, then this is a
101
- # getkq response with a value that we want to set in the response hash
102
- values[key] = [value, resp_header.cas] unless key.nil?
103
-
104
- # Get the next response from the buffer
105
- resp_header, key, value = pipeline_response
106
- end
107
-
108
- values
109
- rescue SystemCallError, Timeout::Error, EOFError => e
110
- @connection_manager.error_on_request!(e)
111
- end
112
-
113
- # Abort current pipelined get. Generally used to signal an external
114
- # timeout during pipelined get. The underlying socket is
115
- # disconnected, and the exception is swallowed.
116
- #
117
- # Returns nothing.
118
- def pipeline_abort
119
- response_buffer.clear
120
- @connection_manager.abort_request!
121
- return true unless connected?
122
-
123
- # Closes the connection, which ensures that our connection
124
- # is in a clean state for future requests
125
- @connection_manager.error_on_request!('External timeout')
126
- rescue NetworkError
127
- true
128
- end
129
-
130
- # Did the last call to #pipeline_response_setup complete successfully?
131
- def pipeline_complete?
132
- !response_buffer.in_progress?
133
- end
134
-
135
- def username
136
- @options[:username] || ENV['MEMCACHE_USERNAME']
137
- end
138
-
139
- def password
140
- @options[:password] || ENV['MEMCACHE_PASSWORD']
141
- end
142
-
143
- def require_auth?
144
- !username.nil?
14
+ class Binary < Base
15
+ def response_processor
16
+ @response_processor ||= ResponseProcessor.new(@connection_manager, @value_marshaller)
145
17
  end
146
18
 
147
- # NOTE: Additional public methods should be overridden in Dalli::Threadsafe
148
-
149
19
  private
150
20
 
151
- ##
152
- # Checks to see if we can execute the specified operation. Checks
153
- # whether the connection is in use, and whether the command is allowed
154
- ##
155
- def verify_state(opkey)
156
- @connection_manager.confirm_ready!
157
- verify_allowed_quiet!(opkey) if quiet?
158
-
159
- # The ensure_connected call has the side effect of connecting the
160
- # underlying socket if it is not connected, or there's been a disconnect
161
- # because of timeout or other error. Method raises an error
162
- # if it can't connect
163
- raise_down_error unless ensure_connected!
164
- end
165
-
166
- # The socket connection to the underlying server is initialized as a side
167
- # effect of this call. In fact, this is the ONLY place where that
168
- # socket connection is initialized.
169
- #
170
- # Both this method and connect need to be in this class so we can do auth
171
- # as required
172
- #
173
- # Since this is invoked exclusively in verify_state!, we don't need to worry about
174
- # thread safety. Using it elsewhere may require revisiting that assumption.
175
- def ensure_connected!
176
- return true if connected?
177
- return false unless reconnect_down_server?
178
-
179
- connect # This call needs to be in this class so we can do auth
180
- connected?
181
- end
182
-
183
21
  ALLOWED_QUIET_OPS = %i[add replace set delete incr decr append prepend flush noop].freeze
184
22
  def verify_allowed_quiet!(opkey)
185
23
  return if ALLOWED_QUIET_OPS.include?(opkey)
@@ -187,34 +25,28 @@ module Dalli
187
25
  raise Dalli::NotPermittedMultiOpError, "The operation #{opkey} is not allowed in a quiet block."
188
26
  end
189
27
 
190
- def quiet?
191
- Thread.current[::Dalli::QUIET]
192
- end
193
-
194
- def cache_nils?(opts)
195
- return false unless opts.is_a?(Hash)
196
-
197
- opts[:cache_nils] ? true : false
198
- end
199
-
200
28
  # Retrieval Commands
201
29
  def get(key, options = nil)
202
30
  req = RequestFormatter.standard_request(opkey: :get, key: key)
203
31
  write(req)
204
- @response_processor.generic_response(unpack: true, cache_nils: cache_nils?(options))
32
+ response_processor.generic_response(unpack: true, cache_nils: cache_nils?(options))
33
+ end
34
+
35
+ def quiet_get_request(key)
36
+ RequestFormatter.standard_request(opkey: :getkq, key: key)
205
37
  end
206
38
 
207
39
  def gat(key, ttl, options = nil)
208
40
  ttl = TtlSanitizer.sanitize(ttl)
209
41
  req = RequestFormatter.standard_request(opkey: :gat, key: key, ttl: ttl)
210
42
  write(req)
211
- @response_processor.generic_response(unpack: true, cache_nils: cache_nils?(options))
43
+ response_processor.generic_response(unpack: true, cache_nils: cache_nils?(options))
212
44
  end
213
45
 
214
46
  def touch(key, ttl)
215
47
  ttl = TtlSanitizer.sanitize(ttl)
216
48
  write(RequestFormatter.standard_request(opkey: :touch, key: key, ttl: ttl))
217
- @response_processor.generic_response
49
+ response_processor.generic_response
218
50
  end
219
51
 
220
52
  # TODO: This is confusing, as there's a cas command in memcached
@@ -222,7 +54,7 @@ module Dalli
222
54
  def cas(key)
223
55
  req = RequestFormatter.standard_request(opkey: :get, key: key)
224
56
  write(req)
225
- @response_processor.data_cas_response
57
+ response_processor.data_cas_response
226
58
  end
227
59
 
228
60
  # Storage Commands
@@ -250,7 +82,7 @@ module Dalli
250
82
  value: value, bitflags: bitflags,
251
83
  ttl: ttl, cas: cas)
252
84
  write(req)
253
- @response_processor.storage_response unless quiet?
85
+ response_processor.storage_response unless quiet?
254
86
  end
255
87
  # rubocop:enable Metrics/ParameterLists
256
88
 
@@ -266,7 +98,7 @@ module Dalli
266
98
 
267
99
  def write_append_prepend(opkey, key, value)
268
100
  write(RequestFormatter.standard_request(opkey: opkey, key: key, value: value))
269
- @response_processor.no_body_response unless quiet?
101
+ response_processor.no_body_response unless quiet?
270
102
  end
271
103
 
272
104
  # Delete Commands
@@ -274,7 +106,7 @@ module Dalli
274
106
  opkey = quiet? ? :deleteq : :delete
275
107
  req = RequestFormatter.standard_request(opkey: opkey, key: key, cas: cas)
276
108
  write(req)
277
- @response_processor.no_body_response unless quiet?
109
+ response_processor.delete_response unless quiet?
278
110
  end
279
111
 
280
112
  # Arithmetic Commands
@@ -300,37 +132,37 @@ module Dalli
300
132
  initial ||= 0
301
133
  write(RequestFormatter.decr_incr_request(opkey: opkey, key: key,
302
134
  count: count, initial: initial, expiry: expiry))
303
- @response_processor.decr_incr_response unless quiet?
135
+ response_processor.decr_incr_response unless quiet?
304
136
  end
305
137
 
306
138
  # Other Commands
307
139
  def flush(ttl = 0)
308
140
  opkey = quiet? ? :flushq : :flush
309
141
  write(RequestFormatter.standard_request(opkey: opkey, ttl: ttl))
310
- @response_processor.no_body_response unless quiet?
142
+ response_processor.no_body_response unless quiet?
311
143
  end
312
144
 
313
145
  # Noop is a keepalive operation but also used to demarcate the end of a set of pipelined commands.
314
146
  # We need to read all the responses at once.
315
147
  def noop
316
148
  write_noop
317
- @response_processor.multi_with_keys_response
149
+ response_processor.multi_with_keys_response
318
150
  end
319
151
 
320
152
  def stats(info = '')
321
153
  req = RequestFormatter.standard_request(opkey: :stat, key: info)
322
154
  write(req)
323
- @response_processor.multi_with_keys_response
155
+ response_processor.multi_with_keys_response
324
156
  end
325
157
 
326
158
  def reset_stats
327
159
  write(RequestFormatter.standard_request(opkey: :stat, key: 'reset'))
328
- @response_processor.generic_response
160
+ response_processor.generic_response
329
161
  end
330
162
 
331
163
  def version
332
164
  write(RequestFormatter.standard_request(opkey: :version))
333
- @response_processor.generic_response
165
+ response_processor.generic_response
334
166
  end
335
167
 
336
168
  def write_noop
@@ -338,55 +170,10 @@ module Dalli
338
170
  write(req)
339
171
  end
340
172
 
341
- def connect
342
- @connection_manager.establish_connection
343
- authenticate_connection if require_auth?
344
- @version = version # Connect socket if not authed
345
- up!
346
- rescue Dalli::DalliError
347
- raise
348
- end
349
-
350
- def pipelined_get(keys)
351
- req = +''
352
- keys.each do |key|
353
- req << RequestFormatter.standard_request(opkey: :getkq, key: key)
354
- end
355
- # Could send noop here instead of in pipeline_response_setup
356
- write(req)
357
- end
358
-
359
- def response_buffer
360
- @response_buffer ||= ResponseBuffer.new(@connection_manager, @response_processor)
361
- end
362
-
363
- def pipeline_response
364
- response_buffer.process_single_getk_response
365
- end
366
-
367
- # Called after the noop response is received at the end of a set
368
- # of pipelined gets
369
- def finish_pipeline
370
- response_buffer.clear
371
- @connection_manager.finish_request!
372
-
373
- true # to simplify response
374
- end
375
-
376
- def reconnect_on_pipeline_complete!
377
- @connection_manager.reconnect! 'pipelined get has completed' if pipeline_complete?
378
- end
379
-
380
- def log_marshal_err(key, err)
381
- Dalli.logger.error "Marshalling error for key '#{key}': #{err.message}"
382
- Dalli.logger.error 'You are trying to cache a Ruby object which cannot be serialized to memcached.'
383
- end
384
-
385
- def log_unexpected_err(err)
386
- Dalli.logger.error "Unexpected exception during Dalli request: #{err.class.name}: #{err.message}"
387
- Dalli.logger.error err.backtrace.join("\n\t")
388
- end
389
-
173
+ require_relative 'binary/request_formatter'
174
+ require_relative 'binary/response_header'
175
+ require_relative 'binary/response_processor'
176
+ require_relative 'binary/sasl_authentication'
390
177
  include SaslAuthentication
391
178
  end
392
179
  end
data/lib/dalli/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dalli
4
- VERSION = '3.1.1'
4
+ VERSION = '3.1.3'
5
5
 
6
6
  MIN_SUPPORTED_MEMCACHED_VERSION = '1.4'
7
7
  end
data/lib/dalli.rb CHANGED
@@ -62,6 +62,7 @@ require_relative 'dalli/key_manager'
62
62
  require_relative 'dalli/pipelined_getter'
63
63
  require_relative 'dalli/ring'
64
64
  require_relative 'dalli/protocol'
65
+ require_relative 'dalli/protocol/base'
65
66
  require_relative 'dalli/protocol/binary'
66
67
  require_relative 'dalli/protocol/connection_manager'
67
68
  require_relative 'dalli/protocol/response_buffer'
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.1.1
4
+ version: 3.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter M. Goldstein
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-12-10 00:00:00.000000000 Z
12
+ date: 2021-12-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: connection_pool
@@ -121,6 +121,7 @@ files:
121
121
  - lib/dalli/options.rb
122
122
  - lib/dalli/pipelined_getter.rb
123
123
  - lib/dalli/protocol.rb
124
+ - lib/dalli/protocol/base.rb
124
125
  - lib/dalli/protocol/binary.rb
125
126
  - lib/dalli/protocol/binary/request_formatter.rb
126
127
  - lib/dalli/protocol/binary/response_header.rb
@@ -159,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
160
  - !ruby/object:Gem::Version
160
161
  version: '0'
161
162
  requirements: []
162
- rubygems_version: 3.2.33
163
+ rubygems_version: 3.2.31
163
164
  signing_key:
164
165
  specification_version: 4
165
166
  summary: High performance memcached client for Ruby