object-cache 0.0.2 → 0.0.3

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: b3be3bd853f9ffd24ff89cff95d2762241021a1f
4
- data.tar.gz: 48fc790b6f2a15b13d945a9fe6f0483355bc9995
3
+ metadata.gz: 1d2f1ec4b3467a87297e809f094d3f75461b3fa9
4
+ data.tar.gz: bf7eef92986a7ddb52c5f7ec2aa3110ddbaa791d
5
5
  SHA512:
6
- metadata.gz: 6e1cd521b1b326ab8a381b71a0c39677fc37885dd0f714c8e8db010d7cc22dd5e88067827be3c4a863bda017f847ff63f77ab5814be6de0e20d527f986b4cf2e
7
- data.tar.gz: 12f817db636a6d87ed92dbc80885d999f0b19b11b507aab5283fcf1ee7d9941495e430b0ff47571ab2601c559a5017703dde3de97f7d8666f04b6bf97dd4f4ae
6
+ metadata.gz: 323e1806f012635837d50ac2111d607232714308376d16e9ab32718cc2217fe760d745298b3e20165b1d3e70f339b90acca9aada9ec81cf44f5b75e971403006
7
+ data.tar.gz: 7b0cd11b83029e6e2b9701804a7426679e6002578777192916301c75af7faaf9780a61acd5ef8a32a8df52de45e977a5d86be1954f1a56dfdbd876bb7ea15dc7
data/.rubocop.yml CHANGED
@@ -6,8 +6,5 @@ AllCops:
6
6
  Metrics/MethodLength:
7
7
  Max: 15
8
8
 
9
- Metrics/AbcSize:
10
- Max: 16
11
-
12
9
  Metrics/LineLength:
13
10
  Max: 100
