redis-memo 0.0.0.beta → 0.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,7 +6,7 @@ require_relative 'middleware'
6
6
  require_relative 'options'
7
7
 
8
8
  module RedisMemo::MemoizeMethod
9
- def memoize_method(method_name, **options, &depends_on)
9
+ def memoize_method(method_name, method_id: nil, **options, &depends_on)
10
10
  method_name_without_memo = :"_redis_memo_#{method_name}_without_memo"
11
11
  method_name_with_memo = :"_redis_memo_#{method_name}_with_memo"
12
12
 
@@ -15,11 +15,24 @@ module RedisMemo::MemoizeMethod
15
15
  define_method method_name_with_memo do |*args|
16
16
  return send(method_name_without_memo, *args) if RedisMemo.without_memo?
17
17
 
18
+ dependent_memos = nil
19
+ if depends_on
20
+ dependency = RedisMemo::MemoizeMethod.get_or_extract_dependencies(self, *args, &depends_on)
21
+ dependent_memos = dependency.memos
22
+ end
23
+
18
24
  future = RedisMemo::Future.new(
19
25
  self,
20
- RedisMemo::MemoizeMethod.method_id(self, method_name),
26
+ case method_id
27
+ when NilClass
28
+ RedisMemo::MemoizeMethod.method_id(self, method_name)
29
+ when String, Symbol
30
+ method_id
31
+ else
32
+ method_id.call(self, *args)
33
+ end,
21
34
  args,
22
- depends_on,
35
+ dependent_memos,
23
36
  options,
24
37
  method_name_without_memo,
25
38
  )
@@ -30,9 +43,25 @@ module RedisMemo::MemoizeMethod
30
43
  end
31
44
 
32
45
  future.execute
46
+ rescue RedisMemo::WithoutMemoization
47
+ send(method_name_without_memo, *args)
33
48
  end
34
49
 
35
50
  alias_method method_name, method_name_with_memo
51
+
52
+ @__redis_memo_method_dependencies ||= Hash.new
53
+ @__redis_memo_method_dependencies[method_name] = depends_on
54
+
55
+ define_method :dependency_of do |method_name, *method_args|
56
+ method_depends_on = self.class.instance_variable_get(:@__redis_memo_method_dependencies)[method_name]
57
+ unless method_depends_on
58
+ raise(
59
+ RedisMemo::ArgumentError,
60
+ "#{method_name} is not a memoized method"
61
+ )
62
+ end
63
+ RedisMemo::MemoizeMethod.get_or_extract_dependencies(self, *method_args, &method_depends_on)
64
+ end
36
65
  end
37
66
 
38
67
  def self.method_id(ref, method_name)
@@ -42,23 +71,34 @@ module RedisMemo::MemoizeMethod
42
71
  "#{class_name}#{is_class_method ? '::' : '#'}#{method_name}"
43
72
  end
44
73
 
45
- def self.method_cache_keys(future_contexts)
46
- memos = Array.new(future_contexts.size)
47
- future_contexts.each_with_index do |(ref, _, method_args, depends_on), i|
48
- if depends_on
49
- dependency = RedisMemo::Memoizable::Dependency.new
74
+ def self.extract_dependencies(ref, *method_args, &depends_on)
75
+ dependency = RedisMemo::Memoizable::Dependency.new
50
76
 
51
- # Resolve the dependency recursively
52
- dependency.instance_exec(ref, *method_args, &depends_on)
77
+ # Resolve the dependency recursively
78
+ dependency.instance_exec(ref, *method_args, &depends_on)
79
+ dependency
80
+ end
53
81
 
54
- memos[i] = dependency.memos
55
- end
82
+ def self.get_or_extract_dependencies(ref, *method_args, &depends_on)
83
+ if RedisMemo::Cache.local_dependency_cache
84
+ RedisMemo::Cache.local_dependency_cache[ref] ||= {}
85
+ RedisMemo::Cache.local_dependency_cache[ref][depends_on] ||= {}
86
+ RedisMemo::Cache.local_dependency_cache[ref][depends_on][method_args] ||= extract_dependencies(ref, *method_args, &depends_on)
87
+ else
88
+ extract_dependencies(ref, *method_args, &depends_on)
89
+ end
90
+ end
91
+
92
+ def self.method_cache_keys(future_contexts)
93
+ memos = Array.new(future_contexts.size)
94
+ future_contexts.each_with_index do |(_, _, dependent_memos), i|
95
+ memos[i] = dependent_memos
56
96
  end
