redis-memo 0.0.0.beta.3 → 0.0.0.beta.4
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.rb +1 -0
- data/lib/redis_memo/cache.rb +9 -3
- data/lib/redis_memo/connection_pool.rb +27 -0
- data/lib/redis_memo/future.rb +3 -3
- data/lib/redis_memo/memoizable.rb +5 -1
- data/lib/redis_memo/memoizable/dependency.rb +2 -2
- data/lib/redis_memo/memoizable/invalidation.rb +6 -2
- data/lib/redis_memo/memoize_method.rb +12 -7
- data/lib/redis_memo/memoize_query.rb +6 -2
- data/lib/redis_memo/memoize_query/cached_select.rb +33 -3
- data/lib/redis_memo/memoize_query/invalidation.rb +64 -25
- data/lib/redis_memo/options.rb +17 -18
- metadata +24 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72bcf0679b811825222a6b38de0fcdadf4546640d2f61b18ebc827e37137dc41
|
4
|
+
data.tar.gz: 7a55c7bbd084a24afe085e85bc5cd5c486cf240094b64ca09d48e9e0ce126384
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a3af887512e4b6571829fcfda719e43abb917eb4773407bd27788b0b671a42263ec31c2f6286f0a1279a354851c8c8cb48eb9701cba59863e500ca47419080e
|
7
|
+
data.tar.gz: feeb72b177ec07953b839e6e0759cbdf42dfd4eddd19f89599e721589462e849e7685a659b03128504d670764223f1805402cb3ee8a96411b834f229ba837d99
|
data/lib/redis_memo.rb
CHANGED
data/lib/redis_memo/cache.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_relative 'options'
|
3
3
|
require_relative 'redis'
|
4
|
+
require_relative 'connection_pool'
|
4
5
|
|
5
6
|
class RedisMemo::Cache < ActiveSupport::Cache::RedisCacheStore
|
6
7
|
class Rescuable < Exception; end
|
@@ -24,7 +25,12 @@ class RedisMemo::Cache < ActiveSupport::Cache::RedisCacheStore
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def self.redis
|
27
|
-
@@redis ||=
|
28
|
+
@@redis ||=
|
29
|
+
if RedisMemo::DefaultOptions.connection_pool
|
30
|
+
RedisMemo::ConnectionPool.new(**RedisMemo::DefaultOptions.connection_pool)
|
31
|
+
else
|
32
|
+
RedisMemo::DefaultOptions.redis
|
33
|
+
end
|
28
34
|
end
|
29
35
|
|
30
36
|
def self.redis_store
|
@@ -60,7 +66,7 @@ class RedisMemo::Cache < ActiveSupport::Cache::RedisCacheStore
|
|
60
66
|
end
|
61
67
|
|
62
68
|
# RedisCacheStore doesn't read from the local cache before reading from redis
|
63
|
-
def read_multi(*keys, raise_error: false)
|
69
|
+
def read_multi(*keys, raw: false, raise_error: false)
|
64
70
|
return {} if keys.empty?
|
65
71
|
|
66
72
|
Thread.current[THREAD_KEY_RAISE_ERROR] = raise_error
|
@@ -71,7 +77,7 @@ class RedisMemo::Cache < ActiveSupport::Cache::RedisCacheStore
|
|
71
77
|
keys_to_fetch -= local_entries.keys unless local_entries.empty?
|
72
78
|
return local_entries if keys_to_fetch.empty?
|
73
79
|
|
74
|
-
remote_entries = redis_store.read_multi(*keys_to_fetch)
|
80
|
+
remote_entries = redis_store.read_multi(*keys_to_fetch, raw: raw)
|
75
81
|
local_cache&.merge!(remote_entries)
|
76
82
|
|
77
83
|
if local_entries.empty?
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'connection_pool'
|
3
|
+
require_relative 'redis'
|
4
|
+
|
5
|
+
class RedisMemo::ConnectionPool
|
6
|
+
def initialize(**options)
|
7
|
+
@connection_pool = ::ConnectionPool.new(**options) do
|
8
|
+
# Construct a new client every time the block gets called
|
9
|
+
RedisMemo::Redis.new(RedisMemo::DefaultOptions.redis_config)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Avoid method_missing when possible for better performance
|
14
|
+
%i(get mget mapped_mget set eval).each do |method_name|
|
15
|
+
define_method method_name do |*args, &blk|
|
16
|
+
@connection_pool.with do |redis|
|
17
|
+
redis.send(method_name, *args, &blk)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(method_name, *args, &blk)
|
23
|
+
@connection_pool.with do |redis|
|
24
|
+
redis.send(method_name, *args, &blk)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/redis_memo/future.rb
CHANGED
@@ -9,14 +9,14 @@ class RedisMemo::Future
|
|
9
9
|
ref,
|
10
10
|
method_id,
|
11
11
|
method_args,
|
12
|
-
|
12
|
+
dependent_memos,
|
13
13
|
cache_options,
|
14
14
|
method_name_without_memo
|
15
15
|
)
|
16
16
|
@ref = ref
|
17
17
|
@method_id = method_id
|
18
18
|
@method_args = method_args
|
19
|
-
@
|
19
|
+
@dependent_memos = dependent_memos
|
20
20
|
@cache_options = cache_options
|
21
21
|
@method_name_without_memo = method_name_without_memo
|
22
22
|
@method_cache_key = nil
|
@@ -28,7 +28,7 @@ class RedisMemo::Future
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def context
|
31
|
-
[@
|
31
|
+
[@method_id, @method_args, @dependent_memos]
|
32
32
|
end
|
33
33
|
|
34
34
|
def method_cache_key
|
@@ -82,7 +82,11 @@ class RedisMemo::Memoizable
|
|
82
82
|
if keys_to_fetch.empty?
|
83
83
|
{}
|
84
84
|
else
|
85
|
-
RedisMemo::Cache.read_multi(
|
85
|
+
RedisMemo::Cache.read_multi(
|
86
|
+
*keys_to_fetch,
|
87
|
+
raw: true,
|
88
|
+
raise_error: true,
|
89
|
+
)
|
86
90
|
end
|
87
91
|
memo_versions.merge!(cached_versions) unless cached_versions.empty?
|
88
92
|
|
@@ -51,8 +51,8 @@ class RedisMemo::Memoizable::Dependency
|
|
51
51
|
RedisMemo::MemoizeQuery::CachedSelect.current_query = relation.arel
|
52
52
|
is_query_cached = RedisMemo::MemoizeQuery::CachedSelect.extract_bind_params(query)
|
53
53
|
raise(
|
54
|
-
RedisMemo::
|
55
|
-
"
|
54
|
+
RedisMemo::WithoutMemoization,
|
55
|
+
"Arel query is not cached using RedisMemo."
|
56
56
|
) unless is_query_cached
|
57
57
|
extracted_dependency = connection.dependency_of(:exec_query, query, nil, binds)
|
58
58
|
end
|
@@ -56,7 +56,10 @@ module RedisMemo::Memoizable::Invalidation
|
|
56
56
|
# Fill an expected previous version so the later calculation results
|
57
57
|
# based on this version can still be rolled out if this version
|
58
58
|
# does not change
|
59
|
-
previous_version ||= RedisMemo::Cache.read_multi(
|
59
|
+
previous_version ||= RedisMemo::Cache.read_multi(
|
60
|
+
key,
|
61
|
+
raw: true,
|
62
|
+
)[key]
|
60
63
|
end
|
61
64
|
|
62
65
|
local_cache&.send(:[]=, key, version)
|
@@ -123,7 +126,8 @@ module RedisMemo::Memoizable::Invalidation
|
|
123
126
|
task = @@invalidation_queue.pop
|
124
127
|
begin
|
125
128
|
bump_version(task)
|
126
|
-
rescue SignalException, Redis::BaseConnectionError
|
129
|
+
rescue SignalException, Redis::BaseConnectionError,
|
130
|
+
::ConnectionPool::TimeoutError
|
127
131
|
retry_queue << task
|
128
132
|
end
|
129
133
|
end
|
@@ -15,6 +15,12 @@ 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
26
|
case method_id
|
@@ -26,7 +32,7 @@ module RedisMemo::MemoizeMethod
|
|
26
32
|
method_id.call(self, *args)
|
27
33
|
end,
|
28
34
|
args,
|
29
|
-
|
35
|
+
dependent_memos,
|
30
36
|
options,
|
31
37
|
method_name_without_memo,
|
32
38
|
)
|
@@ -37,6 +43,8 @@ module RedisMemo::MemoizeMethod
|
|
37
43
|
end
|
38
44
|
|
39
45
|
future.execute
|
46
|
+
rescue RedisMemo::WithoutMemoization
|
47
|
+
send(method_name_without_memo, *args)
|
40
48
|
end
|
41
49
|
|
42
50
|
alias_method method_name, method_name_with_memo
|
@@ -83,17 +91,14 @@ module RedisMemo::MemoizeMethod
|
|
83
91
|
|
84
92
|
def self.method_cache_keys(future_contexts)
|
85
93
|
memos = Array.new(future_contexts.size)
|
86
|
-
future_contexts.each_with_index do |(
|
87
|
-
|
88
|
-
dependency = get_or_extract_dependencies(ref, *method_args, &depends_on)
|
89
|
-
memos[i] = dependency.memos
|
90
|
-
end
|
94
|
+
future_contexts.each_with_index do |(_, _, dependent_memos), i|
|
95
|
+
memos[i] = dependent_memos
|
91
96
|
end
|
92
97
|
|
93
98
|
j = 0
|
94
99
|
memo_checksums = RedisMemo::Memoizable.checksums(memos.compact)
|
95
100
|
method_cache_key_versions = Array.new(future_contexts.size)
|
96
|
-
future_contexts.each_with_index do |(
|
101
|
+
future_contexts.each_with_index do |(method_id, method_args, _), i|
|
97
102
|
if memos[i]
|
98
103
|
method_cache_key_versions[i] = [method_id, memo_checksums[j]]
|
99
104
|
j += 1
|
@@ -13,6 +13,8 @@ if defined?(ActiveRecord)
|
|
13
13
|
# after each record save
|
14
14
|
def memoize_table_column(*raw_columns, editable: true)
|
15
15
|
RedisMemo::MemoizeQuery.using_active_record!(self)
|
16
|
+
return if ENV["REDIS_MEMO_DISABLE_#{self.table_name.upcase}"] == 'true'
|
17
|
+
|
16
18
|
columns = raw_columns.map(&:to_sym).sort
|
17
19
|
|
18
20
|
RedisMemo::MemoizeQuery.memoized_columns(self, editable_only: true) << columns if editable
|
@@ -102,8 +104,10 @@ if defined?(ActiveRecord)
|
|
102
104
|
end
|
103
105
|
end
|
104
106
|
|
105
|
-
def self.invalidate(
|
106
|
-
RedisMemo::Memoizable.invalidate(
|
107
|
+
def self.invalidate(*records)
|
108
|
+
RedisMemo::Memoizable.invalidate(
|
109
|
+
records.map { |record| to_memos(record) }.flatten,
|
110
|
+
)
|
107
111
|
end
|
108
112
|
|
109
113
|
def self.to_memos(record)
|
@@ -123,7 +123,14 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
123
123
|
|
124
124
|
depends_on RedisMemo::Memoizable.new(
|
125
125
|
__redis_memo_memoize_query_memoize_query_sql__: sql,
|
126
|
-
__redis_memo_memoize_query_memoize_query_binds__: binds.map
|
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
|
127
134
|
)
|
128
135
|
end
|
129
136
|
end
|
@@ -210,7 +217,7 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
210
217
|
bind_params = BindParams.new
|
211
218
|
|
212
219
|
case node
|
213
|
-
when
|
220
|
+
when NodeHasFilterCondition
|
214
221
|
attr_node = node.left
|
215
222
|
return unless attr_node.is_a?(Arel::Attributes::Attribute)
|
216
223
|
|
@@ -247,7 +254,13 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
247
254
|
}
|
248
255
|
when Arel::Nodes::Casted
|
249
256
|
bind_params.params[binding_relation] << {
|
250
|
-
right.attribute.name.to_sym =>
|
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,
|
251
264
|
}
|
252
265
|
else
|
253
266
|
bind_params = bind_params.union(extract_bind_params_recurse(right))
|
@@ -343,6 +356,23 @@ class RedisMemo::MemoizeQuery::CachedSelect
|
|
343
356
|
enabled_models[table_node.try(:name)]
|
344
357
|
end
|
345
358
|
|
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
|
369
|
+
else
|
370
|
+
false
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
346
376
|
# Thread locals to exchange information between RedisMemo and ActiveRecord
|
347
377
|
THREAD_KEY_AREL = :__redis_memo_memoize_query_cached_select_arel__
|
348
378
|
THREAD_KEY_SUBSTITUTES = :__redis_memo_memoize_query_cached_select_substitues__
|
@@ -110,9 +110,9 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
110
110
|
define_method method_name do |*args, &blk|
|
111
111
|
options = args.last.is_a?(Hash) ? args.last : {}
|
112
112
|
records = args[args.last.is_a?(Hash) ? -2 : -1]
|
113
|
-
|
114
|
-
if
|
115
|
-
|
113
|
+
columns_to_update = options[:on_duplicate_key_update]
|
114
|
+
if columns_to_update.is_a?(Hash)
|
115
|
+
columns_to_update = columns_to_update[:columns]
|
116
116
|
end
|
117
117
|
|
118
118
|
if records.last.is_a?(Hash)
|
@@ -123,11 +123,11 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
123
123
|
# - default values filled by the database
|
124
124
|
# - updates on conflict conditions
|
125
125
|
records_to_invalidate =
|
126
|
-
if
|
126
|
+
if columns_to_update
|
127
127
|
RedisMemo::MemoizeQuery::Invalidation.send(
|
128
|
-
:
|
128
|
+
:select_by_columns,
|
129
129
|
records,
|
130
|
-
|
130
|
+
columns_to_update,
|
131
131
|
)
|
132
132
|
else
|
133
133
|
[]
|
@@ -135,38 +135,77 @@ class RedisMemo::MemoizeQuery::Invalidation
|
|
135
135
|
|
136
136
|
result = send(:"#{method_name}_without_redis_memo_invalidation", *args, &blk)
|
137
137
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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)
|
142
153
|
end
|
143
154
|
|
144
|
-
memos_to_invalidate = records_to_invalidate.map do |record|
|
145
|
-
RedisMemo::MemoizeQuery.to_memos(record)
|
146
|
-
end
|
147
|
-
RedisMemo::Memoizable.invalidate(memos_to_invalidate.flatten)
|
148
|
-
|
149
155
|
result
|
150
156
|
end
|
151
157
|
end
|
152
158
|
end
|
153
159
|
|
154
|
-
def self.
|
160
|
+
def self.select_by_columns(records, columns_to_update)
|
155
161
|
model_class = records.first.class
|
156
162
|
or_chain = nil
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
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
|
+
|
170
|
+
RedisMemo::Tracer.trace(
|
171
|
+
'redis_memo.memoize_query.invalidation',
|
172
|
+
"#{__method__}##{model_class.name}",
|
173
|
+
) do
|
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
|
162
184
|
end
|
163
|
-
|
164
|
-
|
185
|
+
|
186
|
+
record_count = RedisMemo.without_memo { or_chain.count }
|
187
|
+
if record_count > bulk_operations_invalidation_limit
|
188
|
+
nil
|
165
189
|
else
|
166
|
-
|
190
|
+
RedisMemo.without_memo { or_chain.to_a }
|
167
191
|
end
|
168
192
|
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.select_by_id(model_class, ids)
|
196
|
+
RedisMemo::Tracer.trace(
|
197
|
+
'redis_memo.memoize_query.invalidation',
|
198
|
+
"#{__method__}##{model_class.name}",
|
199
|
+
) do
|
200
|
+
RedisMemo.without_memo do
|
201
|
+
model_class.where(model_class.primary_key => ids).to_a
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
169
205
|
|
170
|
-
|
206
|
+
def self.bulk_operations_invalidation_limit
|
207
|
+
ENV['REDIS_MEMO_BULK_OPERATIONS_INVALIDATION_LIMIT']&.to_i ||
|
208
|
+
RedisMemo::DefaultOptions.bulk_operations_invalidation_limit ||
|
209
|
+
10000
|
171
210
|
end
|
172
211
|
end
|
data/lib/redis_memo/options.rb
CHANGED
@@ -13,7 +13,7 @@ class RedisMemo::Options
|
|
13
13
|
)
|
14
14
|
@compress = compress.nil? ? true : compress
|
15
15
|
@compress_threshold = compress_threshold || 1.kilobyte
|
16
|
-
@
|
16
|
+
@redis_config = redis
|
17
17
|
@redis_client = nil
|
18
18
|
@redis_error_handler = redis_error_handler
|
19
19
|
@tracer = tracer
|
@@ -22,20 +22,18 @@ class RedisMemo::Options
|
|
22
22
|
@expires_in = expires_in
|
23
23
|
end
|
24
24
|
|
25
|
-
def redis
|
26
|
-
|
27
|
-
|
25
|
+
def redis
|
26
|
+
@redis_client ||= RedisMemo::Redis.new(redis_config)
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@redis = blk
|
38
|
-
end
|
29
|
+
def redis_config
|
30
|
+
@redis_config || {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def redis=(config)
|
34
|
+
@redis_config = config
|
35
|
+
@redis_client = nil
|
36
|
+
redis
|
39
37
|
end
|
40
38
|
|
41
39
|
def tracer(&blk)
|
@@ -74,15 +72,16 @@ class RedisMemo::Options
|
|
74
72
|
end
|
75
73
|
|
76
74
|
attr_accessor :async
|
75
|
+
attr_accessor :bulk_operations_invalidation_limit
|
76
|
+
attr_accessor :cache_out_of_date_handler
|
77
|
+
attr_accessor :cache_validation_sampler
|
77
78
|
attr_accessor :compress
|
78
79
|
attr_accessor :compress_threshold
|
79
|
-
attr_accessor :
|
80
|
+
attr_accessor :connection_pool
|
80
81
|
attr_accessor :expires_in
|
81
|
-
attr_accessor :
|
82
|
-
attr_accessor :cache_out_of_date_handler
|
82
|
+
attr_accessor :redis_error_handler
|
83
83
|
|
84
84
|
attr_writer :global_cache_key_version
|
85
|
-
attr_writer :redis
|
86
85
|
attr_writer :tracer
|
87
86
|
attr_writer :logger
|
88
87
|
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.0.0.beta.
|
4
|
+
version: 0.0.0.beta.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chan Zuckerberg Initiative
|
@@ -14,42 +14,56 @@ dependencies:
|
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: redis
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 4.0.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 4.0.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: connection_pool
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.2.3
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: activerecord
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '5.2'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '5.2'
|
55
69
|
- !ruby/object:Gem::Dependency
|
@@ -161,6 +175,7 @@ files:
|
|
161
175
|
- lib/redis_memo/after_commit.rb
|
162
176
|
- lib/redis_memo/batch.rb
|
163
177
|
- lib/redis_memo/cache.rb
|
178
|
+
- lib/redis_memo/connection_pool.rb
|
164
179
|
- lib/redis_memo/future.rb
|
165
180
|
- lib/redis_memo/memoizable.rb
|
166
181
|
- lib/redis_memo/memoizable/dependency.rb
|