redis-memo 0.0.0.beta.4 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/redis_memo/memoizable/dependency.rb +18 -17
- data/lib/redis_memo/memoize_method.rb +77 -3
- data/lib/redis_memo/memoize_query/cached_select.rb +2 -12
- data/lib/redis_memo/memoize_query/invalidation.rb +133 -78
- data/lib/redis_memo/options.rb +0 -1
- data/lib/redis_memo/redis.rb +2 -1
- data/lib/redis_memo/testing.rb +55 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 976988ff54686693396ffb07c47b9e4326646837b3be53264891c886f03771c6
|
4
|
+
data.tar.gz: 9e4a3d4dca78cb9389af8e1728addb3aa8d04493365bcfda2ea236e20c657971
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 118d801be413e14616becfb3a9c4e4715a1e7b7cb6722ac48bd8b1c63e6b1c8f565c8a148909b4bd7b4b538f89d1d79145ad137403139eb7158cad61c9d7a847
|
7
|
+
data.tar.gz: 52bdf762fc8bf22a6b65fc158512e001dd12490904db9766cd9f3ff1aee74e61f23f218bfa46cdf57fdb67f9f0d2508649fedc2379d6224d0d34416ffbafb902
|
@@ -26,14 +26,18 @@ class RedisMemo::Memoizable::Dependency
|
|
26
26
|
instance_exec(&memo.depends_on)
|
27
27
|
end
|
28
28
|
when ActiveRecord::Relation
|
29
|
-
extracted =
|
29
|
+
extracted = self.class.extract_from_relation(dependency)
|
30
30
|
nodes.merge!(extracted.nodes)
|
31
|
-
when
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
].each do |memo|
|
31
|
+
when RedisMemo::MemoizeQuery::CachedSelect::BindParams
|
32
|
+
# A private API
|
33
|
+
dependency.params.each do |model, attrs_set|
|
34
|
+
memo = model.redis_memo_class_memoizable
|
36
35
|
nodes[memo.cache_key] = memo
|
36
|
+
|
37
|
+
attrs_set.each do |attrs|
|
38
|
+
memo = RedisMemo::MemoizeQuery.create_memo(model, **attrs)
|
39
|
+
nodes[memo.cache_key] = memo
|
40
|
+
end
|
37
41
|
end
|
38
42
|
else
|
39
43
|
raise(
|
@@ -43,24 +47,21 @@ class RedisMemo::Memoizable::Dependency
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
|
-
|
50
|
+
private
|
51
|
+
|
52
|
+
def self.extract_from_relation(relation)
|
47
53
|
# Extract the dependent memos of an Arel without calling exec_query to actually execute the query
|
48
54
|
RedisMemo::MemoizeQuery::CachedSelect.with_new_query_context do
|
49
55
|
connection = ActiveRecord::Base.connection
|
50
56
|
query, binds, _ = connection.send(:to_sql_and_binds, relation.arel)
|
51
57
|
RedisMemo::MemoizeQuery::CachedSelect.current_query = relation.arel
|
52
58
|
is_query_cached = RedisMemo::MemoizeQuery::CachedSelect.extract_bind_params(query)
|
53
|
-
raise(
|
54
|
-
RedisMemo::WithoutMemoization,
|
55
|
-
"Arel query is not cached using RedisMemo."
|
56
|
-
) unless is_query_cached
|
57
|
-
extracted_dependency = connection.dependency_of(:exec_query, query, nil, binds)
|
58
|
-
end
|
59
|
-
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
unless is_query_cached
|
61
|
+
raise RedisMemo::WithoutMemoization, 'Arel query is not cached using RedisMemo'
|
62
|
+
end
|
63
|
+
|
64
|
+
connection.dependency_of(:exec_query, query, nil, binds)
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
@@ -81,14 +81,88 @@ module RedisMemo::MemoizeMethod
|
|
81
81
|
|
82
82
|
def self.get_or_extract_dependencies(ref, *method_args, &depends_on)
|
83
83
|
if RedisMemo::Cache.local_dependency_cache
|
84
|
-
RedisMemo::Cache.local_dependency_cache[ref] ||= {}
|
85
|
-
RedisMemo::Cache.local_dependency_cache[ref][depends_on] ||= {}
|
86
|
-
|
84
|
+
RedisMemo::Cache.local_dependency_cache[ref.class] ||= {}
|
85
|
+
RedisMemo::Cache.local_dependency_cache[ref.class][depends_on] ||= {}
|
86
|
+
named_args = exclude_anonymous_args(depends_on, ref, method_args)
|
87
|
+
RedisMemo::Cache.local_dependency_cache[ref.class][depends_on][named_args] ||= extract_dependencies(ref, *method_args, &depends_on)
|
87
88
|
else
|
88
89
|
extract_dependencies(ref, *method_args, &depends_on)
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
93
|
+
# We only look at named method parameters in the dependency block in order to define its dependent
|
94
|
+
# memos and ignore anonymous parameters, following the convention that nil or :_ is an anonymous parameter.
|
95
|
+
# Example:
|
96
|
+
# ```
|
97
|
+
# def method(param1, param2)
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# memoize_method :method do |_, _, param2|`
|
101
|
+
# depends_on RedisMemo::Memoizable.new(param2: param2)
|
102
|
+
# end
|
103
|
+
# ```
|
104
|
+
# `exclude_anonymous_args(depends_on, ref, [1, 2])` returns [2]
|
105
|
+
def self.exclude_anonymous_args(depends_on, ref, args)
|
106
|
+
return [] if depends_on.parameters.empty? or args.empty?
|
107
|
+
|
108
|
+
positional_args = []
|
109
|
+
kwargs = {}
|
110
|
+
depends_on_args = [ref] + args
|
111
|
+
options = depends_on_args.extract_options!
|
112
|
+
|
113
|
+
# Keep track of the splat start index, and the number of positional args before and after the splat,
|
114
|
+
# so we can map which args belong to positional args and which args belong to the splat.
|
115
|
+
named_splat = false
|
116
|
+
splat_index = nil
|
117
|
+
num_positional_args_after_splat = 0
|
118
|
+
num_positional_args_before_splat = 0
|
119
|
+
|
120
|
+
depends_on.parameters.each_with_index do |param, i|
|
121
|
+
# Defined by https://github.com/ruby/ruby/blob/22b8ddfd1049c3fd1e368684c4fd03bceb041b3a/proc.c#L3048-L3059
|
122
|
+
case param.first
|
123
|
+
when :opt, :req
|
124
|
+
if splat_index
|
125
|
+
num_positional_args_after_splat += 1
|
126
|
+
else
|
127
|
+
num_positional_args_before_splat += 1
|
128
|
+
end
|
129
|
+
when :rest
|
130
|
+
named_splat = is_named?(param)
|
131
|
+
splat_index = i
|
132
|
+
when :key, :keyreq
|
133
|
+
kwargs[param.last] = options[param.last] if is_named?(param)
|
134
|
+
when :keyrest
|
135
|
+
kwargs.merge!(options) if is_named?(param)
|
136
|
+
else
|
137
|
+
raise(RedisMemo::ArgumentError, "#{param.first} argument isn't supported in the dependency block")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Determine the named positional and splat arguments after we know the # of pos. arguments before and after splat
|
142
|
+
after_splat_index = depends_on_args.size - num_positional_args_after_splat
|
143
|
+
depends_on_args.each_with_index do |arg, i|
|
144
|
+
# if the index is within the splat
|
145
|
+
if i >= num_positional_args_before_splat && i < after_splat_index
|
146
|
+
positional_args << arg if named_splat
|
147
|
+
else
|
148
|
+
j = i < num_positional_args_before_splat ? i : i - (after_splat_index - splat_index) - 1
|
149
|
+
positional_args << arg if is_named?(depends_on.parameters[j])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
if !kwargs.empty?
|
154
|
+
positional_args + [kwargs]
|
155
|
+
elsif named_splat && !options.empty?
|
156
|
+
positional_args + [options]
|
157
|
+
else
|
158
|
+
positional_args
|
159
|
+
end
|
160
|
+
end
|
161
|
+
private
|
162
|
+
def self.is_named?(param)
|
163
|
+
param.size == 2 && param.last != :_
|
164
|
+
end
|
165
|
+
|
92
166
|
def self.method_cache_keys(future_contexts)
|
93
167
|
memos = Array.new(future_contexts.size)
|
94
168
|
future_contexts.each_with_index do |(_, _, dependent_memos), i|
|
@@ -111,15 +111,8 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
111
111
|
sql.gsub(/(\$\d+)/, '?') # $1 -> ?
|
112
112
|
.gsub(/((, *)*\?)+/, '?') # (?, ?, ? ...) -> (?)
|
113
113
|
end,
|
114
|
-
) do |_, sql,
|
115
|
-
RedisMemo::MemoizeQuery::CachedSelect
|
116
|
-
.current_query_bind_params
|
117
|
-
.params
|
118
|
-
.each do |model, attrs_set|
|
119
|
-
attrs_set.each do |attrs|
|
120
|
-
depends_on model, **attrs
|
121
|
-
end
|
122
|
-
end
|
114
|
+
) do |_, sql, _, binds, **|
|
115
|
+
depends_on RedisMemo::MemoizeQuery::CachedSelect.current_query_bind_params
|
123
116
|
|
124
117
|
depends_on RedisMemo::Memoizable.new(
|
125
118
|
__redis_memo_memoize_query_memoize_query_sql__: sql,
|
@@ -274,9 +267,6 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
274
267
|
|
275
268
|
bind_params
|
276
269
|
when Arel::Nodes::SelectStatement
|
277
|
-
# No OREDER BY
|
278
|
-
return unless node.orders.empty?
|
279
|
-
|
280
270
|
node.cores.each do |core|
|
281
271
|
# We don't support JOINs
|
282
272
|
return unless core.source.right.empty?
|
@@ -36,10 +36,8 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
36
36
|
decrement_counter
|
37
37
|
delete_all delete_by
|
38
38
|
increment_counter
|
39
|
-
insert insert! insert_all insert_all!
|
40
39
|
touch_all
|
41
40
|
update_column update_columns update_all update_counters
|
42
|
-
upsert upsert_all
|
43
41
|
).each do |method_name|
|
44
42
|
# Example: Model.update_all
|
45
43
|
rewrite_default_method(
|
@@ -58,6 +56,24 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
58
56
|
)
|
59
57
|
end
|
60
58
|
|
59
|
+
%i(
|
60
|
+
insert insert! insert_all insert_all!
|
61
|
+
).each do |method_name|
|
62
|
+
rewrite_insert_method(
|
63
|
+
model_class,
|
64
|
+
method_name,
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
%i(
|
69
|
+
upsert upsert_all
|
70
|
+
).each do |method_name|
|
71
|
+
rewrite_upsert_method(
|
72
|
+
model_class,
|
73
|
+
method_name,
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
61
77
|
%i(
|
62
78
|
import import!
|
63
79
|
).each do |method_name|
|
@@ -70,6 +86,36 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
70
86
|
model_class.class_variable_set(var_name, true)
|
71
87
|
end
|
72
88
|
|
89
|
+
def self.invalidate_new_records(model_class, &blk)
|
90
|
+
current_id = model_class.maximum(model_class.primary_key)
|
91
|
+
result = blk.call
|
92
|
+
records = select_by_new_ids(model_class, current_id)
|
93
|
+
RedisMemo::MemoizeQuery.invalidate(*records) unless records.empty?
|
94
|
+
result
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.invalidate_records_by_conflict_target(model_class, records:, conflict_target: nil, &blk)
|
98
|
+
if conflict_target.nil?
|
99
|
+
# When the conflict_target is not set, we are basically inserting new
|
100
|
+
# records since duplicate rows are simply skipped
|
101
|
+
return invalidate_new_records(model_class, &blk)
|
102
|
+
end
|
103
|
+
|
104
|
+
relation = build_relation_by_conflict_target(model_class, records, conflict_target)
|
105
|
+
# Invalidate records before updating
|
106
|
+
records = select_by_conflict_target_relation(model_class, relation)
|
107
|
+
RedisMemo::MemoizeQuery.invalidate(*records) unless records.empty?
|
108
|
+
|
109
|
+
# Perform updating
|
110
|
+
result = blk.call
|
111
|
+
|
112
|
+
# Invalidate records after updating
|
113
|
+
records = select_by_conflict_target_relation(model_class, relation)
|
114
|
+
RedisMemo::MemoizeQuery.invalidate(*records) unless records.empty?
|
115
|
+
|
116
|
+
result
|
117
|
+
end
|
118
|
+
|
73
119
|
private
|
74
120
|
|
75
121
|
#
|
@@ -95,12 +141,48 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
95
141
|
end
|
96
142
|
end
|
97
143
|
|
98
|
-
def self.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
144
|
+
def self.rewrite_insert_method(model_class, method_name)
|
145
|
+
return unless model_class.respond_to?(method_name)
|
146
|
+
|
147
|
+
model_class.singleton_class.class_eval do
|
148
|
+
alias_method :"#{method_name}_without_redis_memo_invalidation", method_name
|
149
|
+
|
150
|
+
define_method method_name do |*args, &blk|
|
151
|
+
RedisMemo::MemoizeQuery::Invalidation.invalidate_new_records(model_class) do
|
152
|
+
send(:"#{method_name}_without_redis_memo_invalidation", *args, &blk)
|
153
|
+
end
|
154
|
+
end
|
103
155
|
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.rewrite_upsert_method(model_class, method_name)
|
159
|
+
return unless model_class.respond_to?(method_name)
|
160
|
+
|
161
|
+
model_class.singleton_class.class_eval do
|
162
|
+
alias_method :"#{method_name}_without_redis_memo_invalidation", method_name
|
163
|
+
|
164
|
+
define_method method_name do |attributes, unique_by: nil, **kwargs, &blk|
|
165
|
+
RedisMemo::MemoizeQuery::Invalidation.invalidate_records_by_conflict_target(
|
166
|
+
model_class,
|
167
|
+
records: nil, # not used
|
168
|
+
# upsert does not support on_duplicate_key_update yet at activerecord
|
169
|
+
# HEAD (6.1.3)
|
170
|
+
conflict_target: nil,
|
171
|
+
) do
|
172
|
+
send(
|
173
|
+
:"#{method_name}_without_redis_memo_invalidation",
|
174
|
+
attributes,
|
175
|
+
unique_by: unique_by,
|
176
|
+
**kwargs,
|
177
|
+
&blk
|
178
|
+
)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.rewrite_import_method(model_class, method_name)
|
185
|
+
return unless model_class.respond_to?(method_name)
|
104
186
|
|
105
187
|
model_class.singleton_class.class_eval do
|
106
188
|
alias_method :"#{method_name}_without_redis_memo_invalidation", method_name
|
@@ -110,102 +192,75 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
110
192
|
define_method method_name do |*args, &blk|
|
111
193
|
options = args.last.is_a?(Hash) ? args.last : {}
|
112
194
|
records = args[args.last.is_a?(Hash) ? -2 : -1]
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
# - default values filled by the database
|
124
|
-
# - updates on conflict conditions
|
125
|
-
records_to_invalidate =
|
126
|
-
if columns_to_update
|
127
|
-
RedisMemo::MemoizeQuery::Invalidation.send(
|
128
|
-
:select_by_columns,
|
129
|
-
records,
|
130
|
-
columns_to_update,
|
131
|
-
)
|
195
|
+
on_duplicate_key_update = options[:on_duplicate_key_update]
|
196
|
+
conflict_target =
|
197
|
+
case on_duplicate_key_update
|
198
|
+
when Hash
|
199
|
+
# The conflict_target option is only supported in PostgreSQL. In
|
200
|
+
# MySQL, the primary_key is used as the conflict_target
|
201
|
+
on_duplicate_key_update[:conflict_target] || [model_class.primary_key.to_sym]
|
202
|
+
when Array
|
203
|
+
# The default conflict_target is just the primary_key
|
204
|
+
[model_class.primary_key.to_sym]
|
132
205
|
else
|
133
|
-
|
206
|
+
# Ignore duplicate rows
|
207
|
+
nil
|
134
208
|
end
|
135
209
|
|
136
|
-
|
137
|
-
|
138
|
-
# Offload the records to invalidate while selecting the next set of
|
139
|
-
# records to invalidate
|
140
|
-
case records_to_invalidate
|
141
|
-
when Array
|
142
|
-
RedisMemo::MemoizeQuery.invalidate(*records_to_invalidate) unless records_to_invalidate.empty?
|
143
|
-
|
144
|
-
RedisMemo::MemoizeQuery.invalidate(*RedisMemo::MemoizeQuery::Invalidation.send(
|
145
|
-
:select_by_id,
|
146
|
-
model_class,
|
147
|
-
# Not all databases support "RETURNING", which is useful when
|
148
|
-
# invaldating records after bulk creation
|
149
|
-
result.ids,
|
150
|
-
))
|
151
|
-
else
|
152
|
-
RedisMemo::MemoizeQuery.invalidate_all(model_class)
|
210
|
+
if conflict_target && records.last.is_a?(Hash)
|
211
|
+
records.map! { |hash| model_class.new(hash) }
|
153
212
|
end
|
154
213
|
|
155
|
-
|
214
|
+
RedisMemo::MemoizeQuery::Invalidation.invalidate_records_by_conflict_target(
|
215
|
+
model_class,
|
216
|
+
records: records,
|
217
|
+
conflict_target: conflict_target,
|
218
|
+
) do
|
219
|
+
send(:"#{method_name}_without_redis_memo_invalidation", *args, &blk)
|
220
|
+
end
|
156
221
|
end
|
157
222
|
end
|
158
223
|
end
|
159
224
|
|
160
|
-
def self.
|
161
|
-
model_class = records.first.class
|
225
|
+
def self.build_relation_by_conflict_target(model_class, records, conflict_target)
|
162
226
|
or_chain = nil
|
163
|
-
columns_to_select = columns_to_update & RedisMemo::MemoizeQuery
|
164
|
-
.memoized_columns(model_class)
|
165
|
-
.to_a.flatten.uniq
|
166
|
-
|
167
|
-
# Nothing to invalidate here
|
168
|
-
return [] if columns_to_select.empty?
|
169
227
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
records.each do |record|
|
175
|
-
conditions = {}
|
176
|
-
columns_to_select.each do |column|
|
177
|
-
conditions[column] = record.send(column)
|
178
|
-
end
|
179
|
-
if or_chain
|
180
|
-
or_chain = or_chain.or(model_class.where(conditions))
|
181
|
-
else
|
182
|
-
or_chain = model_class.where(conditions)
|
183
|
-
end
|
228
|
+
records.each do |record|
|
229
|
+
conditions = {}
|
230
|
+
conflict_target.each do |column|
|
231
|
+
conditions[column] = record.send(column)
|
184
232
|
end
|
185
|
-
|
186
|
-
|
187
|
-
if record_count > bulk_operations_invalidation_limit
|
188
|
-
nil
|
233
|
+
if or_chain
|
234
|
+
or_chain = or_chain.or(model_class.where(conditions))
|
189
235
|
else
|
190
|
-
|
236
|
+
or_chain = model_class.where(conditions)
|
191
237
|
end
|
192
238
|
end
|
239
|
+
|
240
|
+
or_chain
|
193
241
|
end
|
194
242
|
|
195
|
-
def self.
|
243
|
+
def self.select_by_new_ids(model_class, target_id)
|
196
244
|
RedisMemo::Tracer.trace(
|
197
245
|
'redis_memo.memoize_query.invalidation',
|
198
246
|
"#{__method__}##{model_class.name}",
|
199
247
|
) do
|
200
248
|
RedisMemo.without_memo do
|
201
|
-
model_class.where(
|
249
|
+
model_class.where(
|
250
|
+
model_class.arel_table[model_class.primary_key].gt(target_id),
|
251
|
+
).to_a
|
202
252
|
end
|
203
253
|
end
|
204
254
|
end
|
205
255
|
|
206
|
-
def self.
|
207
|
-
|
208
|
-
|
209
|
-
|
256
|
+
def self.select_by_conflict_target_relation(model_class, relation)
|
257
|
+
return [] unless relation
|
258
|
+
|
259
|
+
RedisMemo::Tracer.trace(
|
260
|
+
'redis_memo.memoize_query.invalidation',
|
261
|
+
"#{__method__}##{model_class.name}",
|
262
|
+
) do
|
263
|
+
RedisMemo.without_memo { relation.reload }
|
264
|
+
end
|
210
265
|
end
|
211
266
|
end
|
data/lib/redis_memo/options.rb
CHANGED
data/lib/redis_memo/redis.rb
CHANGED
@@ -31,7 +31,8 @@ class RedisMemo::Redis < Redis::Distributed
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class WithReplicas < ::Redis
|
34
|
-
def initialize(
|
34
|
+
def initialize(orig_options)
|
35
|
+
options = orig_options.dup
|
35
36
|
primary_option = options.shift
|
36
37
|
@replicas = options.map do |option|
|
37
38
|
option[:logger] ||= RedisMemo::DefaultOptions.logger
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Redis memo can be flaky due to transient network errors (e.g. Redis connection errors), or when
|
4
|
+
# used with async handlers. This class allows users to override the default redis-memo behavior
|
5
|
+
# to be more robust when testing their code that uses redis-memo.
|
6
|
+
module RedisMemo
|
7
|
+
class Testing
|
8
|
+
|
9
|
+
def self.__test_mode
|
10
|
+
@__test_mode
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.__test_mode=(mode)
|
14
|
+
@__test_mode = mode
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.enable_test_mode(&blk)
|
18
|
+
__set_test_mode(true, &blk)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.disable_test_mode(&blk)
|
22
|
+
__set_test_mode(false, &blk)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.enabled?
|
26
|
+
__test_mode
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.__set_test_mode(mode, &blk)
|
32
|
+
if blk.nil?
|
33
|
+
__test_mode = mode
|
34
|
+
else
|
35
|
+
prev_mode = __test_mode
|
36
|
+
begin
|
37
|
+
__test_mode = mode
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
__test_mode = prev_mode
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module TestOverrides
|
47
|
+
def without_memo?
|
48
|
+
if RedisMemo::Testing.enabled? && !RedisMemo::Memoizable::Invalidation.class_variable_get(:@@invalidation_queue).empty?
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
singleton_class.prepend(TestOverrides)
|
55
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-memo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chan Zuckerberg Initiative
|
@@ -192,6 +192,7 @@ files:
|
|
192
192
|
- lib/redis_memo/middleware.rb
|
193
193
|
- lib/redis_memo/options.rb
|
194
194
|
- lib/redis_memo/redis.rb
|
195
|
+
- lib/redis_memo/testing.rb
|
195
196
|
- lib/redis_memo/tracer.rb
|
196
197
|
homepage: https://github.com/chanzuckerberg/redis-memo
|
197
198
|
licenses:
|
@@ -208,9 +209,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
208
209
|
version: 2.5.0
|
209
210
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
210
211
|
requirements:
|
211
|
-
- - "
|
212
|
+
- - ">="
|
212
213
|
- !ruby/object:Gem::Version
|
213
|
-
version:
|
214
|
+
version: '0'
|
214
215
|
requirements: []
|
215
216
|
rubygems_version: 3.0.8
|
216
217
|
signing_key:
|