@@ -13,58 +13,23 @@ module Cache
1313 class MemcachedStore < Store
1414 ESCAPE_KEY_CHARS = /[\x00 -\x20 %\x7F -\xFF ]/n
1515
16- class Codec
17- # use dalli compatible flags
18- SERIALIZED_FLAG = 0x1
19- COMPRESSED_FLAG = 0x2
20-
21- # Older versions of this gem would use 0 for the flags whether or not
22- # the value was marshal dumped. By setting this flag, we can tell if
23- # it were set with an older version for backwards compatible decoding.
24- RAW_FLAG = 0x10
25-
26- def initialize ( serializer : Marshal , compressor : nil )
27- @serializer = serializer
28- @compressor = compressor
29- end
16+ attr_accessor :swallow_exceptions
3017
31- def encode ( _key , value , flags )
32- unless value . is_a? ( String )
33- flags |= SERIALIZED_FLAG
34- value = @serializer . dump ( value )
35- end
36- if @compressor
37- flags |= COMPRESSED_FLAG
38- value = @compressor . compress ( value )
39- end
40- flags |= RAW_FLAG if flags == 0
18+ module RawCodec
19+ def self . encode ( _key , value , flags )
4120 [ value , flags ]
4221 end
4322
44- def decode ( _key , value , flags )
45- if ( flags & COMPRESSED_FLAG ) != 0
46- value = @compressor . decompress ( value )
47- end
48-
49- if ( flags & SERIALIZED_FLAG ) != 0
50- @serializer . load ( value )
51- elsif flags == 0 # legacy cache value
52- @serializer . load ( value ) rescue value
53- else
54- value
55- end
23+ def self . decode ( _key , value , _flags )
24+ value
5625 end
5726 end
5827
59- attr_accessor :read_only , :swallow_exceptions
60-
6128 prepend ( Strategy ::LocalCache )
6229
6330 def initialize ( *addresses , **options )
6431 addresses = addresses . flatten
65- options [ :codec ] ||= Codec . new
66- @swallow_exceptions = true
67- @swallow_exceptions = options . delete ( :swallow_exceptions ) if options . key? ( :swallow_exceptions )
32+ options [ :codec ] ||= RawCodec
6833
6934 super ( options )
7035
@@ -81,7 +46,6 @@ def initialize(*addresses, **options)
8146 end
8247
8348 def append ( name , value , options = nil )
84- return true if read_only
8549 options = merged_options ( options )
8650 normalized_key = normalize_key ( name , options )
8751
@@ -93,16 +57,6 @@ def append(name, value, options = nil)
9357 end
9458 end
9559
96- def write ( *)
97- return true if read_only
98- super
99- end
100-
101- def delete ( *)
102- return true if read_only
103- super
104- end
105-
10660 def read_multi ( *names )
10761 options = names . extract_options!
10862 return { } if names . empty?
@@ -115,7 +69,7 @@ def read_multi(*names)
11569 instrument ( :read_multi , names , options ) do
11670 if raw_values = @connection . get ( keys_to_names . keys )
11771 raw_values . each do |key , value |
118- entry = deserialize_entry ( value )
72+ entry = deserialize_entry ( value , ** options )
11973 values [ keys_to_names [ key ] ] = entry . value unless entry . expired?
12074 end
12175 end
@@ -133,8 +87,7 @@ def cas(name, options = nil)
13387 @connection . cas ( key , expiration ( options ) ) do |raw_value |
13488 entry = deserialize_entry ( raw_value )
13589 value = yield entry . value
136- break true if read_only
137- serialize_entry ( Entry . new ( value , **options ) , options )
90+ serialize_entry ( Entry . new ( value , **options ) , **options )
13891 end
13992 end
14093 true
@@ -159,10 +112,8 @@ def cas_multi(*names, **options)
159112
160113 values = yield values
161114
162- break true if read_only
163-
164115 serialized_values = values . map do |name , value |
165- [ normalize_key ( name , options ) , serialize_entry ( Entry . new ( value , **options ) , options ) ]
116+ [ normalize_key ( name , options ) , serialize_entry ( Entry . new ( value , **options ) , ** options ) ]
166117 end
167118
168119 Hash [ serialized_values ]
@@ -212,55 +163,63 @@ def reset #:nodoc:
212163 end
213164 end
214165
215- protected
166+ private
167+
168+ def read_entry ( key , **options ) # :nodoc:
169+ deserialize_entry ( read_serialized_entry ( key , **options ) , **options )
170+ end
216171
217- def read_entry ( key , _options ) # :nodoc:
172+ def read_serialized_entry ( key , ** )
218173 handle_exceptions ( return_value_on_error : nil ) do
219- deserialize_entry ( @connection . get ( key ) )
174+ @connection . get ( key )
220175 end
221176 end
222177
223- def write_entry ( key , entry , options ) # :nodoc:
224- return true if read_only
178+ def write_entry ( key , entry , **options ) # :nodoc:
179+ write_serialized_entry ( key , serialize_entry ( entry , **options ) , **options )
180+ end
181+
182+ def write_serialized_entry ( key , value , **options )
225183 method = options && options [ :unless_exist ] ? :add : :set
226184 expires_in = expiration ( options )
227- value = serialize_entry ( entry , options )
228185 handle_exceptions ( return_value_on_error : false ) do
229186 @connection . send ( method , key , value , expires_in )
230187 true
231188 end
232189 end
233190
234191 def delete_entry ( key , _options ) # :nodoc:
235- return true if read_only
236192 handle_exceptions ( return_value_on_error : false , on_miss : true ) do
237193 @connection . delete ( key )
238194 true
239195 end
240196 end
241197
242- private
243-
244198 def normalize_key ( key , options )
245199 key = super . dup
246200 key = key . force_encoding ( Encoding ::ASCII_8BIT )
247201 key = key . gsub ( ESCAPE_KEY_CHARS ) { |match | "%#{ match . getbyte ( 0 ) . to_s ( 16 ) . upcase } " }
248- # When we remove support to Rails 5.1 we can change the code to use ActiveSupport::Digest
249202 key = "#{ key [ 0 , 213 ] } :md5:#{ ::Digest ::MD5 . hexdigest ( key ) } " if key . size > 250
250203 key
251204 end
252205
253- def deserialize_entry ( value )
254- unless value . nil?
255- value . is_a? ( Entry ) ? value : Entry . new ( value , compress : false )
206+ def deserialize_entry ( payload , raw : false , **)
207+ if !payload . nil? && raw
208+ if payload . is_a? ( Entry )
209+ payload
210+ else
211+ Entry . new ( payload , compress : false )
212+ end
213+ else
214+ super ( payload )
256215 end
257216 end
258217
259- def serialize_entry ( entry , options )
260- if options [ : raw]
218+ def serialize_entry ( entry , raw : false , ** )
219+ if raw
261220 entry . value . to_s
262221 else
263- entry
222+ super ( entry )
264223 end
265224 end
266225
@@ -276,19 +235,16 @@ def handle_exceptions(return_value_on_error:, on_miss: return_value_on_error, mi
276235 yield
277236 rescue Memcached ::NotFound , Memcached ::ConnectionDataExists , *miss_exceptions
278237 on_miss
238+ rescue Memcached ::NotStored
239+ return_value_on_error
279240 rescue Memcached ::Error => e
280241 log_warning ( e )
281- raise unless @swallow_exceptions
282242 return_value_on_error
283243 end
284244
285245 def log_warning ( err )
286- return unless logger
287- return if err . is_a? ( Memcached ::NotStored ) && @swallow_exceptions
288-
289- logger . warn (
290- "[MEMCACHED_ERROR] swallowed=#{ @swallow_exceptions } " \
291- " exception_class=#{ err . class } exception_message=#{ err . message } "
246+ logger &.warn (
247+ "[MEMCACHED_ERROR] exception_class=#{ err . class } exception_message=#{ err . message } "
292248 )
293249 end
294250
0 commit comments