cache_json 1.2.1 → 1.2.6
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 +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +38 -0
- data/lib/cache_json/adapters/redis.rb +4 -0
- data/lib/cache_json/base.rb +10 -1
- data/lib/cache_json/version.rb +1 -1
- data/lib/cache_json/worker.rb +56 -43
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44125f970020a38afcbd640051d4f9b6d5565530b753d1e63079401d1ef607b2
|
4
|
+
data.tar.gz: 8a6d4e5469e88e118ff40cc346b80d422002a2e36cde0318538b452a530ffa1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b76526fafe43e2f8e51b785c18672fbf7f60c1ddd86ec98185499284bf40441c3dff96e3b55a771eb275ab33656548f6d012dd135c69b408057d5366cedd60af
|
7
|
+
data.tar.gz: 7ab99f8451f502bae4c9f4805507f0bbdedec4c57b29117c869f079647482342b1b54c9d1bd96495928175122918623fc22a18691b34e0961f28c0fbfe05f70f
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cache_json (1.2.
|
4
|
+
cache_json (1.2.6)
|
5
5
|
redis (>= 3.3.5, < 5)
|
6
6
|
|
7
7
|
GEM
|
@@ -15,7 +15,7 @@ GEM
|
|
15
15
|
parallel (1.19.1)
|
16
16
|
parser (2.7.0.3)
|
17
17
|
ast (~> 2.4.0)
|
18
|
-
rack (2.2.
|
18
|
+
rack (2.2.3)
|
19
19
|
rack-protection (2.0.8.1)
|
20
20
|
rack
|
21
21
|
rainbow (3.0.0)
|
@@ -66,4 +66,4 @@ DEPENDENCIES
|
|
66
66
|
timecop (~> 0.9.1)
|
67
67
|
|
68
68
|
BUNDLED WITH
|
69
|
-
2.
|
69
|
+
2.2.3
|
data/README.md
CHANGED
@@ -54,6 +54,44 @@ CacheJSON.configure do |config|
|
|
54
54
|
end
|
55
55
|
```
|
56
56
|
|
57
|
+
## Automatic refreshing (Sidekiq)
|
58
|
+
|
59
|
+
There is a simple Sidekiq job that lets you pre-compute selected classes with specified ranges of arguments. All you have to do is add a `refresh` option:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class ExpensiveJob
|
63
|
+
|
64
|
+
include CacheJSON::Base
|
65
|
+
|
66
|
+
|
67
|
+
cache_json_options(
|
68
|
+
time_to_expire: 1.hour,
|
69
|
+
refresh: {
|
70
|
+
buffer: 5.minutes,
|
71
|
+
arguments: {
|
72
|
+
first: (5..10),
|
73
|
+
second: ['one option', 'another option'],
|
74
|
+
third: 'the only option',
|
75
|
+
fourth: -> { ['proc result'] }
|
76
|
+
}
|
77
|
+
}
|
78
|
+
)
|
79
|
+
...
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
The Sidekiq job will take the Cartesian product of all the argument ranges/arrays (all the combinations).
|
84
|
+
|
85
|
+
We leave it to you to schedule the job. If you're using https://github.com/moove-it/sidekiq-scheduler, you can do something like this:
|
86
|
+
|
87
|
+
```yml
|
88
|
+
cache_json_worker:
|
89
|
+
every: "20s"
|
90
|
+
class: CacheJSON::Worker
|
91
|
+
```
|
92
|
+
|
93
|
+
Whenever the worker runs, it checks which results have expired, and refreshes only those. If you pass in the `buffer` option, it will actually refresh keys that are that far away from expiring. In the example above, the worker will refresh the cache 5 minutes before it expires. This is good if you want to avoid cache misses altogether.
|
94
|
+
|
57
95
|
## Development
|
58
96
|
|
59
97
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/cache_json/base.rb
CHANGED
@@ -8,7 +8,7 @@ module CacheJSON
|
|
8
8
|
base.extend(ClassMethods)
|
9
9
|
end
|
10
10
|
|
11
|
-
def results(args)
|
11
|
+
def results(args = {})
|
12
12
|
raise ArgumentError, 'Must use keyword arguments' unless args.is_a?(Hash)
|
13
13
|
|
14
14
|
options = self.class.cache_json_full_options
|
@@ -17,6 +17,11 @@ module CacheJSON
|
|
17
17
|
JSON.parse(refresh_cache!(args: args, cache: cache).to_json) # stringify keys
|
18
18
|
end
|
19
19
|
|
20
|
+
def cache_expiring_soon?(args:, cache: nil)
|
21
|
+
cache ||= Cache.new(args: args, options: self.class.cache_json_full_options)
|
22
|
+
cache.cache_expiring_soon?
|
23
|
+
end
|
24
|
+
|
20
25
|
def clear_cache!
|
21
26
|
Cache.new(options: self.class.cache_json_full_options).clear_cache!
|
22
27
|
end
|
@@ -54,6 +59,10 @@ module CacheJSON
|
|
54
59
|
adapter.clear_cache!
|
55
60
|
end
|
56
61
|
|
62
|
+
def cache_expiring_soon?
|
63
|
+
adapter.cache_expiring_soon?
|
64
|
+
end
|
65
|
+
|
57
66
|
def adapter
|
58
67
|
@adapter ||= CacheJSON::Adapters::Redis.new(args: args, options: options)
|
59
68
|
end
|
data/lib/cache_json/version.rb
CHANGED
data/lib/cache_json/worker.rb
CHANGED
@@ -5,7 +5,6 @@ begin
|
|
5
5
|
rescue LoadError
|
6
6
|
nil
|
7
7
|
end
|
8
|
-
|
9
8
|
module CacheJSON
|
10
9
|
class Worker
|
11
10
|
if defined?(Sidekiq)
|
@@ -18,66 +17,80 @@ module CacheJSON
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
def perform(
|
20
|
+
def perform(params="{}")
|
21
|
+
parsed_params = JSON.parse(params)
|
22
|
+
klass = parsed_params["klass"]
|
23
|
+
args = (parsed_params["args"] || {}).transform_keys(&:to_sym)
|
22
24
|
if klass
|
23
|
-
klass.
|
25
|
+
klass = Object.const_get(klass)
|
26
|
+
klass.new.refresh_cache!(args: args) if should_refresh?(klass, args)
|
24
27
|
else
|
25
|
-
|
28
|
+
AllPermutations.new.results.each do |perm|
|
29
|
+
if should_refresh?(perm[:klass], perm[:args])
|
30
|
+
perm[:klass] = perm[:klass].to_s
|
31
|
+
CacheJSON::Worker.perform_async(perm.to_json)
|
32
|
+
end
|
33
|
+
end
|
26
34
|
end
|
27
35
|
end
|
28
36
|
|
29
37
|
private
|
30
38
|
|
31
|
-
def
|
32
|
-
|
33
|
-
all_argument_permutations(klass).each do |args|
|
34
|
-
CacheJSON::Worker.new.perform(klass: klass, args: args) if should_refresh?(klass, args)
|
35
|
-
end
|
36
|
-
end
|
39
|
+
def should_refresh?(klass, args)
|
40
|
+
!klass.new.check_cache(args: args) || klass.new.cache_expiring_soon?(args: args)
|
37
41
|
end
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
class AllPermutations
|
44
|
+
def results
|
45
|
+
all_cache_classes.flat_map do |klass|
|
46
|
+
all_argument_permutations(klass).map do |args|
|
47
|
+
{
|
48
|
+
klass: klass,
|
49
|
+
args: args
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
43
53
|
end
|
44
|
-
end
|
45
54
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
[]
|
55
|
+
def all_cache_classes
|
56
|
+
# TODO: make this more efficient
|
57
|
+
ObjectSpace.each_object(Class).select do |klass|
|
58
|
+
klass.included_modules.include? CacheJSON::Base
|
59
|
+
end
|
52
60
|
end
|
53
|
-
end
|
54
61
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
values_for_key(non_fixed_points, pivot_key).flat_map do |pivot_key_value|
|
62
|
-
new_fixed_points = fixed_points.merge(Hash[pivot_key, pivot_key_value])
|
63
|
-
all_combinations_with_fixed_points(new_fixed_points, full_hash)
|
62
|
+
def all_argument_permutations(klass)
|
63
|
+
refresh_options = klass.cache_json_full_options[:refresh]
|
64
|
+
if refresh_options
|
65
|
+
all_combinations_with_fixed_points({}, refresh_options[:arguments])
|
66
|
+
else
|
67
|
+
[]
|
64
68
|
end
|
65
69
|
end
|
66
|
-
end
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
def all_combinations_with_fixed_points(fixed_points, full_hash)
|
72
|
+
non_fixed_points = full_hash.dup.delete_if { |k, _| fixed_points.key?(k) }
|
73
|
+
if non_fixed_points.empty?
|
74
|
+
[fixed_points]
|
75
|
+
else
|
76
|
+
pivot_key = non_fixed_points.keys.first
|
77
|
+
values_for_key(non_fixed_points, pivot_key).flat_map do |pivot_key_value|
|
78
|
+
new_fixed_points = fixed_points.merge(Hash[pivot_key, pivot_key_value])
|
79
|
+
all_combinations_with_fixed_points(new_fixed_points, full_hash)
|
80
|
+
end
|
81
|
+
end
|
76
82
|
end
|
77
|
-
end
|
78
83
|
|
79
|
-
|
80
|
-
|
84
|
+
def values_for_key(hsh, key)
|
85
|
+
pivot_key_values = hsh[key]
|
86
|
+
if pivot_key_values.is_a?(Proc)
|
87
|
+
pivot_key_values.call
|
88
|
+
elsif pivot_key_values.is_a?(Range) || pivot_key_values.is_a?(Array)
|
89
|
+
pivot_key_values
|
90
|
+
else
|
91
|
+
[pivot_key_values]
|
92
|
+
end
|
93
|
+
end
|
81
94
|
end
|
82
95
|
end
|
83
96
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Gut
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -166,7 +166,7 @@ licenses:
|
|
166
166
|
metadata:
|
167
167
|
homepage_uri: https://github.com/loopsupport/cache_json
|
168
168
|
source_code_uri: https://github.com/loopsupport/cache_json
|
169
|
-
post_install_message:
|
169
|
+
post_install_message:
|
170
170
|
rdoc_options: []
|
171
171
|
require_paths:
|
172
172
|
- lib
|
@@ -181,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
181
|
- !ruby/object:Gem::Version
|
182
182
|
version: '0'
|
183
183
|
requirements: []
|
184
|
-
rubygems_version: 3.
|
185
|
-
signing_key:
|
184
|
+
rubygems_version: 3.2.3
|
185
|
+
signing_key:
|
186
186
|
specification_version: 4
|
187
187
|
summary: Extremely simple Redis caching for any Ruby class
|
188
188
|
test_files: []
|