any_cache 0.2.0 → 0.3.0

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.
@@ -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