57
97
 
58
98
  j = 0
59
99
  memo_checksums = RedisMemo::Memoizable.checksums(memos.compact)
60
100
  method_cache_key_versions = Array.new(future_contexts.size)
61
- future_contexts.each_with_index do |(_, method_id, method_args, _), i|
101
+ future_contexts.each_with_index do |(method_id, method_args, _), i|
62
102
  if memos[i]
63
103
  method_cache_key_versions[i] = [method_id, memo_checksums[j]]
64
104
  j += 1
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'memoize_method'
3
+
4
+ if defined?(ActiveRecord)
5
+ # Hook into ActiveRecord to cache SQL queries and perform auto cache
6
+ # invalidation
7
+ module RedisMemo::MemoizeQuery
8
+ require_relative 'memoize_query/cached_select'
9
+ require_relative 'memoize_query/invalidation'
10
+ require_relative 'memoize_query/model_callback'
11
+
12
+ # Only editable columns will be used to create memos that are invalidatable
13
+ # after each record save
14
+ def memoize_table_column(*raw_columns, editable: true)
15
+ RedisMemo::MemoizeQuery.using_active_record!(self)
16
+ return if ENV["REDIS_MEMO_DISABLE_#{self.table_name.upcase}"] == 'true'
17
+
18
+ columns = raw_columns.map(&:to_sym).sort
19
+
20
+ RedisMemo::MemoizeQuery.memoized_columns(self, editable_only: true) << columns if editable
21
+ RedisMemo::MemoizeQuery.memoized_columns(self, editable_only: false) << columns
22
+
23
+ RedisMemo::MemoizeQuery::ModelCallback.install(self)
24
+ RedisMemo::MemoizeQuery::Invalidation.install(self)
25
+
26
+ if ENV['REDIS_MEMO_DISABLE_CACHED_SELECT'] != 'true'
27
+ RedisMemo::MemoizeQuery::CachedSelect.install(ActiveRecord::Base.connection)
28
+ end
29
+
30
+ # The code below might fail due to missing DB/table errors
31
+ columns.each do |column|
32
+ unless self.columns_hash.include?(column.to_s)
33
+ raise(
34
+ RedisMemo::ArgumentError,
35
+ "'#{self.name}' does not contain column '#{column}'",
36
+ )
37
+ end
38
+ end
39
+
40
+ unless ENV["REDIS_MEMO_DISABLE_QUERY_#{self.table_name.upcase}"] == 'true'
41
+ RedisMemo::MemoizeQuery::CachedSelect.enabled_models[self.table_name] = self
42
+ end
43
+ rescue ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid
44
+ # no-opts: models with memoize_table_column decleared might be loaded in
45
+ # rake tasks that are used to create databases
46
+ end
47
+
48
+ def self.using_active_record!(model_class)
49
+ unless using_active_record?(model_class)
50
+ raise RedisMemo::ArgumentError, "'#{model_class.name}' does not use ActiveRecord"
51
+ end
52
+ end
53
+
54
+ def self.using_active_record?(model_class)
55
+ model_class.respond_to?(:<) && model_class < ActiveRecord::Base
56
+ end
57
+
58
+ @@memoized_columns = Hash.new { |h, k| h[k] = [Set.new, Set.new] }
59
+
60
+ def self.memoized_columns(model_or_table, editable_only: false)
61
+ table = model_or_table.is_a?(Class) ? model_or_table.table_name : model_or_table
62
+ @@memoized_columns[table.to_sym][editable_only ? 1 : 0]
63
+ end
64
+
65
+ # extra_props are considered as AND conditions on the model class
66
+ def self.create_memo(model_class, **extra_props)
67
+ using_active_record!(model_class)
68
+
69
+ keys = extra_props.keys.sort
70
+ if !keys.empty? && !memoized_columns(model_class).include?(keys)
71
+ raise(
72
+ RedisMemo::ArgumentError,
73
+ "'#{model_class.name}' has not memoized columns: #{keys}",
74
+ )
75
+ end
76
+
77
+ extra_props.each do |key, value|
78
+ # The data type is ensured by the database, thus we don't need to cast
79
+ # types here for better performance
80
+ column_name = key.to_s
81
+ extra_props[key] =
82
+ if model_class.defined_enums.include?(column_name)
83
+ enum_mapping = model_class.defined_enums[column_name]
84
+ # Assume a value is a converted enum if it does not exist in the
85
+ # enum mapping
86
+ (enum_mapping[value.to_s] || value).to_s
87
+ else
88
+ value.to_s
89
+ end
90
+ end
91
+
92
+ RedisMemo::Memoizable.new(
93
+ __redis_memo_memoize_query_table_name__: model_class.table_name,
94
+ **extra_props,
95
+ )
96
+ end
97
+
98
+ def self.invalidate_all(model_class)
99
+ RedisMemo::Tracer.trace(
100
+ 'redis_memo.memoizable.invalidate_all',
101
+ model_class.name,
102
+ ) do
103
+ RedisMemo::Memoizable.invalidate([model_class.redis_memo_class_memoizable])
104
+ end
105
+ end
106
+
107
+ def self.invalidate(*records)
108
+ RedisMemo::Memoizable.invalidate(
109
+ records.map { |record| to_memos(record) }.flatten,
110
+ )
111
+ end
112
+
113
+ def self.to_memos(record)
114
+ # Invalidate memos with current values
115
+ memos_to_invalidate = memoized_columns(record.class).map do |columns|
116
+ props = {}
117
+ columns.each do |column|
118
+ props[column] = record.send(column)
119
+ end
120
+
121
+ create_memo(record.class, **props)
122
+ end
123
+
124
+ # Create memos with previous values if
125
+ # - there are saved changes
126
+ # - this is not creating a new record
127
+ if !record.saved_changes.empty? && !record.saved_changes.include?(record.class.primary_key)
128
+ previous_values = {}
129
+ record.saved_changes.each do |column, (previous_value, _)|
130
+ previous_values[column.to_sym] = previous_value
131
+ end
132
+
133
+ memoized_columns(record.class, editable_only: true).each do |columns|
134
+ props = previous_values.slice(*columns)
135
+ next if props.empty?
136
+
137
+ # Fill the column values that have not changed
138
+ columns.each do |column|
139
+ next if props.include?(column)
140
+
141
+ props[column] = record.send(column)
142
+ end
143
+
144
+ memos_to_invalidate << create_memo(record.class, **props)
145
+ end
146
+ end
147
+
148
+ memos_to_invalidate
149
+ end
150
+ end
151
+ end
@@ -38,7 +38,7 @@
38
38
  # the `memoize_table_column` declaration on the model class.
