active_cached_resource 0.1.5 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/lib/active_cached_resource/caching.rb +15 -13
- data/lib/active_cached_resource/caching_strategies/active_support_cache.rb +27 -8
- data/lib/active_cached_resource/caching_strategies/base.rb +31 -8
- data/lib/active_cached_resource/caching_strategies/sql_cache.rb +4 -0
- data/lib/active_cached_resource/collection.rb +1 -1
- data/lib/active_cached_resource/constants.rb +7 -0
- data/lib/active_cached_resource/model.rb +1 -1
- data/lib/active_cached_resource/version.rb +1 -1
- data/lib/active_cached_resource.rb +1 -0
- data/lib/activeresource/lib/active_resource/collection.rb +20 -2
- metadata +7 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45d04dcc0d591d945fbee26f110200f54a889a55516b2340e16f5a53e571d07d
|
4
|
+
data.tar.gz: 9ccf72f8ff91404b52650d199c2ea0569e93b1cc62e830ec2f8551cae8537d23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a3f42bfc71f0f3abba12204f1bb27ce08389ec6a28d79ca527b95b9bc010eee02bb9f3bc238bbd9a481a3d4f3454b1f05baba48b8885474f92d0778db189975
|
7
|
+
data.tar.gz: 8cda34284a02b73a3c4c3f5a29eb00543c82636340371997af90219d556e80c62056e3d4d50bf7f795680dfd02805c637a4f89c4611a056cffac48c1754e0e81
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
-
## [0.1.
|
1
|
+
## [0.1.7] - 2024-01-23
|
2
|
+
- Improved `clear_cache` method for `active_support_cache` strategy to no longer use `delete_matched`.
|
3
|
+
- Introduced `.delete_from_cache` method to delete single cached resources.
|
4
|
+
|
5
|
+
## [0.1.6] - 2024-01-15
|
6
|
+
- Renamed `ActiveResource::Collection#refresh` to `#reload` to match Rails ORM naming convention.
|
7
|
+
- Added a `ActiveResource::Collection.none` class method similar to Rails `ActiveRecord::QueryMethods.none`
|
8
|
+
- Enhanced `ActiveResource::Collection#where` so that it returns `ActiveResource::Collection.none` if `resource_class` is missing.
|
9
|
+
- This is useful for when `where` clauses are chained on an empty `ActiveResource::Collection`
|
10
|
+
|
11
|
+
## [0.1.5] - 2024-01-09
|
2
12
|
- Added callbacks to cache:
|
3
13
|
- Create/POST, refresh cache after successful POST request
|
4
14
|
- Update/PUT, refresh cache after successful PUT request
|
5
15
|
- Destroy/DELETE, invalidate cache after successful DELETE request
|
6
16
|
- Fixed issue with generator for SQLCache strategy tables
|
17
|
+
|
7
18
|
## [0.1.4] - 2024-12-20
|
8
19
|
- CI Improvements
|
9
20
|
- Added annotations
|
@@ -2,9 +2,6 @@ require_relative "collection"
|
|
2
2
|
|
3
3
|
module ActiveCachedResource
|
4
4
|
module Caching
|
5
|
-
GLOBAL_PREFIX = "acr"
|
6
|
-
RELOAD_PARAM = :_acr_reload
|
7
|
-
|
8
5
|
extend ActiveSupport::Concern
|
9
6
|
|
10
7
|
included do
|
@@ -128,7 +125,7 @@ module ActiveCachedResource
|
|
128
125
|
# Hacky but this way ActiveCachedResource::Collection#request_resources! can access it
|
129
126
|
if should_reload && args.first == :all
|
130
127
|
options[:params] = {} if options[:params].blank?
|
131
|
-
options[:params][RELOAD_PARAM] = should_reload
|
128
|
+
options[:params][Constants::RELOAD_PARAM] = should_reload
|
132
129
|
args << options
|
133
130
|
end
|
134
131
|
|
@@ -140,13 +137,19 @@ module ActiveCachedResource
|
|
140
137
|
should_reload ? find_via_reload(*args) : find_via_cache(*args)
|
141
138
|
end
|
142
139
|
|
143
|
-
#
|
140
|
+
# Deletes a resource from the cache.
|
141
|
+
#
|
142
|
+
# @param id [Object] the identifier of the resource to be deleted from the cache.
|
143
|
+
def delete_from_cache(id)
|
144
|
+
cached_resource.cache.delete(cache_key(id))
|
145
|
+
end
|
146
|
+
|
147
|
+
# Clears the entire cache for the specified model that matches current prefix.
|
144
148
|
#
|
145
|
-
# @param pattern [String, nil] The pattern to match cache keys against.
|
146
|
-
# If nil, all cache keys with this models prefix will be cleared.
|
147
149
|
# @return [void]
|
148
|
-
def clear_cache
|
149
|
-
cached_resource.
|
150
|
+
def clear_cache
|
151
|
+
cached_resource.logger.debug("Clearing cache for #{name} cache with prefix: #{cache_key_prefix}")
|
152
|
+
cached_resource.cache.clear(cache_key_prefix)
|
150
153
|
end
|
151
154
|
|
152
155
|
private
|
@@ -216,8 +219,7 @@ module ActiveCachedResource
|
|
216
219
|
end
|
217
220
|
|
218
221
|
def name_key
|
219
|
-
#
|
220
|
-
"#{cache_key_prefix}-" + name.parameterize.tr("-", "/")
|
222
|
+
"#{cache_key_prefix}#{Constants::PREFIX_SEPARATOR}#{name.parameterize.tr("-", "/")}"
|
221
223
|
end
|
222
224
|
|
223
225
|
def cache_key_prefix
|
@@ -228,9 +230,9 @@ module ActiveCachedResource
|
|
228
230
|
if !result.is_a?(String) || result.empty?
|
229
231
|
raise ArgumentError, "cache_key_prefix must return a non-empty String"
|
230
232
|
end
|
231
|
-
"#{GLOBAL_PREFIX}/#{result}"
|
233
|
+
"#{Constants::GLOBAL_PREFIX}/#{result}"
|
232
234
|
else
|
233
|
-
"#{GLOBAL_PREFIX}/#{prefix}"
|
235
|
+
"#{Constants::GLOBAL_PREFIX}/#{prefix}"
|
234
236
|
end
|
235
237
|
end
|
236
238
|
|
@@ -15,16 +15,35 @@ module ActiveCachedResource
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def write_raw(key, compressed_value, options)
|
18
|
-
@cache_store.write(key, compressed_value, options)
|
18
|
+
successful_write = @cache_store.write(key, compressed_value, options)
|
19
|
+
update_master_key(key, options) if successful_write
|
20
|
+
|
21
|
+
successful_write
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_raw(key)
|
25
|
+
@cache_store.delete(key)
|
19
26
|
end
|
20
27
|
|
21
|
-
def clear_raw(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
def clear_raw(prefix)
|
29
|
+
existing_keys = @cache_store.read(prefix)
|
30
|
+
return if existing_keys.nil?
|
31
|
+
|
32
|
+
existing_keys.add(prefix)
|
33
|
+
@cache_store.delete_multi(existing_keys)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Updates the `master` key, which contains keys for a given prefix.
|
39
|
+
def update_master_key(key, options)
|
40
|
+
prefix, _ = split_key(key)
|
41
|
+
|
42
|
+
existing_keys = @cache_store.read(prefix) || Set.new
|
43
|
+
existing_keys.add(key)
|
44
|
+
|
45
|
+
# Maintain the list of keys for twice the expiration time
|
46
|
+
@cache_store.write(prefix, existing_keys, expires_in: options[:expires_in])
|
28
47
|
end
|
29
48
|
end
|
30
49
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "msgpack"
|
2
1
|
module ActiveCachedResource
|
3
2
|
module CachingStrategies
|
4
3
|
class Base
|
@@ -29,6 +28,14 @@ module ActiveCachedResource
|
|
29
28
|
write_raw(hash_key(key), compress(value), options)
|
30
29
|
end
|
31
30
|
|
31
|
+
# Deletes the cached value associated with the given key.
|
32
|
+
#
|
33
|
+
# @param key [Object] the key whose associated cached value is to be deleted.
|
34
|
+
# @return [void]
|
35
|
+
def delete(key)
|
36
|
+
delete_raw(hash_key(key))
|
37
|
+
end
|
38
|
+
|
32
39
|
# Clears the cache based on the given pattern.
|
33
40
|
#
|
34
41
|
# @param pattern [String] the pattern to match cache keys that need to be cleared.
|
@@ -76,6 +83,22 @@ module ActiveCachedResource
|
|
76
83
|
raise NotImplementedError, "#{self.class} must implement `clear_raw`"
|
77
84
|
end
|
78
85
|
|
86
|
+
protected
|
87
|
+
|
88
|
+
# Splits the provided key into a prefix and the remaining part
|
89
|
+
#
|
90
|
+
# @param key [String] the key to be split
|
91
|
+
#
|
92
|
+
# @example Splitting a key
|
93
|
+
# split_key("prefix-key") #=> "acr/prefix/keyvalue"
|
94
|
+
#
|
95
|
+
# @return [Array<String>] an array containing two elements: the part before the first "-", and the rest of the string
|
96
|
+
def split_key(key)
|
97
|
+
# Prefix of keys are expected to be the first part of key separated by a dash.
|
98
|
+
prefix, k = key.split(ActiveCachedResource::Constants::PREFIX_SEPARATOR, 2)
|
99
|
+
[prefix, k]
|
100
|
+
end
|
101
|
+
|
79
102
|
private
|
80
103
|
|
81
104
|
# Generates a hashed key for caching purposes.
|
@@ -88,25 +111,25 @@ module ActiveCachedResource
|
|
88
111
|
# @example Hashing a key
|
89
112
|
# hash_key("prefix-key") #=> "acr/prefix/Digest::SHA256.hexdigest(key)"
|
90
113
|
#
|
114
|
+
# @raise [ArgumentError] If the key does not contain a prefix and a key separated by a dash.
|
115
|
+
#
|
91
116
|
# @param key [String] the original key to be hashed. It is expected to have a prefix and the key separated by a dash.
|
92
117
|
# @return [String] the generated hashed key with the global prefix and the prefix from the original key.
|
93
118
|
def hash_key(key)
|
94
|
-
|
95
|
-
prefix, k = key.split("-", 2)
|
119
|
+
prefix, k = split_key(key)
|
96
120
|
if prefix.nil? || k.nil?
|
97
121
|
raise ArgumentError, "Key must have a prefix and a key separated by a dash"
|
98
122
|
end
|
99
|
-
|
100
|
-
"#{prefix}/" + Digest::SHA256.hexdigest(k)
|
123
|
+
"#{prefix}#{ActiveCachedResource::Constants::PREFIX_SEPARATOR}#{Digest::SHA256.hexdigest(k)}"
|
101
124
|
end
|
102
125
|
|
103
126
|
def compress(value)
|
104
|
-
|
127
|
+
value.to_json
|
105
128
|
end
|
106
129
|
|
107
130
|
def decompress(value)
|
108
|
-
|
109
|
-
rescue
|
131
|
+
JSON.parse(value)
|
132
|
+
rescue JSON::ParserError
|
110
133
|
nil
|
111
134
|
end
|
112
135
|
end
|
@@ -7,7 +7,7 @@ module ActiveCachedResource
|
|
7
7
|
|
8
8
|
# Delete the reload param from query params.
|
9
9
|
# This is drilled down via `params` option to determine if the collection should be reloaded
|
10
|
-
should_reload = query_params.delete(
|
10
|
+
should_reload = query_params.delete(Constants::RELOAD_PARAM)
|
11
11
|
if !should_reload
|
12
12
|
from_cache = resource_class.send(:cache_read, from, path_params, query_params, prefix_options)
|
13
13
|
@elements = from_cache
|
@@ -21,6 +21,23 @@ module ActiveResource # :nodoc:
|
|
21
21
|
attr_writer :prefix_options
|
22
22
|
attr_reader :from
|
23
23
|
|
24
|
+
# Returns a frozen empty collection.
|
25
|
+
#
|
26
|
+
# @return [ActiveResource::Collection] an empty collection
|
27
|
+
def self.none
|
28
|
+
new([]).tap do |collection|
|
29
|
+
collection.instance_variable_set(:@requested, true)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates a new ActiveResource::Collection instance.
|
34
|
+
#
|
35
|
+
# ==== Arguments
|
36
|
+
#
|
37
|
+
# +elements+ (Array<Object>) - An optional array of resources to be set as the collection elements.
|
38
|
+
# Defaults to an empty array.
|
39
|
+
# +from+ (String, Symbol) - The path to the collection resource or the symbol for the collection resource.
|
40
|
+
|
24
41
|
# ActiveResource::Collection is a wrapper to handle parsing index responses that
|
25
42
|
# do not directly map to Rails conventions.
|
26
43
|
#
|
@@ -98,12 +115,12 @@ module ActiveResource # :nodoc:
|
|
98
115
|
@prefix_options || {}
|
99
116
|
end
|
100
117
|
|
101
|
-
#
|
118
|
+
# Reload the collection by re-fetching the resources from the API.
|
102
119
|
#
|
103
120
|
# ==== Returns
|
104
121
|
#
|
105
122
|
# [Array<Object>] The collection of resources retrieved from the API.
|
106
|
-
def
|
123
|
+
def reload
|
107
124
|
@requested = false
|
108
125
|
request_resources!
|
109
126
|
end
|
@@ -182,6 +199,7 @@ module ActiveResource # :nodoc:
|
|
182
199
|
# # => PostCollection:xxx (filtered collection)
|
183
200
|
def where(clauses = {})
|
184
201
|
raise ArgumentError, "expected a clauses Hash, got #{clauses.inspect}" unless clauses.is_a? Hash
|
202
|
+
return self.class.none if resource_class.nil?
|
185
203
|
new_clauses = query_params.merge(clauses)
|
186
204
|
resource_class.where(new_clauses)
|
187
205
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_cached_resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Luis Urena
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-23 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activemodel-serializers-xml
|
@@ -52,25 +52,19 @@ dependencies:
|
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: '6.0'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
|
-
name:
|
55
|
+
name: ostruct
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
61
|
-
- - ">="
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: 1.7.5
|
60
|
+
version: 0.6.1
|
64
61
|
type: :runtime
|
65
62
|
prerelease: false
|
66
63
|
version_requirements: !ruby/object:Gem::Requirement
|
67
64
|
requirements:
|
68
65
|
- - "~>"
|
69
66
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
71
|
-
- - ">="
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: 1.7.5
|
67
|
+
version: 0.6.1
|
74
68
|
email:
|
75
69
|
- eljean@live.com
|
76
70
|
executables: []
|
@@ -87,6 +81,7 @@ files:
|
|
87
81
|
- lib/active_cached_resource/caching_strategies/sql_cache.rb
|
88
82
|
- lib/active_cached_resource/collection.rb
|
89
83
|
- lib/active_cached_resource/configuration.rb
|
84
|
+
- lib/active_cached_resource/constants.rb
|
90
85
|
- lib/active_cached_resource/logger.rb
|
91
86
|
- lib/active_cached_resource/model.rb
|
92
87
|
- lib/active_cached_resource/version.rb
|
@@ -141,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
136
|
- !ruby/object:Gem::Version
|
142
137
|
version: '0'
|
143
138
|
requirements: []
|
144
|
-
rubygems_version: 3.6.
|
139
|
+
rubygems_version: 3.6.3
|
145
140
|
specification_version: 4
|
146
141
|
summary: ActiveResource, but with a caching layer.
|
147
142
|
test_files: []
|