artirix_cache_service 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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/README.md +97 -1
- data/artirix_cache_service.gemspec +1 -0
- data/lib/artirix_cache_service.rb +11 -2
- data/lib/artirix_cache_service/key.rb +15 -3
- data/lib/artirix_cache_service/options_service.rb +59 -0
- data/lib/artirix_cache_service/service.rb +13 -47
- data/lib/artirix_cache_service/variables_store_service.rb +53 -0
- data/lib/artirix_cache_service/variables_stores/base.rb +22 -0
- data/lib/artirix_cache_service/variables_stores/internal.rb +23 -0
- data/lib/artirix_cache_service/variables_stores/redis.rb +35 -0
- data/lib/artirix_cache_service/version.rb +1 -1
- metadata +20 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5871260d413d0b379be074fd68456dbf560e65b5
|
|
4
|
+
data.tar.gz: fe55cfc25c52328783ee5544fefa543b93532b14
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00633e6912fc6549966c6f5f039140139d0416603ba29de9d62a492543e6e9073193a0bbbd87a0070258e1d0c8d86dd4e897ad14c72f23d0e0bb12db7bbcf0e3
|
|
7
|
+
data.tar.gz: a20524d2819fc873444925ce2e17da77ac9ebc9407d6f36e0e3668469bc44bd4a930dc3c0590c16c93d0edd7da82f86648eacd22e77e02f12f656482e1ccf5da
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -136,6 +136,98 @@ ArtirixCacheService.options :missing, :another_missing, return_if_missing: :empt
|
|
|
136
136
|
# => {}
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
## Variables
|
|
140
|
+
|
|
141
|
+
as part of the cache_key, we can specify the name of a variable that the Service
|
|
142
|
+
can retrieve to use in the digest.
|
|
143
|
+
|
|
144
|
+
Using this, we can effectively change cache_keys arguments without changing code,
|
|
145
|
+
effectively invalidating cache without coupling.
|
|
146
|
+
|
|
147
|
+
If the variable does not have a value, it will get nil, which is valid for the
|
|
148
|
+
digest.
|
|
149
|
+
|
|
150
|
+
Note: we retrieve the variables as strings always, and return nil if `blank?`.
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
|
|
154
|
+
# some_view.html.erb
|
|
155
|
+
<%= cache ArtirixCacheService.key(:my_key, variables: :classification) %>
|
|
156
|
+
...
|
|
157
|
+
<% end %>
|
|
158
|
+
|
|
159
|
+
# first request, variable :my_var does not have a value (nil), so
|
|
160
|
+
# the cache_key is "prfx/my_key/333a21750df06ef3c82aece819ded0f6f691638a"
|
|
161
|
+
|
|
162
|
+
# Digest::SHA1.hexdigest( { my_var: nil }.to_s )
|
|
163
|
+
# # => "333a21750df06ef3c82aece819ded0f6f691638a"
|
|
164
|
+
|
|
165
|
+
# model_a.rb
|
|
166
|
+
uuid = SecureRandom.uuid # => "6d6eb11e-0241-4f97-b706-91982eb8e69b"
|
|
167
|
+
ArtirixCacheService.variable_set :my_var, uuid
|
|
168
|
+
|
|
169
|
+
# now the next request on the view, the cache key is different:
|
|
170
|
+
# cache key is "prfx/my_key/a8484d25b7c57b1f93a05ad82422d7b45c4ad83e"
|
|
171
|
+
|
|
172
|
+
# Digest::SHA1.hexdigest( { my_var: uuid }.to_s )
|
|
173
|
+
# # => "a8484d25b7c57b1f93a05ad82422d7b45c4ad83e"
|
|
174
|
+
|
|
175
|
+
# =>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This way we can invalidate based on a variable value, without directly
|
|
179
|
+
invalidating cache, for the use cases when we cannot rely on the argument's `cache_key`.
|
|
180
|
+
|
|
181
|
+
We use `variable_set` to set new values, and `variable_get` to retrieve them.
|
|
182
|
+
|
|
183
|
+
We can also pass an optional block to `variable_get` to set the value if it's nil.
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
|
|
187
|
+
ArtirixCacheService.variable_get :my_var # => nil
|
|
188
|
+
ArtirixCacheService.variable_get(:my_var) { 990 } # => "990"
|
|
189
|
+
ArtirixCacheService.variable_get :my_var # => "990"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Variable Store
|
|
193
|
+
|
|
194
|
+
by default (dev mode) the values are stored in an internal hash.
|
|
195
|
+
|
|
196
|
+
#### Redis
|
|
197
|
+
|
|
198
|
+
it can connect to Redis, using the given options, and store the variables with
|
|
199
|
+
a given prefix.
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
redis_options = {
|
|
203
|
+
namespace: 'xyz',
|
|
204
|
+
host: 'localhost',
|
|
205
|
+
port: 6379,
|
|
206
|
+
db: 0,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
ArtirixCacheService.redis_options = redis_options
|
|
210
|
+
ArtirixCacheService.register_variables_store :redis, force: true
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
A prefix on the variable name will be used. By default it's `artirix_cache_service`.
|
|
214
|
+
It gets prepended to the given variable name, and separated by `_`.
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
# default prefix
|
|
218
|
+
ArtirixCacheService.redis_variable_prefix # => "artirix_cache_service"
|
|
219
|
+
|
|
220
|
+
# setting a new prefix (don't forget to reload the store)
|
|
221
|
+
ArtirixCacheService.redis_variable_prefix = 'my_app_prefix'
|
|
222
|
+
ArtirixCacheService.register_variables_store :redis, force: true
|
|
223
|
+
|
|
224
|
+
# checking variables
|
|
225
|
+
ArtirixCacheService.variable_set 'myvar', 'paco'
|
|
226
|
+
|
|
227
|
+
redis_client = Redis.new redis_options
|
|
228
|
+
redis_client.get 'my_app_prefix_myvar' # => 'paco'
|
|
229
|
+
```
|
|
230
|
+
|
|
139
231
|
## Installation
|
|
140
232
|
|
|
141
233
|
Add this line to your application's Gemfile:
|
|
@@ -165,7 +257,11 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/artiri
|
|
|
165
257
|
|
|
166
258
|
# Changeset
|
|
167
259
|
|
|
168
|
-
##
|
|
260
|
+
## v0.3.0
|
|
261
|
+
|
|
262
|
+
- add Redis support
|
|
263
|
+
|
|
264
|
+
## v0.2.0
|
|
169
265
|
|
|
170
266
|
- removed `ArtirixCacheService.config_params` support, now using `register_key_prefix` method
|
|
171
267
|
- add `options` support
|
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.require_paths = ['lib']
|
|
28
28
|
|
|
29
29
|
spec.add_dependency 'activesupport', '~> 4'
|
|
30
|
+
spec.add_dependency 'redis'
|
|
30
31
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
|
31
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|
|
32
33
|
spec.add_development_dependency 'rspec'
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
require 'active_support/all'
|
|
2
|
+
require 'redis'
|
|
2
3
|
require 'artirix_cache_service/version'
|
|
3
4
|
require 'artirix_cache_service/key'
|
|
5
|
+
require 'artirix_cache_service/options_service'
|
|
6
|
+
require 'artirix_cache_service/variables_store_service'
|
|
7
|
+
require 'artirix_cache_service/variables_stores/base'
|
|
8
|
+
require 'artirix_cache_service/variables_stores/internal'
|
|
9
|
+
require 'artirix_cache_service/variables_stores/redis'
|
|
4
10
|
require 'artirix_cache_service/service'
|
|
5
11
|
|
|
6
12
|
module ArtirixCacheService
|
|
@@ -11,8 +17,11 @@ module ArtirixCacheService
|
|
|
11
17
|
:register_key_prefix, :key_prefix,
|
|
12
18
|
:default_options, :register_default_options,
|
|
13
19
|
:register_options, :registered_options,
|
|
14
|
-
:registered_options?, :registered_options,
|
|
15
|
-
:
|
|
20
|
+
:registered_options?, :registered_options, :options,
|
|
21
|
+
:variables_store, :register_variables_store, :reload_variables_store,
|
|
22
|
+
:redis_options, :redis_options=,
|
|
23
|
+
:redis_variable_prefix, :redis_variable_prefix=,
|
|
24
|
+
:variable_set, :variable_get,
|
|
16
25
|
to: :service
|
|
17
26
|
end
|
|
18
27
|
|
|
@@ -9,7 +9,7 @@ module ArtirixCacheService
|
|
|
9
9
|
@args = clean_key_args given_args
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
delegate :key_prefix, :digest, to: :service
|
|
12
|
+
delegate :key_prefix, :digest, :variable_get, to: :service
|
|
13
13
|
|
|
14
14
|
def call
|
|
15
15
|
clean_parts.join KEY_SEPARATOR
|
|
@@ -39,9 +39,21 @@ module ArtirixCacheService
|
|
|
39
39
|
|
|
40
40
|
def cache_key_from_options(hash)
|
|
41
41
|
return nil unless hash.kind_of? Hash
|
|
42
|
-
return nil unless hash[:digest]
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
d = hash[:digest].presence
|
|
44
|
+
v = variables_hash(Array(hash[:variables])).presence
|
|
45
|
+
|
|
46
|
+
return nil unless d || v
|
|
47
|
+
|
|
48
|
+
if d && v
|
|
49
|
+
digest [d, v]
|
|
50
|
+
else
|
|
51
|
+
digest d || v
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def variables_hash(variable_names)
|
|
56
|
+
Hash[variable_names.map { |var| [var, variable_get(var)] }]
|
|
45
57
|
end
|
|
46
58
|
|
|
47
59
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module ArtirixCacheService
|
|
2
|
+
class OptionsService
|
|
3
|
+
|
|
4
|
+
def default_options
|
|
5
|
+
@default_options ||= {}
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def register_default_options(default_options)
|
|
9
|
+
@default_options = Hash(default_options)
|
|
10
|
+
self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def register_options(name, options)
|
|
14
|
+
raise ArgumentError if name.blank?
|
|
15
|
+
options_map[name.to_sym] = Hash(options)
|
|
16
|
+
self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def registered_options(name)
|
|
20
|
+
return nil unless name.present?
|
|
21
|
+
options_map[name.to_sym]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def registered_options?(name)
|
|
25
|
+
!registered_options(name).nil?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def options(*names, return_if_missing: :empty)
|
|
29
|
+
name = names.detect { |name| registered_options? name }
|
|
30
|
+
if name.present?
|
|
31
|
+
get_options(name)
|
|
32
|
+
else
|
|
33
|
+
missing_options(return_if_missing)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def missing_options(return_if_missing)
|
|
40
|
+
case return_if_missing
|
|
41
|
+
when :default
|
|
42
|
+
default_options.dup
|
|
43
|
+
when :nil, nil
|
|
44
|
+
nil
|
|
45
|
+
else
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_options(name)
|
|
51
|
+
default_options.merge registered_options(name)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def options_map
|
|
55
|
+
@options_map ||= {}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -17,59 +17,25 @@ module ArtirixCacheService
|
|
|
17
17
|
Digest::SHA1.hexdigest arg.to_s
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def register_default_options(default_options)
|
|
25
|
-
@default_options = Hash(default_options)
|
|
26
|
-
self
|
|
27
|
-
end
|
|
20
|
+
delegate :default_options, :register_default_options,
|
|
21
|
+
:register_options, :registered_options,
|
|
22
|
+
:registered_options?, :options,
|
|
23
|
+
to: :options_service
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def registered_options(name)
|
|
36
|
-
return nil unless name.present?
|
|
37
|
-
options_map[name.to_sym]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def registered_options?(name)
|
|
41
|
-
!registered_options(name).nil?
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def options(*names, return_if_missing: :empty)
|
|
45
|
-
name = names.detect { |name| registered_options? name }
|
|
46
|
-
if name.present?
|
|
47
|
-
get_options(name)
|
|
48
|
-
else
|
|
49
|
-
missing_options(return_if_missing)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
25
|
+
delegate :register_variables_store, :variables_store, :reload_variables_store,
|
|
26
|
+
:redis_options, :redis_options=,
|
|
27
|
+
:redis_variable_prefix, :redis_variable_prefix=,
|
|
28
|
+
:variable_get, :variable_set,
|
|
29
|
+
to: :variables_store_service
|
|
52
30
|
|
|
53
31
|
private
|
|
54
32
|
|
|
55
|
-
def
|
|
56
|
-
|
|
57
|
-
when :default
|
|
58
|
-
default_options.dup
|
|
59
|
-
when :nil, nil
|
|
60
|
-
nil
|
|
61
|
-
else
|
|
62
|
-
{}
|
|
63
|
-
end
|
|
33
|
+
def options_service
|
|
34
|
+
@options_service ||= OptionsService.new
|
|
64
35
|
end
|
|
65
36
|
|
|
66
|
-
def
|
|
67
|
-
|
|
37
|
+
def variables_store_service
|
|
38
|
+
@variables_store_service ||= VariablesStoreService.new
|
|
68
39
|
end
|
|
69
|
-
|
|
70
|
-
def options_map
|
|
71
|
-
@options_map ||= {}
|
|
72
|
-
end
|
|
73
|
-
|
|
74
40
|
end
|
|
75
41
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module ArtirixCacheService
|
|
2
|
+
class VariablesStoreService
|
|
3
|
+
DEFAULT_PREFIX = 'artirix_cache_service'.freeze
|
|
4
|
+
|
|
5
|
+
attr_writer :redis_options
|
|
6
|
+
attr_writer :redis_variable_prefix
|
|
7
|
+
|
|
8
|
+
def redis_options
|
|
9
|
+
@redis_options ||= {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def redis_variable_prefix
|
|
13
|
+
@redis_variable_prefix ||= DEFAULT_PREFIX
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def register_variables_store(type, force: false)
|
|
17
|
+
@variables_store = build_by_type type, force
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def reload_variables_store
|
|
21
|
+
register_variables_store type, force: true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def variables_store
|
|
25
|
+
@variables_store ||= build_internal
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
delegate :variable_get, :variable_set, :type, to: :variables_store
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def build_by_type(type, force = false)
|
|
33
|
+
case type
|
|
34
|
+
when :internal
|
|
35
|
+
build_internal force
|
|
36
|
+
when :redis
|
|
37
|
+
build_redis force
|
|
38
|
+
else
|
|
39
|
+
raise ArgumentError, 'type not recognized'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def build_internal(force = false)
|
|
44
|
+
return @variables_store if !force && @variables_store.kind_of?(VariablesStores::Internal)
|
|
45
|
+
VariablesStores::Internal.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def build_redis(force = false)
|
|
49
|
+
return @variables_store if !force && @variables_store.kind_of?(VariablesStores::Redis)
|
|
50
|
+
VariablesStores::Redis.new redis_variable_prefix, redis_options
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module ArtirixCacheService
|
|
2
|
+
module VariablesStores
|
|
3
|
+
class Base
|
|
4
|
+
|
|
5
|
+
def variable_get(given_key, &block)
|
|
6
|
+
key = given_key.to_sym
|
|
7
|
+
val = retrieve(key).presence
|
|
8
|
+
return val.to_s if val
|
|
9
|
+
return nil unless block_given?
|
|
10
|
+
|
|
11
|
+
val = block.call
|
|
12
|
+
store key, val
|
|
13
|
+
val.presence && val.to_s
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def variable_set(key, value)
|
|
17
|
+
store key.to_sym, value
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ArtirixCacheService
|
|
2
|
+
module VariablesStores
|
|
3
|
+
class Internal < Base
|
|
4
|
+
def type
|
|
5
|
+
:internal
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def retrieve(key)
|
|
11
|
+
map[key]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def store(key, value)
|
|
15
|
+
map[key] = value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def map
|
|
19
|
+
@map ||= {}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ArtirixCacheService
|
|
2
|
+
module VariablesStores
|
|
3
|
+
class Redis < Base
|
|
4
|
+
|
|
5
|
+
attr_reader :redis_variable_prefix
|
|
6
|
+
|
|
7
|
+
def type
|
|
8
|
+
:redis
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(redis_variable_prefix, redis_options = {})
|
|
12
|
+
@redis_variable_prefix = redis_variable_prefix
|
|
13
|
+
@redis_options = redis_options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def retrieve(key)
|
|
19
|
+
redis.get(complete_key(key))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def store(key, value)
|
|
23
|
+
redis.set(complete_key(key), value)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def complete_key(key)
|
|
27
|
+
"#{redis_variable_prefix}_#{key}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def redis
|
|
31
|
+
@redis ||= ::Redis.new @redis_options
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: artirix_cache_service
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eduardo Turiño
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '4'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: redis
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: bundler
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -98,7 +112,12 @@ files:
|
|
|
98
112
|
- bin/setup
|
|
99
113
|
- lib/artirix_cache_service.rb
|
|
100
114
|
- lib/artirix_cache_service/key.rb
|
|
115
|
+
- lib/artirix_cache_service/options_service.rb
|
|
101
116
|
- lib/artirix_cache_service/service.rb
|
|
117
|
+
- lib/artirix_cache_service/variables_store_service.rb
|
|
118
|
+
- lib/artirix_cache_service/variables_stores/base.rb
|
|
119
|
+
- lib/artirix_cache_service/variables_stores/internal.rb
|
|
120
|
+
- lib/artirix_cache_service/variables_stores/redis.rb
|
|
102
121
|
- lib/artirix_cache_service/version.rb
|
|
103
122
|
homepage: https://github.com/artirix/artirix_cache_service
|
|
104
123
|
licenses: []
|