39
39
  #
40
40
  # class MyRecord < ApplicationRecord
41
- # extend RedisMemo::MemoizeRecords
41
+ # extend RedisMemo::MemoizeQuery
42
42
  # memoize_table_column :value
43
43
  # end
44
44
  #
@@ -87,8 +87,17 @@
87
87
  #
88
88
  # See +extract_bind_params+ for the precise detection logic.
89
89
  #
90
- class RedisMemo::MemoizeRecords::CachedSelect
91
- # TODO: merge this into RedisMemo::MemoizeQuery
90
+ class RedisMemo::MemoizeQuery::CachedSelect
91
+ require_relative 'cached_select/bind_params'
92
+ require_relative 'cached_select/connection_adapter'
93
+ require_relative 'cached_select/statement_cache'
94
+
95
+ @@enabled_models = {}
96
+
97
+ def self.enabled_models
98
+ @@enabled_models
99
+ end
100
+
92
101
  def self.install(connection)
93
102
  klass = connection.class
94
103
  return if klass.singleton_class < RedisMemo::MemoizeMethod
@@ -96,8 +105,14 @@ class RedisMemo::MemoizeRecords::CachedSelect
96
105
  klass.class_eval do
97
106
  extend RedisMemo::MemoizeMethod
98
107
 
99
- memoize_method :exec_query do |_, sql, name, binds, **kwargs|
100
- RedisMemo::MemoizeRecords::CachedSelect
108
+ memoize_method(
109
+ :exec_query,
110
+ method_id: proc do |_, sql, *args|
111
+ sql.gsub(/(\$\d+)/, '?') # $1 -> ?
112
+ .gsub(/((, *)*\?)+/, '?') # (?, ?, ? ...) -> (?)
113
+ end,
114
+ ) do |_, sql, name, binds, **kwargs|
115
+ RedisMemo::MemoizeQuery::CachedSelect
101
116
  .current_query_bind_params
102
117
  .params
103
118
  .each do |model, attrs_set|