data/README.md CHANGED
@@ -8,6 +8,7 @@ Easy caching of Ruby objects, using [Redis](http://redis.io) as a backend store.
8
8
  * [marshaling data](#marshaling-data)
9
9
  * [ttl](#ttl)
10
10
  * [namespaced keys](#namespaced-keys)
11
+ * [key prefixes](#key-prefixes)
11
12
  * [redis replicas](#redis-replicas)
12
13
  * [core extension](#core-extension)
13
14
  * [License](#license)
@@ -128,6 +129,58 @@ merged together with the file name and line number of the cache request, so you
128
129
  can re-use that same `email` namespace in different locations, without worrying
129
130
  about any naming collisions.
130
131
 
132
+ #### key prefixes
133
+
134
+ By default, the eventual key ending up in Redis is a 6-character long digest,
135
+ based on the file name, line number, and optional key passed into the Cache
136
+ object:
137
+
138
+ ```ruby
139
+ Cache.new { 'hello world' }
140
+ Cache.backend.keys # => ["22abcc"]
141
+ ```
142
+
143
+ This makes working with keys quick and easy, without worying about conflicting
144
+ keys.
145
+
146
+ However, this does make it more difficult to selectively delete keys from the
147
+ backend, if you want to purge the cache of specific keys, before their TTL
148
+ expires.
149
+
150
+ To support this use-case, you can use the `key_prefix` attribute:
151
+
152
+ ```ruby
153
+ Cache.new(key_prefix: 'hello') { 'hello world' }
154
+ Cache.backend.keys # => ["hello_22abcc"]
155
+ ```
156
+
157
+ This allows you to selectively purge keys from Redis:
158
+
159
+ ```ruby
160
+ Cache.backend.del('hello_')
161
+ ```
162
+
163
+ You can also use the special value `:method_name` to dynamically set the key
164
+ prefix based on where the cached object was created:
165
+
166
+ ```ruby
167
+ Cache.new(key_prefix: :method_name) { 'hello world' }
168
+ Cache.backend.keys # => ["test_key_prefix_method_name_22abcc"]
169
+ ```
170
+
171
+ Or, use `:class_name` to group keys in the same class together:
172
+
173
+ ```ruby
174
+ Cache.new(key_prefix: :class_name) { 'hello world' }
175
+ Cache.backend.keys # => ["CacheTest_22abcc"]
176
+ ```
177
+
178
+ You can also define these options globally:
179
+
180
+ ```ruby
181
+ Cache.default_key_prefix = :method_name
182
+ ```
183
+
131
184
  #### redis replicas
132
185
 
133
186
  Before, we used the following setup to connect `Object::Cache` to a redis
@@ -137,7 +190,7 @@ backend:
137
190
  Cache.backend = Redis.new
138
191
  ```
139
192
 
140
- The Ruby Redis library has primary/replicas support [buit-in using Redis
193
+ The Ruby Redis library has primary/replicas support [built-in using Redis
141
194
  Sentinel][sentinel].
142
195
 
143
196
  If however, you have your own setup, and want the writes and reads to be
@@ -151,7 +204,7 @@ Cache.backend = { primary: Redis.new, replicas: [Redis.new, Redis.new] }
151
204
  When writing the initial object to the backend, the `primary` Redis is used. On
152
205
  subsequent requests, a random replica is used to retrieve the stored value.
153
206
 
154
- The above example obiously only works if the replicas receive the written data
207
+ The above example obviously only works if the replicas receive the written data
155
208
  from the primary instance.
156
209
 
157
210
  #### core extension
@@ -167,8 +220,8 @@ cache('hello', ttl: 60) { 'hello world' }
167
220
  Cache.new('hello', ttl: 60) { 'hello world' }
168
221
  ```
169
222
 
170
- Since the core extension adds the `cache` method to the `Object` class, you can
171
- also call this method directly on any instances inheriting from `Object`:
223
+ You can also call this method directly on any instances inheriting from
224
+ `Object`:
172
225
 
173
226
  ```ruby
174
227
  require 'object/cache/core_extension'
data/lib/object/cache.rb CHANGED
@@ -10,6 +10,7 @@ class Cache
10
10
  class << self
11
11
  attr_accessor :backend
12
12
  attr_accessor :default_ttl
13
+ attr_accessor :default_key_prefix
13
14
 
14
15
  # new
15
16
  #
@@ -43,10 +44,10 @@ class Cache
43
44
  # Cache.new { item } # item is only stored once, and then always
44
45
  # # retrieved, even if it is a different item
45
46
  #
46
- def new(key = nil, ttl: default_ttl)
47
+ def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix)
47
48
  return yield unless replica
48
49
 
49
- key = Digest::SHA1.hexdigest([key, Proc.new.source_location].flatten.join)[0..5]
50
+ key = build_key(key, key_prefix, Proc.new)
50
51
 
51
52
  if (cached_value = replica.get(key)).nil?
52
53
  yield.tap { |value| update_cache(key, value, ttl: ttl) }
@@ -94,5 +95,24 @@ class Cache
94
95
  def replica
95
96
  replicas.sample
96
97
  end
98
+
99
+ def build_key(key, key_prefix, proc)
100
+ hash = Digest::SHA1.hexdigest([key, proc.source_location].flatten.join)[0..5]
101
+ prefix = build_key_prefix(key_prefix, proc)
102
+
103
+ [prefix, hash].compact.join('_')
104
+ end
105
+
106
+ def build_key_prefix(key_prefix, proc)
107
+ case key_prefix
108
+ when :method_name
109
+ location = caller_locations.find { |l| "#{l.path}#{l.lineno}" == proc.source_location.join }
110
+ location&.base_label
111
+ when :class_name
112
+ proc.binding.receiver.class.to_s
113
+ else
114
+ key_prefix
115
+ end
116
+ end
97
117
  end
98
118
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Cache
4
- VERSION = '0.0.2'
4
+ VERSION = '0.0.3'
5
5
  end
data/test/cache_test.rb CHANGED
@@ -147,4 +147,40 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
147
147
  assert_equal 1, primary.keys.count
148
148
  assert_equal 0, replica.keys.count
149
149
  end
150
+
151
+ def test_default_key_prefix_custom
152
+ Cache.default_key_prefix = 'hello'
153
+
154
+ Cache.new { 'hello world' }
155
+ assert_match(/^hello/, redis.keys.first)
156
+ end
157
+
158
+ def test_default_key_prefix_method_name
159
+ Cache.default_key_prefix = :method_name
160
+
161
+ Cache.new { 'hello world' }
162
+ assert_match(/^test_default_key_prefix_method_name/, redis.keys.first)
163
+ end
164
+
165
+ def test_default_key_prefix_class_name
166
+ Cache.default_key_prefix = :class_name
167
+
168
+ Cache.new { 'hello world' }
169
+ assert_match(/^CacheTest/, redis.keys.first)
170
+ end
171
+
172
+ def test_key_prefix_custom
173
+ Cache.new(key_prefix: 'hello') { 'hello world' }
174
+ assert_match(/^hello/, redis.keys.first)
175
+ end
176
+
177
+ def test_key_prefix_method_name
178
+ Cache.new(key_prefix: :method_name) { 'hello world' }
179
+ assert_match(/^test_key_prefix_method_name/, redis.keys.first)
180
+ end
181
+
182
+ def test_key_prefix_class_name
183
+ Cache.new(key_prefix: :class_name) { 'hello world' }
184
+ assert_match(/^CacheTest/, redis.keys.first)
185
+ end
150
186
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: object-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean