any_cache 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnyCache::Adapters
4
+ # @api private
5
+ # @since 0.3.0
6
+ class ActiveSupportDalliStore < Basic
7
+ class << self
8
+ # @param driver [Object]
9
+ # @retunr [Boolean]
10
+ #
11
+ # @api private
12
+ # @since 0.3.0
13
+ def supported_driver?(driver)
14
+ AnyCache::Drivers::ActiveSupportDalliStore.supported_source?(driver)
15
+ end
16
+ end
17
+
18
+ # @return [Array]
19
+ #
20
+ # @api private
21
+ # @since 0.3.0
22
+ READ_MULTI_EMPTY_KEYS_SET = [].freeze
23
+
24
+ # @return [Integer]
25
+ #
26
+ # @api private
27
+ # @since 0.3.0
28
+ DEFAULT_INCR_DECR_AMOUNT = 1
29
+
30
+ # @return [Integer]
31
+ #
32
+ # @api private
33
+ # @since 0.3.0
34
+ INITIAL_DECREMNETED_VALUE = 0
35
+
36
+ # @return [NilClass]
37
+ #
38
+ # @api private
39
+ # @since 0.3.0
40
+ NO_EXPIRATION_TTL = nil
41
+
42
+ # @return [Integer]
43
+ #
44
+ # @api private
45
+ # @since 0.3.0
46
+ DEAD_TTL = 0
47
+
48
+ # @since 0.3.0
49
+ def_delegators :driver, :delete, :clear
50
+
51
+ # @param key [String]
52
+ # @param options [Hash]
53
+ # @return [void]
54
+ #
55
+ # @api private
56
+ # @since 0.3.0
57
+ def read(key, **options)
58
+ raw = options.fetch(:raw, true)
59
+
60
+ driver.read(key, raw: raw)
61
+ end
62
+
63
+ # @param keys [Array<String>]
64
+ # @param options [Hash]
65
+ # @return [Hash]
66
+ #
67
+ # @api private
68
+ # @since 0.3.0
69
+ def read_multi(*keys, **options)
70
+ raw = options.fetch(:raw, true)
71
+
72
+ driver.read_multi(*keys, raw: raw).tap do |entries|
73
+ entries.merge!(Hash[(keys - entries.keys).zip(READ_MULTI_EMPTY_KEYS_SET)])
74
+ end
75
+ end
76
+
77
+ # @param key [String]
78
+ # @param value [Object]
79
+ # @option expires_in [NilClass, Integer] Time in seconds
80
+ # @return [void]
81
+ #
82
+ # @api private
83
+ # @since 0.3.0
84
+ def write(key, value, **options)
85
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
86
+ raw = options.fetch(:raw, true)
87
+
88
+ driver.write(key, value, expires_in: expires_in, raw: raw)
89
+ end
90
+
91
+ # @param entries [Hash]
92
+ # @param options [Hash]
93
+ # @return [void]
94
+ #
95
+ # @api private
96
+ # @since 0.3.0
97
+ def write_multi(entries, **options)
98
+ raw = options.fetch(:raw, true)
99
+
100
+ # NOTE: ActiveSupport::Cache::DalliStore does not support #write_multi :\
101
+ entries.each_pair do |key, value|
102
+ write(key, value, expires_in: NO_EXPIRATION_TTL, raw: raw)
103
+ end
104
+ end
105
+
106
+ # @param key [String]
107
+ # @option expires_in [Integer]
108
+ # @option force [Boolean, Proc]
109
+ # @return [Object]
110
+ #
111
+ # @api private
112
+ # @since 0.3.0
113
+ def fetch(key, **options, &fallback)
114
+ force_rewrite = options.fetch(:force, false)
115
+ force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
116
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
117
+
118
+ driver.fetch(key, force: force_rewrite, expires_in: expires_in, &fallback)
119
+ end
120
+
121
+ # @param keys [Array<String>]
122
+ # @param options [Hash]
123
+ # @param fallback [Proc]
124
+ # @return [Hash]
125
+ #
126
+ # @api private
127
+ # @since 0.3.0
128
+ def fetch_multi(*keys, **options, &fallback)
129
+ keys.each_with_object({}) do |key, dataset|
130
+ dataset[key] = fetch(key, **options, &fallback)
131
+ end
132
+ end
133
+
134
+ # @param key [String]
135
+ # @param amount [Integer]
136
+ # @options expires_in [Integer]
137
+ # @return [Integer, Float]
138
+ #
139
+ # @api private
140
+ # @since 0.3.0
141
+ def increment(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
142
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
143
+
144
+ unless exist?(key)
145
+ write(key, amount, expires_in: expires_in) && amount
146
+ else
147
+ driver.increment(key, amount).tap do
148
+ expire(key, expires_in: expires_in) if expires_in
149
+ end
150
+ end
151
+ end
152
+
153
+ # @param key [String]
154
+ # @param amount [Integer]
155
+ # @option expires_in [Integer]
156
+ # @return [Integer, Float]
157
+ #
158
+ # @api private
159
+ # @since 0.3.0
160
+ def decrement(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
161
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
162
+
163
+ unless exist?(key)
164
+ # NOTE: Dalli::Client (under the hood of this) can't decrement:
165
+ # - non-raw values;
166
+ # - values lower than zero;
167
+ # - empty entries;
168
+ write(key, INITIAL_DECREMNETED_VALUE, expires_in: expires_in) && INITIAL_DECREMNETED_VALUE
169
+ else
170
+ driver.decrement(key, amount).tap do
171
+ expire(key, expires_in: expires_in) if expires_in
172
+ end
173
+ end
174
+ end
175
+
176
+ # @param pattern [String, Regexp]
177
+ # @param options [Hash]
178
+ # @return [void]
179
+ #
180
+ # @api private
181
+ # @since 0.3.0
182
+ def delete_matched(pattern, **options)
183
+ # TODO: make it real >:]
184
+ end
185
+
186
+ # @param key [String]
187
+ # @option expires_in [Integer]
188
+ # @return [void]
189
+ #
190
+ # @api private
191
+ # @since 0.3.0
192
+ def expire(key, expires_in: DEAD_TTL)
193
+ read(key).tap do |value|
194
+ is_alive = expires_in ? expires_in.positive? : false
195
+ is_alive ? write(key, value, expires_in: expires_in) : delete(key)
196
+ end
197
+ end
198
+
199
+ # @param key [String]
200
+ # @param options [Hash]
201
+ # @return [void]
202
+ #
203
+ # @api private
204
+ # @since 0.3.0
205
+ def persist(key, **options)
206
+ read(key).tap { |value| write(key, value) }
207
+ end
208
+
209
+ # @param key [String]
210
+ # @param options [Hash]
211
+ # @return [BOolean]
212
+ #
213
+ # @api private
214
+ # @since 0.3.0
215
+ def exist?(key, **options)
216
+ driver.exist?(key, options)
217
+ end
218
+ end
219
+ end
@@ -17,6 +17,12 @@ module AnyCache::Adapters
17
17
  end
18
18
  end
19
19
 
20
+ # @return [Array]
21
+ #
22
+ # @api private
23
+ # @since 0.3.0
24
+ READ_MULTI_EMPTY_KEYS_SET = [].freeze
25
+
20
26
  # @return [NilClass]
21
27
  #
22
28
  # @api private
@@ -44,7 +50,7 @@ module AnyCache::Adapters
44
50
  # @since 0.2.0
45
51
  def_delegators :driver, :delete, :clear
46
52
 
47
- # @param key
53
+ # @param key [String]
48
54
  # @param options [Hash]
49
55
  # @return [Object]
50
56
  #
@@ -56,6 +62,20 @@ module AnyCache::Adapters
56
62
  driver.read(key, raw: raw)
57
63
  end
58
64
 
65
+ # @param keys [Array<String>]
66
+ # @param options [Hash]
67
+ # @return [Hash]
68
+ #
69
+ # @api private
70
+ # @since 0.3.0
71
+ def read_multi(*keys, **options)
72
+ raw = options.fetch(:raw, true)
73
+
74
+ driver.read_multi(*keys, raw: raw).tap do |entries|
75
+ entries.merge!(Hash[(keys - entries.keys).zip(READ_MULTI_EMPTY_KEYS_SET)])
76
+ end
77
+ end
78
+
59
79
  # @param key [String]
60
80
  # @param value [Object]
61
81
  # @option expires_in [NilClass, Integer] Time in seconds
@@ -70,6 +90,56 @@ module AnyCache::Adapters
70
90
  driver.write(key, value, expires_in: expires_in, raw: raw)
71
91
  end
72
92
 
93
+ # @param entries [Hash]
94
+ # @param options [Hash]
95
+ # @return [void]
96
+ #
97
+ # @api private
98
+ # @since 0.3.0
99
+ def write_multi(entries, **options)
100
+ raw = options.fetch(:raw, true)
101
+
102
+ driver.write_multi(entries, expires_in: NO_EXPIRATION_TTL, raw: raw)
103
+ end
104
+
105
+ # @param key [String]
106
+ # @option expires_in [Integer]
107
+ # @option force [Boolean, Proc]
108
+ # @return [Object]
109
+ #
110
+ # @api private
111
+ # @since 0.2.0
112
+ def fetch(key, **options, &fallback)
113
+ force_rewrite = options.fetch(:force, false)
114
+ force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
115
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
116
+
117
+ driver.fetch(key, force: force_rewrite, expires_in: expires_in, &fallback)
118
+ end
119
+
120
+ # @param keys [Array<String>]
121
+ # @param options [Hash]
122
+ # @param fallback [Proc]
123
+ # @return [Hash]
124
+ #
125
+ # @api private
126
+ # @since 0.3.0
127
+ def fetch_multi(*keys, **options, &fallback)
128
+ keys.each_with_object({}) do |key, dataset|
129
+ dataset[key] = fetch(key, **options, &fallback)
130
+ end
131
+ end
132
+
133
+ # @param pattern [String, Regexp]
134
+ # @param options [Hash]
135
+ # @return [void]
136
+ #
137
+ # @api private
138
+ # @since 0.3.0
139
+ def delete_matched(pattern, **options)
140
+ # TODO: make it real >:]
141
+ end
142
+
73
143
  # @param key [String]
74
144
  # @param amount [Integer]
75
145
  # @options expires_in [Integer]
@@ -144,20 +214,5 @@ module AnyCache::Adapters
144
214
  def exist?(key, **options)
145
215
  driver.exist?(key)
146
216
  end
147
-
148
- # @param key [String]
149
- # @option expires_in [Integer]
150
- # @option force [Boolean]
151
- # @return [Object]
152
- #
153
- # @api private
154
- # @since 0.2.0
155
- def fetch(key, **options, &block)
156
- force_rewrite = options.fetch(:force, false)
157
- force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
158
- expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
159
-
160
- driver.fetch(key, force: force_rewrite, expires_in: expires_in, &block)
161
- end
162
217
  end
163
218
  end
@@ -7,6 +7,12 @@ class AnyCache::Adapters::ActiveSupportNaiveStore
7
7
  # @since 0.1.0
8
8
  extend Forwardable
9
9
 
10
+ # @return [Array]
11
+ #
12
+ # @api private
13
+ # @since 0.3.0
14
+ READ_MULTI_EMPTY_KEYS_SET = [].freeze
15
+
10
16
  # @return [NilClass]
11
17
  #
12
18
  # @api private
@@ -34,6 +34,20 @@ module AnyCache::Adapters
34
34
  lock.with_read_lock { super }
35
35
  end
36
36
 
37
+ # @param keys [Array<String>]
38
+ # @param options [Hash]
39
+ # @return [Hash]
40
+ #
41
+ # @api private
42
+ # @since 0.3.0
43
+ def read_multi(*keys, **options)
44
+ lock.with_read_lock do
45
+ super.tap do |res|
46
+ res.merge!(Hash[(keys - res.keys).zip(Operation::READ_MULTI_EMPTY_KEYS_SET)])
47
+ end
48
+ end
49
+ end
50
+
37
51
  # @param key [String]
38
52
  # @param options [Hash]
39
53
  # @return [void]
@@ -44,6 +58,16 @@ module AnyCache::Adapters
44
58
  lock.with_write_lock { super }
45
59
  end
46
60
 
61
+ # @param pattern [String, Regexp]
62
+ # @param options [Hash]
63
+ # @return [void]
64
+ #
65
+ # @api private
66
+ # @since 0.3.0
67
+ def delete_matched(pattern, **options)
68
+ lock.with_write_lock { super }
69
+ end
70
+
47
71
  # @param options [Hash]
48
72
  # @return [void]
49
73
  #
@@ -68,6 +92,61 @@ module AnyCache::Adapters
68
92
  end
69
93
  end
70
94
 
95
+ # @param entries [Hash]
96
+ # @param options [Hash]
97
+ # @return [void]
98
+ #
99
+ # @api private
100
+ # @since 0.3.0
101
+ def write_multi(entries, **options)
102
+ lock.with_write_lock do
103
+ expires_in = self.class::Operation::NO_EXPIRATION_TTL
104
+
105
+ super(entries, expires_in: expires_in)
106
+ end
107
+ end
108
+
109
+ # @param key [String]
110
+ # @param fallback [Proc]
111
+ # @option expires_in [Integer]
112
+ # @option force [Boolean, Proc]
113
+ # @return [Object]
114
+ #
115
+ # @api private
116
+ # @since 0.2.0
117
+ def fetch(key, **options, &fallback)
118
+ lock.with_write_lock do
119
+ force_rewrite = options.fetch(:force, false)
120
+ force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
121
+ expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
122
+
123
+ super(key, force: force_rewrite, expires_in: expires_in, &fallback)
124
+ end
125
+ end
126
+
127
+ # @param keys [Array<String>]
128
+ # @param fallback [Proc]
129
+ # @option force [Boolean, Proc]
130
+ # @option expires_in [Integer]
131
+ # @return [Hash]
132
+ #
133
+ # @api private
134
+ # @since 0.3.0
135
+ def fetch_multi(*keys, **options, &fallback)
136
+ lock.with_write_lock do
137
+ force_rewrite = options.fetch(:force, false)
138
+ expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
139
+
140
+ # NOTE:
141
+ # use own #fetch_multi implementation cuz original #fetch_multi
142
+ # does not support :force option
143
+ keys.each_with_object({}) do |key, dataset|
144
+ force = force_rewrite.respond_to?(:call) ? force_rewrite.call(key) : force_rewrite
145
+ dataset[key] = driver.fetch(key, force: force, expires_in: expires_in, &fallback)
146
+ end
147
+ end
148
+ end
149
+
71
150
  # @param key [String]
72
151
  # @param amount [Integer, Float]
73
152
  # @option expires_in [NilClass, Integer]
@@ -128,23 +207,6 @@ module AnyCache::Adapters
128
207
  lock.with_read_lock { super }
129
208
  end
130
209
 
131
- # @param key [String]
132
- # @option expires_in [Integer]
133
- # @option force [Boolean]
134
- # @return [Object]
135
- #
136
- # @api private
137
- # @since 0.2.0
138
- def fetch(key, **options, &block)
139
- lock.with_write_lock do
140
- force_rewrite = options.fetch(:force, false)
141
- force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
142
- expires_in = options.fetch(:expires_in, self.class::Operation::NO_EXPIRATION_TTL)
143
-
144
- super(key, force: force_rewrite, expires_in: expires_in, &block)
145
- end
146
- end
147
-
148
210
  private
149
211
 
150
212
  # @return [Concurrent::ReentrantReadWriteLock]
@@ -17,8 +17,14 @@ module AnyCache::Adapters
17
17
  end
18
18
  end
19
19
 
20
+ # @return [Array]
21
+ #
22
+ # @api private
23
+ # @since 0.3.0
24
+ READ_MULTI_EMPTY_KEYS_SET = [].freeze
25
+
20
26
  # @since 0.1.0
21
- def_delegators :driver, :delete, :clear
27
+ def_delegators :driver, :delete, :delete_matched, :clear
22
28
 
23
29
  # @return [NilClass]
24
30
  #
@@ -38,7 +44,7 @@ module AnyCache::Adapters
38
44
  # @since 0.1.0
39
45
  DEFAULT_INCR_DECR_AMOUNT = 1
40
46
 
41
- # @param key
47
+ # @param key [String]
42
48
  # @param options [Hash]
43
49
  # @return [Object]
44
50
  #
@@ -50,6 +56,20 @@ module AnyCache::Adapters
50
56
  driver.read(key, raw: raw)
51
57
  end
52
58
 
59
+ # @param keys [Array<String>]
60
+ # @param options [Hash]
61
+ # @return [Hash]
62
+ #
63
+ # @api private
64
+ # @since 0.3.0
65
+ def read_multi(*keys, **options)
66
+ raw = options.fetch(:raw, true)
67
+
68
+ driver.read_multi(*keys, raw: raw).tap do |res|
69
+ res.merge!(Hash[(keys - res.keys).zip(READ_MULTI_EMPTY_KEYS_SET)])
70
+ end
71
+ end
72
+
53
73
  # @param key [String]
54
74
  # @param value [Object]
55
75
  # @option expires_in [NilClass, Integer] Time in seconds
@@ -64,6 +84,52 @@ module AnyCache::Adapters
64
84
  driver.write(key, value, expires_in: expires_in, raw: raw)
65
85
  end
66
86
 
87
+ # @param entries [Hash]
88
+ # @param options [Hash]
89
+ # @return [void]
90
+ #
91
+ # @api private
92
+ # @sicne 0.3.0
93
+ def write_multi(entries, **options)
94
+ raw = options.fetch(:raw, true)
95
+
96
+ driver.write_multi(entries, expires_in: NO_EXPIRATION_TTL, raw: raw)
97
+ end
98
+
99
+ # @param key [String]
100
+ # @param fallback [Proc]
101
+ # @option expires_in [Integer]
102
+ # @option force [Boolean, Proc]
103
+ # @return [Object]
104
+ #
105
+ # @api private
106
+ # @since 0.2.0
107
+ def fetch(key, **options, &fallback)
108
+ force_rewrite = options.fetch(:force, false)
109
+ force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
110
+ expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
111
+ raw = options.fetch(:raw, true)
112
+
113
+ driver.fetch(key, force: force_rewrite, expires_in: expires_in, raw: raw, &fallback)
114
+ end
115
+
116
+ # @param keys [Array<string]
117
+ # @param fallback [Proc]
118
+ # @poption expires_in [Integer]
119
+ # @option force [Boolean, Proc]
120
+ # @return [Hash]
121
+ #
122
+ # @api private
123
+ # @since 0.3.0
124
+ def fetch_multi(*keys, **options, &fallback)
125
+ # NOTE:
126
+ # use own :fetch_multi implementation cuz original :fetch_multi
127
+ # doesnt support :force option
128
+ keys.each_with_object({}) do |key, dataset|
129
+ dataset[key] = fetch(key, **options, &fallback)
130
+ end
131
+ end
132
+
67
133
  # @param key [String]
68
134
  # @param amount [Integer, Float]
69
135
  # @option expires_in [Integer]
@@ -134,20 +200,5 @@ module AnyCache::Adapters
134
200
  def exist?(key, **options)
135
201
  driver.exist?(key)
136
202
  end
137
-
138
- # @param key [String]
139
- # @option expires_in [Integer]
140
- # @option force [Boolean]
141
- # @return [Object]
142
- #
143
- # @api private
144
- # @since 0.2.0
145
- def fetch(key, **options, &block)
146
- force_rewrite = options.fetch(:force, false)
147
- force_rewrite = force_rewrite.call if force_rewrite.respond_to?(:call)
148
- expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
149
-
150
- driver.fetch(key, force: force_rewrite, expires_in: expires_in, &block)
151
- end
152
203
  end
153
204
  end
@@ -43,6 +43,16 @@ module AnyCache::Adapters
43
43
  raise NotImplementedError
44
44
  end
45
45
 
46
+ # @param keys [Array<String>]
47
+ # @param options [Hash]
48
+ # @return [Hash]
49
+ #
50
+ # @api private
51
+ # @since 0.3.0
52
+ def read_multi(*keys, **options)
53
+ raise NotImplementedError
54
+ end
55
+
46
56
  # @param key [String]
47
57
  # @param value [Object]
48
58
  # @param options [Hash]
@@ -54,6 +64,38 @@ module AnyCache::Adapters
54
64
  raise NotImplementedError
55
65
  end
56
66
 
67
+ # @param entries [Hash]
68
+ # @param options [Hash]
69
+ # @return [void]
70
+ #
71
+ # @api private
72
+ # @since 0.3.0
73
+ def write_multi(entries, **options)
74
+ raise NotImplementedError
75
+ end
76
+
77
+ # @param key [String]
78
+ # @param options [Hash]
79
+ # @param fallback [Proc]
80
+ # @return [Object]
81
+ #
82
+ # @api private
83
+ # @since 0.2.0
84
+ def fetch(key, **options, &fallback)
85
+ raise NotImplementedError
86
+ end
87
+
88
+ # @param keys [Array<String>]
89
+ # @param options [Hash]
90
+ # @param fallback [Proc]
91
+ # @return [Hash]
92
+ #
93
+ # @api private
94
+ # @since 0.3.0
95
+ def fetch_multi(*keys, **options, &fallback)
96
+ raise NotImplementedError
97
+ end
98
+
57
99
  # @param key [String]
58
100
  # @param options [Hash]
59
101
  # @return [void]
@@ -64,6 +106,16 @@ module AnyCache::Adapters
64
106
  raise NotImplementedError
65
107
  end
66
108
 
109
+ # @param pattern [Regexp, String, Object]
110
+ # @param options [Hash]
111
+ # @return [void]
112
+ #
113
+ # @api private
114
+ # @since 0.3.0
115
+ def delete_matched(pattern, **options)
116
+ raise NotImplementedError
117
+ end
118
+
67
119
  # @param key [String]
68
120
  # @param value [Integer, Float]
69
121
  # @param options [Hash]
@@ -124,15 +176,5 @@ module AnyCache::Adapters
124
176
  def exist?(key, **options)
125
177
  raise NotImplementedError
126
178
  end
127
-
128
- # @param key [String]
129
- # @param options [Hash]
130
- # @return [Object]
131
- #
132
- # @api private
133
- # @since 0.2.0
134
- def fetch(key, **options, &block)
135
- raise NotImplementedError
136
- end
137
179
  end
138
180
  end