@@ -107,8 +122,15 @@ class RedisMemo::MemoizeRecords::CachedSelect
107
122
  end
108
123
 
109
124
  depends_on RedisMemo::Memoizable.new(
110
- __redis_memo_memoize_records_memoize_query_sql__: sql,
111
- __redis_memo_memoize_records_memoize_query_binds__: binds.map(&:value_for_database),
125
+ __redis_memo_memoize_query_memoize_query_sql__: sql,
126
+ __redis_memo_memoize_query_memoize_query_binds__: binds.map do |bind|
127
+ if bind.respond_to?(:value_for_database)
128
+ bind.value_for_database
129
+ else
130
+ # In activerecord >= 6, a bind could be an actual database value
131
+ bind
132
+ end
133
+ end
112
134
  )
113
135
  end
114
136
  end
@@ -137,64 +159,6 @@ class RedisMemo::MemoizeRecords::CachedSelect
137
159
  end
138
160
  end
139
161
 
140
- module ConnectionAdapter
141
- def cacheable_query(*args)
142
- query, binds = super(*args)
143
-
144
- # Persist the arel object to StatementCache#execute
145
- query.instance_variable_set(:@__redis_memo_memoize_records_memoize_query_arel, args.last)
146
-
147
- [query, binds]
148
- end
149
-
150
- def exec_query(*args)
151
- # An Arel AST in Thread local is set prior to supported query methods
152
- if !RedisMemo.without_memo? &&
153
- RedisMemo::MemoizeRecords::CachedSelect.extract_bind_params(args[0])
154
- # [Reids $model Load] $sql $binds
155
- RedisMemo::DefaultOptions.logger&.info(
156
- "[Redis] \u001b[36;1m#{args[1]} \u001b[34;1m#{args[0]}\u001b[0m #{
157
- args[2].map { |bind| [bind.name, bind.value_for_database]}
158
- }"
159
- )
160
-
161
- RedisMemo::Tracer.trace(
162
- 'redis_memo.memoize_query',
163
- args[0]
164
- .gsub(/(\$\d+)/, '?') # $1 -> ?
165
- .gsub(/((, *)*\?)+/, '?'), # (?, ?, ? ...) -> (?)
166
- ) do
167
- super(*args)
168
- end
169
- else
170
- RedisMemo.without_memo { super(*args) }
171
- end
172
- end
173
-
174
- def select_all(*args)
175
- if args[0].is_a?(Arel::SelectManager)
176
- RedisMemo::MemoizeRecords::CachedSelect.current_query = args[0]
177
- end
178
-
179
- super(*args)
180
- ensure
181
- RedisMemo::MemoizeRecords::CachedSelect.reset_current_query
182
- end
183
- end
184
-
185
- module StatementCache
186
- def execute(*args)
187
- arel = query_builder.instance_variable_get(:@__redis_memo_memoize_records_memoize_query_arel)
188
- RedisMemo::MemoizeRecords::CachedSelect.current_query = arel
189
- RedisMemo::MemoizeRecords::CachedSelect.current_substitutes =
190
- bind_map.map_substitutes(args[0])
191
-
192
- super(*args)
193
- ensure
194
- RedisMemo::MemoizeRecords::CachedSelect.reset_current_query
195
- end
196
- end
197
-
198
162
  def self.extract_bind_params(sql)
199
163
  ast = Thread.current[THREAD_KEY_AREL]&.ast
200
164
  return false unless ast.is_a?(Arel::Nodes::SelectStatement)
@@ -230,6 +194,19 @@ class RedisMemo::MemoizeRecords::CachedSelect
230
194
  Thread.current[THREAD_KEY_AREL_BIND_PARAMS] = nil
231
195
  end
232
196
 
197
+ def self.with_new_query_context
198
+ prev_arel = Thread.current[THREAD_KEY_AREL]
199
+ prev_substitutes = Thread.current[THREAD_KEY_SUBSTITUTES]
200
+ prev_bind_params = Thread.current[THREAD_KEY_AREL_BIND_PARAMS]
201
+ RedisMemo::MemoizeQuery::CachedSelect.reset_current_query
202
+
203
+ yield
204
+ ensure
205
+ Thread.current[THREAD_KEY_AREL] = prev_arel
206
+ Thread.current[THREAD_KEY_SUBSTITUTES] = prev_substitutes
207
+ Thread.current[THREAD_KEY_AREL_BIND_PARAMS] = prev_bind_params
208
+ end
209
+
233
210
  private
