artirix_cache_service 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|