object-cache 0.0.3 → 0.1.2
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 +5 -5
- data/.rubocop.yml +12 -2
- data/Gemfile +1 -0
- data/README.md +4 -12
- data/Rakefile +3 -2
- data/lib/object/cache.rb +29 -20
- data/lib/object/cache/core_extension.rb +2 -3
- data/lib/object/cache/version.rb +1 -1
- data/object-cache.gemspec +10 -10
- data/test/cache_test.rb +55 -18
- metadata +24 -26
- data/.wercker.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5702bb0b9df058e9fd36b86a712f11b716dc0d8e8ff3d05378a1b204f18bb6dc
|
4
|
+
data.tar.gz: a669e8209d07ce571313e6b63c7643e064e1e0b78ea39e8397b53a583016f49e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a59277f8c32bba979c8d5184c512b41b4faa816f1a9c1ed07af1ca826d69131f92980057e8ad9bd3975cb53bc5953867e4a3577eb84a7b12c592612c3483a9f0
|
7
|
+
data.tar.gz: 79b741e82962f83510437e93aa4d683bb59571452070f30fc55333c418395916d45b3363a70c775075908e4b26b9ae032222f0970382a5cf8d8813954742aac6
|
data/.rubocop.yml
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.4
|
3
3
|
Exclude:
|
4
4
|
- '.wercker/**/*'
|
5
5
|
|
6
6
|
Metrics/MethodLength:
|
7
|
-
Max:
|
7
|
+
Max: 20
|
8
8
|
|
9
9
|
Metrics/LineLength:
|
10
10
|
Max: 100
|
11
|
+
|
12
|
+
Style/RescueStandardError:
|
13
|
+
Exclude:
|
14
|
+
- 'lib/object/cache.rb'
|
15
|
+
- 'test/cache_test.rb'
|
16
|
+
|
17
|
+
Security/MarshalLoad:
|
18
|
+
Exclude:
|
19
|
+
- 'lib/object/cache.rb'
|
20
|
+
- 'test/cache_test.rb'
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -157,7 +157,8 @@ Cache.backend.keys # => ["hello_22abcc"]
|
|
157
157
|
This allows you to selectively purge keys from Redis:
|
158
158
|
|
159
159
|
```ruby
|
160
|
-
Cache.backend.
|
160
|
+
keys = Cache.backend.keys('hello_*')
|
161
|
+
Cache.backend.del(keys)
|
161
162
|
```
|
162
163
|
|
163
164
|
You can also use the special value `:method_name` to dynamically set the key
|
@@ -209,8 +210,8 @@ from the primary instance.
|
|
209
210
|
|
210
211
|
#### core extension
|
211
212
|
|
212
|
-
Finally, if you want, you can
|
213
|
-
|
213
|
+
Finally, if you want, you can use the `cache` method, for convenient
|
214
|
+
access to the cache object:
|
214
215
|
|
215
216
|
```ruby
|
216
217
|
require 'object/cache/core_extension'
|
@@ -220,15 +221,6 @@ cache('hello', ttl: 60) { 'hello world' }
|
|
220
221
|
Cache.new('hello', ttl: 60) { 'hello world' }
|
221
222
|
```
|
222
223
|
|
223
|
-
You can also call this method directly on any instances inheriting from
|
224
|
-
`Object`:
|
225
|
-
|
226
|
-
```ruby
|
227
|
-
require 'object/cache/core_extension'
|
228
|
-
|
229
|
-
'hello world'.cache(ttl: 60)
|
230
|
-
```
|
231
|
-
|
232
224
|
That's it!
|
233
225
|
|
234
226
|
## License
|
data/Rakefile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'bundler/gem_tasks'
|
3
4
|
require 'rake/testtask'
|
4
5
|
require 'rubocop/rake_task'
|
5
6
|
|
6
7
|
RuboCop::RakeTask.new do |t|
|
7
|
-
t.options = %w
|
8
|
+
t.options = %w[--display-cop-names --extra-details --display-style-guide]
|
8
9
|
end
|
9
10
|
|
10
11
|
Rake::TestTask.new(:test) do |t|
|
@@ -13,4 +14,4 @@ Rake::TestTask.new(:test) do |t|
|
|
13
14
|
t.test_files = FileList['test/**/*_test.rb']
|
14
15
|
end
|
15
16
|
|
16
|
-
task default: %i
|
17
|
+
task default: %i[test rubocop]
|
data/lib/object/cache.rb
CHANGED
@@ -44,29 +44,37 @@ class Cache
|
|
44
44
|
# Cache.new { item } # item is only stored once, and then always
|
45
45
|
# # retrieved, even if it is a different item
|
46
46
|
#
|
47
|
-
def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix)
|
47
|
+
def new(key = nil, ttl: default_ttl, key_prefix: default_key_prefix, &block)
|
48
48
|
return yield unless replica
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
begin
|
51
|
+
key = build_key(key, key_prefix, block)
|
52
|
+
|
53
|
+
if (cached_value = replica.get(key)).nil?
|
54
|
+
yield.tap do |value|
|
55
|
+
begin
|
56
|
+
update_cache(key, value, ttl: ttl)
|
57
|
+
rescue TypeError
|
58
|
+
# if `TypeError` is raised, the data could not be Marshal dumped. In that
|
59
|
+
# case, delete anything left in the cache store, and get the data without
|
60
|
+
# caching.
|
61
|
+
#
|
62
|
+
delete(key)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
else
|
66
|
+
begin
|
67
|
+
Marshal.load(cached_value)
|
68
|
+
rescue
|
69
|
+
delete(key)
|
70
|
+
yield
|
71
|
+
end
|
72
|
+
end
|
56
73
|
end
|
57
|
-
rescue TypeError
|
58
|
-
# if `TypeError` is raised, the data could not be Marshal dumped. In that
|
59
|
-
# case, delete anything left in the cache store, and get the data without
|
60
|
-
# caching.
|
61
|
-
#
|
62
|
-
delete(key)
|
63
|
-
yield
|
64
|
-
rescue
|
65
|
-
yield
|
66
74
|
end
|
67
75
|
|
68
76
|
def include?(key)
|
69
|
-
replica.exists(key)
|
77
|
+
replica.exists?(key)
|
70
78
|
rescue
|
71
79
|
false
|
72
80
|
end
|
@@ -89,7 +97,8 @@ class Cache
|
|
89
97
|
end
|
90
98
|
|
91
99
|
def replicas
|
92
|
-
|
100
|
+
replicas = backend.is_a?(Hash) ? backend[:replicas] : backend
|
101
|
+
replicas.respond_to?(:sample) ? replicas : [replicas]
|
93
102
|
end
|
94
103
|
|
95
104
|
def replica
|
@@ -97,7 +106,7 @@ class Cache
|
|
97
106
|
end
|
98
107
|
|
99
108
|
def build_key(key, key_prefix, proc)
|
100
|
-
hash = Digest::SHA1.hexdigest([key, proc.source_location].flatten.join)[0..
|
109
|
+
hash = Digest::SHA1.hexdigest([key, proc.source_location].flatten.join)[0..11]
|
101
110
|
prefix = build_key_prefix(key_prefix, proc)
|
102
111
|
|
103
112
|
[prefix, hash].compact.join('_')
|
@@ -106,7 +115,7 @@ class Cache
|
|
106
115
|
def build_key_prefix(key_prefix, proc)
|
107
116
|
case key_prefix
|
108
117
|
when :method_name
|
109
|
-
location = caller_locations.find { |l| "#{l.path}#{l.lineno}"
|
118
|
+
location = caller_locations.find { |l| proc.source_location.join == "#{l.path}#{l.lineno}" }
|
110
119
|
location&.base_label
|
111
120
|
when :class_name
|
112
121
|
proc.binding.receiver.class.to_s
|
data/lib/object/cache/version.rb
CHANGED
data/object-cache.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
lib = File.expand_path('
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'object/cache'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'object-cache'
|
9
9
|
spec.version = Cache::VERSION
|
10
|
-
spec.authors = %w
|
11
|
-
spec.email = %w
|
10
|
+
spec.authors = %w[Jean Mertz]
|
11
|
+
spec.email = %w[jean@mertz.fm]
|
12
12
|
|
13
13
|
spec.summary = 'Caching of objects, using a Redis store.'
|
14
14
|
spec.description = 'Easily cache objects in Ruby, using a Redis store backend'
|
15
15
|
spec.homepage = 'https://github.com/blendle/object-cache'
|
16
16
|
spec.license = 'MIT'
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
|
-
spec.require_paths = %w
|
18
|
+
spec.require_paths = %w[lib]
|
19
19
|
|
20
|
-
spec.add_development_dependency 'bundler', '~> 1
|
20
|
+
spec.add_development_dependency 'bundler', '~> 2.1'
|
21
21
|
spec.add_development_dependency 'm', '~> 1.5'
|
22
|
-
spec.add_development_dependency 'minitest'
|
22
|
+
spec.add_development_dependency 'minitest'
|
23
23
|
spec.add_development_dependency 'mock_redis', '~> 0.16'
|
24
|
-
spec.add_development_dependency 'pry'
|
25
|
-
spec.add_development_dependency 'rake'
|
26
|
-
spec.add_development_dependency 'rubocop'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rubocop'
|
27
27
|
end
|
data/test/cache_test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
3
4
|
|
4
5
|
require 'mock_redis'
|
5
6
|
require 'object/cache'
|
@@ -21,7 +22,7 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def test_cache_returns_object
|
24
|
-
assert_equal
|
25
|
+
assert_equal('hello world', Cache.new { 'hello world' })
|
25
26
|
end
|
26
27
|
|
27
28
|
def test_cache_stores_object
|
@@ -94,28 +95,15 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
94
95
|
|
95
96
|
def test_core_extension
|
96
97
|
load 'object/cache/core_extension.rb'
|
97
|
-
assert_equal
|
98
|
-
assert
|
98
|
+
assert_equal('hello world', cache { 'hello world' })
|
99
|
+
assert Kernel.send(:remove_method, :cache)
|
99
100
|
end
|
100
101
|
|
101
102
|
def test_core_extension_options
|
102
103
|
load 'object/cache/core_extension.rb'
|
103
104
|
cache(ttl: 60) { 'hello world' }
|
104
105
|
assert_equal 60, redis.ttl(redis.keys.first)
|
105
|
-
assert
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_core_extension_on_objects
|
109
|
-
load 'object/cache/core_extension.rb'
|
110
|
-
assert_equal 'hello world', 'hello world'.cache
|
111
|
-
assert Object.send(:remove_method, :cache)
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_core_extension_on_objects_with_arguments
|
115
|
-
load 'object/cache/core_extension.rb'
|
116
|
-
'hello world'.cache(ttl: 30)
|
117
|
-
assert_equal 30, redis.ttl(redis.keys.first)
|
118
|
-
assert Object.send(:remove_method, :cache)
|
106
|
+
assert Kernel.send(:remove_method, :cache)
|
119
107
|
end
|
120
108
|
|
121
109
|
def test_backend_with_replicas
|
@@ -183,4 +171,53 @@ class CacheTest < Minitest::Test # rubocop:disable Metrics/ClassLength
|
|
183
171
|
Cache.new(key_prefix: :class_name) { 'hello world' }
|
184
172
|
assert_match(/^CacheTest/, redis.keys.first)
|
185
173
|
end
|
174
|
+
|
175
|
+
def test_unset_backend
|
176
|
+
Cache.backend = nil
|
177
|
+
val = 0
|
178
|
+
block = -> { val += 1 }
|
179
|
+
Cache.new(&block)
|
180
|
+
Cache.backend = MockRedis.new
|
181
|
+
|
182
|
+
assert_equal 1, val
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_unset_backend_raising_type_error
|
186
|
+
Cache.backend = nil
|
187
|
+
val = 0
|
188
|
+
begin
|
189
|
+
Cache.new do
|
190
|
+
val += 1
|
191
|
+
raise TypeError
|
192
|
+
end
|
193
|
+
rescue
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
|
197
|
+
Cache.backend = MockRedis.new
|
198
|
+
assert_equal 1, val
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_single_yield_on_failure
|
202
|
+
val = 0
|
203
|
+
begin
|
204
|
+
Cache.new do
|
205
|
+
val += 1
|
206
|
+
raise TypeError
|
207
|
+
end
|
208
|
+
rescue
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
|
212
|
+
assert_equal 1, val
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_yield_when_marshal_load_fails
|
216
|
+
testing = -> { Cache.new(key_prefix: 'marshal') { 'hello world' } }
|
217
|
+
|
218
|
+
assert_equal 'hello world', testing.call
|
219
|
+
redis.set(redis.keys('marshal*').first, 'garbage')
|
220
|
+
assert_equal 'hello world', testing.call
|
221
|
+
assert_empty redis.keys('marshal*')
|
222
|
+
end
|
186
223
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean
|
8
8
|
- Mertz
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-09-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '1
|
20
|
+
version: '2.1'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '1
|
27
|
+
version: '2.1'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: m
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,16 +43,16 @@ dependencies:
|
|
43
43
|
name: minitest
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: mock_redis
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,44 +71,44 @@ dependencies:
|
|
71
71
|
name: pry
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - "
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '0
|
76
|
+
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- - "
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '0
|
83
|
+
version: '0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: rake
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- - "
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '
|
90
|
+
version: '0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- - "
|
95
|
+
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '
|
97
|
+
version: '0'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: rubocop
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- - "
|
102
|
+
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: '0
|
104
|
+
version: '0'
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- - "
|
109
|
+
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: '0
|
111
|
+
version: '0'
|
112
112
|
description: Easily cache objects in Ruby, using a Redis store backend
|
113
113
|
email:
|
114
114
|
- jean@mertz.fm
|
@@ -118,7 +118,6 @@ extra_rdoc_files: []
|
|
118
118
|
files:
|
119
119
|
- ".gitignore"
|
120
120
|
- ".rubocop.yml"
|
121
|
-
- ".wercker.yml"
|
122
121
|
- CODE_OF_CONDUCT.md
|
123
122
|
- Gemfile
|
124
123
|
- LICENSE.txt
|
@@ -133,7 +132,7 @@ homepage: https://github.com/blendle/object-cache
|
|
133
132
|
licenses:
|
134
133
|
- MIT
|
135
134
|
metadata: {}
|
136
|
-
post_install_message:
|
135
|
+
post_install_message:
|
137
136
|
rdoc_options: []
|
138
137
|
require_paths:
|
139
138
|
- lib
|
@@ -148,9 +147,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
147
|
- !ruby/object:Gem::Version
|
149
148
|
version: '0'
|
150
149
|
requirements: []
|
151
|
-
|
152
|
-
|
153
|
-
signing_key:
|
150
|
+
rubygems_version: 3.1.2
|
151
|
+
signing_key:
|
154
152
|
specification_version: 4
|
155
153
|
summary: Caching of objects, using a Redis store.
|
156
154
|
test_files: []
|