234
211
 
235
212
  # A pre-order Depth First Search
@@ -240,7 +217,7 @@ class RedisMemo::MemoizeRecords::CachedSelect
240
217
  bind_params = BindParams.new
241
218
 
242
219
  case node
243
- when Arel::Nodes::Equality, Arel::Nodes::In
220
+ when NodeHasFilterCondition
244
221
  attr_node = node.left
245
222
  return unless attr_node.is_a?(Arel::Attributes::Attribute)
246
223
 
@@ -255,16 +232,8 @@ class RedisMemo::MemoizeRecords::CachedSelect
255
232
  return
256
233
  end
257
234
 
258
- type_caster = table_node.send(:type_caster)
259
- binding_relation =
260
- case type_caster
261
- when ActiveRecord::TypeCaster::Map
262
- type_caster.send(:types)
263
- when ActiveRecord::TypeCaster::Connection
264
- type_caster.instance_variable_get(:@klass)
265
- else
266
- return
267
- end
235
+ binding_relation = extract_binding_relation(table_node)
236
+ return unless binding_relation
268
237
 
269
238
  rights = node.right.is_a?(Array) ? node.right : [node.right]
270
239
  substitutes = Thread.current[THREAD_KEY_SUBSTITUTES]
@@ -285,7 +254,13 @@ class RedisMemo::MemoizeRecords::CachedSelect
285
254
  }
286
255
  when Arel::Nodes::Casted
287
256
  bind_params.params[binding_relation] << {
288
- right.attribute.name.to_sym => right.val,
257
+ right.attribute.name.to_sym =>
258
+ if right.respond_to?(:val)
259
+ right.val
260
+ else
261
+ # activerecord >= 6
262
+ right.value
263
+ end,
289
264
  }
290
265
  else
291
266
  bind_params = bind_params.union(extract_bind_params_recurse(right))
@@ -303,11 +278,17 @@ class RedisMemo::MemoizeRecords::CachedSelect
303
278
  return unless node.orders.empty?
304
279
 
305
280
  node.cores.each do |core|
281
+ # We don't support JOINs
282
+ return unless core.source.right.empty?
283
+
306
284
  # Should have a WHERE if directly selecting from a table
307
285
  source_node = core.source.left
286
+ binding_relation = nil
308
287
  case source_node
309
288
  when Arel::Table
310
- return if core.wheres.empty?
289
+ binding_relation = extract_binding_relation(source_node)
290
+
291
+ return if core.wheres.empty? || binding_relation.nil?
311
292
  when Arel::Nodes::TableAlias
