@@ -35,6 +35,65 @@ def self.cache_for(l); instance.cache_for l; end
35
35
# Simple memory backed cache. This cache is not thread safe and is intended only
36
36
# for serving as a temporary memory cache for a single thread.
37
37
class LocalStore < Store
38
+ class Entry # :nodoc:
39
+ class << self
40
+ def build ( cache_entry )
41
+ return if cache_entry . nil?
42
+ return cache_entry if cache_entry . compressed?
43
+
44
+ value = cache_entry . value
45
+ if value . is_a? ( String )
46
+ DupableEntry . new ( cache_entry )
47
+ elsif !value || value == true || value . is_a? ( Numeric )
48
+ new ( cache_entry )
49
+ else
50
+ MutableEntry . new ( cache_entry )
51
+ end
52
+ end
53
+ end
54
+
55
+ attr_reader :value , :version , :expires_at
56
+
57
+ def initialize ( cache_entry )
58
+ @value = cache_entry . value
59
+ @expires_at = cache_entry . expires_at
60
+ @version = cache_entry . version
61
+ end
62
+
63
+ def mismatched? ( version )
64
+ @version && version && @version != version
65
+ end
66
+
67
+ def expired?
68
+ expires_at && expires_at <= Time . now . to_f
69
+ end
70
+ end
71
+
72
+ class DupableEntry < Entry # :nodoc:
73
+ def initialize ( _cache_entry )
74
+ super
75
+ unless @value . frozen?
76
+ @value = @value . dup . freeze
77
+ end
78
+ end
79
+
80
+ def value
81
+ @value . dup
82
+ end
83
+ end
84
+
85
+ class MutableEntry < Entry # :nodoc:
86
+ def initialize ( cache_entry )
87
+ @payload = Marshal . dump ( cache_entry . value )
88
+ @expires_at = cache_entry . expires_at
89
+ @version = cache_entry . version
90
+ end
91
+
92
+ def value
93
+ Marshal . load ( @payload )
94
+ end
95
+ end
96
+
38
97
def initialize
39
98
super
40
99
@data = { }
@@ -65,8 +124,7 @@ def read_multi_entries(keys, **options)
65
124
end
66
125
67
126
def write_entry ( key , entry , **options )
68
- entry . dup_value!
69
- @data [ key ] = entry
127
+ @data [ key ] = Entry . build ( entry )
70
128
true
71
129
end
72
130
@@ -75,10 +133,7 @@ def delete_entry(key, **options)
75
133
end
76
134
77
135
def fetch_entry ( key , options = nil ) # :nodoc:
78
- entry = @data . fetch ( key ) { @data [ key ] = yield }
79
- dup_entry = entry . dup
80
- dup_entry &.dup_value!
81
- dup_entry
136
+ @data . fetch ( key ) { @data [ key ] = Entry . build ( yield ) }
82
137
end
83
138
end
84
139
@@ -131,12 +186,12 @@ def decrement(name, amount = 1, **options) # :nodoc:
131
186
def read_entry ( key , **options )
132
187
if cache = local_cache
133
188
hit = true
134
- value = cache . fetch_entry ( key ) do
189
+ entry = cache . fetch_entry ( key ) do
135
190
hit = false
136
191
super
137
192
end
138
193
options [ :event ] [ :store ] = cache . class . name if hit && options [ :event ]
139
- value
194
+ entry
140
195
else
141
196
super
142
197
end
0 commit comments