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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c799eb1c4173b8f329ca600d6ae11d41e818106
4
- data.tar.gz: 4ae4f9898571512b39967e59d15e4ff57cfbb7f0
3
+ metadata.gz: 5871260d413d0b379be074fd68456dbf560e65b5
4
+ data.tar.gz: fe55cfc25c52328783ee5544fefa543b93532b14
5
5
  SHA512:
6
- metadata.gz: c1cb3f17d2241fa807bae7fe7c5f4c3f579e4ab6ad56172ea2aaa2b4c99a5844a4546ed00a35e4342368edce62a55b3edb302ef21d7873c01d2995a5295f4831
7
- data.tar.gz: 812862d064c613e2b0360352cf33801e6a5654566e2afd1952d2145fd7117a0abfc1d2fa36718ec46d2b04ee4e4eab69ed4cfeb4634e928b2c5612f24b8258b9
6
+ metadata.gz: 00633e6912fc6549966c6f5f039140139d0416603ba29de9d62a492543e6e9073193a0bbbd87a0070258e1d0c8d86dd4e897ad14c72f23d0e0bb12db7bbcf0e3
7
+ data.tar.gz: a20524d2819fc873444925ce2e17da77ac9ebc9407d6f36e0e3668469bc44bd4a930dc3c0590c16c93d0edd7da82f86648eacd22e77e02f12f656482e1ccf5da
data/Gemfile CHANGED
@@ -11,4 +11,8 @@ group :development, :test do
11
11
  gem 'pry-rescue'
12
12
  end
13
13
 
14
+ group :test do
15
+ gem 'fakeredis', require: "fakeredis/rspec"
16
+ end
17
+
14
18
  gem 'codeclimate-test-reporter', :group => :test, :require => nil
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
- ## v 0.2.0
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
- :options,
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
- digest hash[:digest]
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
- def default_options
21
- @default_options ||= {}
22
- end
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
- def register_options(name, options)
30
- raise ArgumentError if name.blank?
31
- options_map[name.to_sym] = Hash(options)
32
- self
33
- end
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 missing_options(return_if_missing)
56
- case return_if_missing
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 get_options(name)
67
- default_options.merge registered_options(name)
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
@@ -1,3 +1,3 @@
1
1
  module ArtirixCacheService
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  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.2.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: []