312
293
  bind_params = bind_params.union(
313
294
  extract_bind_params_recurse(source_node.left)
@@ -334,6 +315,9 @@ class RedisMemo::MemoizeRecords::CachedSelect
334
315
 
335
316
  return unless bind_params
336
317
  end
318
+
319
+ # Reject any unbound select queries
320
+ return if binding_relation && bind_params.params[binding_relation].empty?
337
321
  end
338
322
 
339
323
  bind_params
@@ -352,7 +336,7 @@ class RedisMemo::MemoizeRecords::CachedSelect
352
336
  end
353
337
 
354
338
  bind_params
355
- when Arel::Nodes::Join, Arel::Nodes::Union, Arel::Nodes::Or
339
+ when Arel::Nodes::Union, Arel::Nodes::Or
356
340
  [node.left, node.right].each do |child|
357
341
  bind_params = bind_params.union(
358
342
  extract_bind_params_recurse(child)
@@ -368,132 +352,29 @@ class RedisMemo::MemoizeRecords::CachedSelect
368
352
  end
369
353
  end
370
354
 
371
- class BindParams
372
- def params
373
- #
374
- # Bind params is hash of sets: each key is a model class, each value is a
375
- # set of hashes for memoized column conditions. Example:
376
- #
377
- # {
378
- # Site => [
379
- # {name: 'a', city: 'b'},
380
- # {name: 'a', city: 'c'},
381
- # {name: 'b', city: 'b'},
382
- # {name: 'b', city: 'c'},
383
- # ],
384
- # }
385
- #
386
- @params ||= Hash.new do |models, model|
387
- models[model] = []
388
- end
389
- end
390
-
391
- def union(other)
392
- return unless other
355
+ def self.extract_binding_relation(table_node)
356
+ enabled_models[table_node.try(:name)]
357
+ end
393
358
 
394
- # The tree is almost always right-heavy. Merge into the right node for better
395
- # performance.
396
- other.params.merge!(params) do |_, other_attrs_set, attrs_set|
397
- if other_attrs_set.empty?
398
- attrs_set
399
- elsif attrs_set.empty?
400
- other_attrs_set
359
+ class NodeHasFilterCondition
360
+ def self.===(node)
361
+ case node
362
+ when Arel::Nodes::Equality, Arel::Nodes::In
363
+ true
364
+ else
365
+ # In activerecord >= 6, a new arel node HomogeneousIn is introduced
366
+ if defined?(Arel::Nodes::HomogeneousIn) &&
367
+ node.is_a?(Arel::Nodes::HomogeneousIn)
368
+ true
401
369
  else
402
- attrs_set + other_attrs_set
403
- end
404
- end
405
-
406
- other
407
- end
408
-
409
- def product(other)
410
- # Example:
411
- #
412
- # and(
413
- # [{a: 1}, {a: 2}],
414
- # [{b: 1}, {b: 2}],
415
- # )
416
- #
417
- # =>
418
- #
419
- # [
420
- # {a: 1, b: 1},
421
- # {a: 1, b: 2},
422
- # {a: 2, b: 1},
423
- # {a: 2, b: 2},
424
- # ]
425
- return unless other
426
-
427
- # The tree is almost always right-heavy. Merge into the right node for better
428
- # performance.
429
- params.each do |model, attrs_set|
430
- next if attrs_set.empty?
431
-
432
- # The other model does not have any conditions so far: carry the
433
- # attributes over to the other node
434
- if other.params[model].empty?
435
- other.params[model] = attrs_set
436
- next
437
- end
438
-
439
- # Distribute the current attrs into the other
440
- other_attrs_set_size = other.params[model].size
441
- other_attrs_set = other.params[model]
442
- merged_attrs_set = Array.new(other_attrs_set_size * attrs_set.size)
443
-
444
- attrs_set.each_with_index do |attrs, i|
445
- other_attrs_set.each_with_index do |other_attrs, j|
446
- k = i * other_attrs_set_size + j
447
- merged_attrs = merged_attrs_set[k] = other_attrs.dup
448
- attrs.each do |name, val|
449
- # Conflict detected. For example:
450
- #
451
- # (a = 1 or b = 1) and (a = 2 or b = 2)
452
- #
453
- # Keep: a = 1 and b = 2, a = 2 and b = 1
454
- # Discard: a = 1 and a = 2, b = 1 and b = 2
455
- if merged_attrs.include?(name) && merged_attrs[name] != val
456
- merged_attrs_set[k] = nil
457
- break
458
- end
459
-
460
- merged_attrs[name] = val
461
- end
462
- end
370
+ false
463
371
  end
464
-
465
- merged_attrs_set.compact!
466
- other.params[model] = merged_attrs_set
467
- end
468
-
469
- other
470
- end
471
-
472
- def uniq!
473
- params.each do |_, attrs_set|
474
- attrs_set.uniq!
475
372
  end
476
373
  end
477
-
478
- def memoizable?
479
- return false if params.empty?
480
-
481
- params.each do |model, attrs_set|
482
- return false if attrs_set.empty?
483
-
484
- attrs_set.each do |attrs|
485
- return false unless RedisMemo::MemoizeRecords
486
- .memoized_columns(model)
487
- .include?(attrs.keys.sort)
488
- end
489
- end
490
-
491
- true
492
- end
493
374
  end
494
375
 
495
376
  # Thread locals to exchange information between RedisMemo and ActiveRecord
496
- THREAD_KEY_AREL = :__redis_memo_memoize_records_cached_select_arel__
497
- THREAD_KEY_SUBSTITUTES = :__redis_memo_memoize_records_cached_select_substitues__
498
- THREAD_KEY_AREL_BIND_PARAMS = :__redis_memo_memoize_records_cached_select_arel_bind_params__
377
+ THREAD_KEY_AREL = :__redis_memo_memoize_query_cached_select_arel__
378
+ THREAD_KEY_SUBSTITUTES = :__redis_memo_memoize_query_cached_select_substitues__
379
+ THREAD_KEY_AREL_BIND_PARAMS = :__redis_memo_memoize_query_cached_select_arel_bind_params__
499
380
  end