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 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: []