cached_resource 7.2.0 → 8.0.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
  SHA256:
3
- metadata.gz: d1c2150c2dc21cf091c9b26674b3e52a7bd43938318704f7c2f0739a0b9756aa
4
- data.tar.gz: 2f7b9665c688f2a60b7def43cfafbe2701accded9fcf9aabc371fe91bf78362d
3
+ metadata.gz: af6263e0c63b68542a68f62371c79b057e8d9244eb4ab670cfa8956c7cdb1d54
4
+ data.tar.gz: 471295437c0567959f596cd4a8e13639dc670991632e99d01d1bbdea82123664
5
5
  SHA512:
6
- metadata.gz: c0c94c6b77f623a49a3259a69a4bb1b1d2d7fc219d590b740d5a86c71f3cfbf7eb783a2e8a2c06631c926bd2679b220341d8fbf03b77a3651d5219a70bb8d779
7
- data.tar.gz: 207c37429a14511fb788d21bc69e86b01f8f59a303b20aebafb2f07e54aba48546c03a5ac7fa4b99da0bd9b7cd53d385ddb73306c643d9044d113ea638949e61
6
+ metadata.gz: 02ee32043c70de70d3befa042ad68c0de0b71e8abf0197e477e97a1489c51ed7eb726bc38a561dd29e34763184cea026275b6a9ff4b9e20ed2c8876f90d5944e
7
+ data.tar.gz: b652cbf1e7d42adaecf1639ac01c2489a75120bb2780bdb272fef5f2be9ad93fe339521d8e0337434cc98e6eb6234164274fa446710211c8eadb3a349435af15
@@ -19,31 +19,11 @@ jobs:
19
19
 
20
20
  strategy:
21
21
  matrix:
22
- ruby-version: ['1.9', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2']
23
- rails-version: ['4.2', '5.0', '5.1', '6.0', '6.1', '7.0']
22
+ ruby-version: ['2.3', '2.4', '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3']
23
+ rails-version: ['4.2', '5.0', '5.1', '6.0', '6.1', '7.0', '7.1']
24
24
  exclude:
25
- # Segmentation faults during tests, but should work?
26
- - ruby-version: '2.2'
27
- rails-version: '5.0'
28
- - ruby-version: '2.2'
29
- rails-version: '5.1'
30
- # Too old
31
- - ruby-version: '1.9'
32
- rails-version: '5.0'
33
- - ruby-version: '1.9'
34
- rails-version: '5.1'
35
- - ruby-version: '1.9'
36
- rails-version: '6.0'
37
- - ruby-version: '1.9'
38
- rails-version: '6.1'
39
- - ruby-version: '1.9'
40
- rails-version: '7.0'
41
25
  # activesupport (~> 6.0.0) was resolved to 6.0.6.1, which depends on ruby (>= 2.5.0)
42
26
  # activesupport (~> 6.1.0) was resolved to 6.1.7.2, which depends on ruby (>= 2.5.0)
43
- - ruby-version: '2.2'
44
- rails-version: '6.0'
45
- - ruby-version: '2.2'
46
- rails-version: '6.1'
47
27
  - ruby-version: '2.3'
48
28
  rails-version: '6.0'
49
29
  - ruby-version: '2.3'
@@ -53,8 +33,6 @@ jobs:
53
33
  - ruby-version: '2.4'
54
34
  rails-version: '6.1'
55
35
  # activesupport (~> 7.0.0) was resolved to 7.0.4.2, which depends on Ruby (>= 2.7.0)
56
- - ruby-version: '2.2'
57
- rails-version: '7.0'
58
36
  - ruby-version: '2.3'
59
37
  rails-version: '7.0'
60
38
  - ruby-version: '2.4'
@@ -87,9 +65,25 @@ jobs:
87
65
  rails-version: '5.0'
88
66
  - ruby-version: '3.2'
89
67
  rails-version: '5.1'
68
+ # rails (~> 7.1.0) was resolved to 7.1.3.2, which depends on Ruby (>= 2.7.0)
69
+ - ruby-version: '2.3'
70
+ rails-version: '7.1'
71
+ - ruby-version: '2.4'
72
+ rails-version: '7.1'
73
+ - ruby-version: '2.5'
74
+ rails-version: '7.1'
75
+ - ruby-version: '2.6'
76
+ rails-version: '7.1'
77
+ # Because rails >= 4.0.0.beta1, < 5.0.5.rc1 depends on bundler >= 1.3.0, < 2.0
78
+ # and the current Bundler version (2.5.9) does not satisfy bundler >= 1.3.0, < 2.0,
79
+ # rails >= 4.0.0.beta1, < 5.0.5.rc1 cannot be used.
80
+ # So, because Gemfile depends on rails ~> 4.2.0,
81
+ # version solving has failed.
82
+ - ruby-version: '3.3'
83
+ rails-version: '4.2'
90
84
 
91
85
  steps:
92
- - uses: actions/checkout@v3
86
+ - uses: actions/checkout@v4
93
87
  - name: Set up Ruby ${{ matrix.ruby-version }}
94
88
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
95
89
  # change this to (see https://github.com/ruby/setup-ruby#versioning):
data/Gemfile CHANGED
@@ -24,6 +24,8 @@ when "6.1"
24
24
  eval_gemfile('../gemfiles/6.1.gemfile')
25
25
  when "7.0"
26
26
  eval_gemfile('../gemfiles/7.0.gemfile')
27
+ when "7.1"
28
+ eval_gemfile('../gemfiles/7.1.gemfile')
27
29
  else
28
30
  puts "\e[93mNo TEST_RAILS_VERSION present, letting dependency manager decide what's best.\e[0m" if ENV['DEBUG']
29
31
  end
data/README.md CHANGED
@@ -12,18 +12,17 @@ gem install cached_resource
12
12
 
13
13
  CachedResource is designed to be framework agnostic, but will hook into Rails for caching and logging if available. CachedResource supports the following ActiveSupport/Rails (right) and Ruby (down) version combinations:
14
14
 
15
- | | 🛤️ 4.2 | 🛤️ 5.0 | 🛤️ 5.1 | 🛤️ 6.0 | 🛤️ 6.1 | 🛤️ 7.0 |
16
- |-------|-----|-----|-----|-----|-----|-----|
17
- | 💎 1.9 | ✅ | | | | | |
18
- | 💎 2.2 | ✅ | | | | | |
19
- | 💎 2.3 | ✅ | ✅ | ✅ | | | |
20
- | 💎 2.4 | ✅ | ✅ | ✅ | | | |
21
- | 💎 2.5 | ✅ | ✅ | ✅ | ✅ | ✅ | |
22
- | 💎 2.6 ||| ✅ | ✅ | ✅ | |
23
- | 💎 2.7 | | ✅ | ✅ | ✅ | ✅ | |
24
- | 💎 3.0 | | | | ✅ | ✅ | ✅ |
25
- | 💎 3.1 | | | | ✅ | ✅ | ✅ |
26
- | 💎 3.2 | | | | ✅ | ✅ | ✅ |
15
+ | | 🛤️ 4.2 | 🛤️ 5.0 | 🛤️ 5.1 | 🛤️ 6.0 | 🛤️ 6.1 | 🛤️ 7.0 | 🛤️ 7.1 |
16
+ |-------|-----|-----|-----|-----|-----|-----|-----|
17
+ | 💎 2.3 | ✅ ||| | | | |
18
+ | 💎 2.4 | ✅ ||| | | | |
19
+ | 💎 2.5 | ✅ | ✅ | ✅ ||| | |
20
+ | 💎 2.6 | ✅ | | ✅ | ✅ || |
21
+ | 💎 2.7 | | ✅ | ✅ | ✅ | ✅ | ✅ |✅ |
22
+ | 💎 3.0 | | | | ✅ | ✅ | ✅ ||
23
+ | 💎 3.1 | | | | ✅ | ✅ | ✅ | ✅ |
24
+ | 💎 3.2 | | | | ✅ | ✅ | ✅ | ✅ |
25
+ | 💎 3.3 | ||| ✅ | ✅ | ✅ | ✅ |
27
26
 
28
27
  ## Limitations
29
28
 
@@ -55,15 +54,17 @@ end
55
54
  CachedResource accepts the following options:
56
55
 
57
56
  * `:enabled` Default: `true`
58
- * `:ttl` The time in seconds until the cache should expire. Default: `604800`
59
- * `:race_condition_ttl` The race condition ttl, to prevent [dog pile effect](https://en.wikipedia.org/wiki/Cache_stampede) or [cache stampede](https://en.wikipedia.org/wiki/Cache_stampede). Default: 86400
60
- * `:ttl_randomization` Enable ttl randomization. Default: `false`
61
- * `:ttl_randomization_scale` A Range from which a random value will be selected to scale the ttl. Default: `1..2`
62
- * `:collection_synchronize` Use collections to generate cache entries for individuals. Update the existing cached principal collection when retrieving subsets of the principal collection or individuals. Default: `false`
57
+ * `:cache_collections` Set to false to always remake a request for collections. Default: `true`
58
+ * `:cache` The cache store that CacheResource should use. Default: The `Rails.cache` if available, or an `ActiveSupport::Cache::MemoryStore`
63
59
  * `:collection_arguments` The arguments that identify the principal collection request. Default: `[:all]`
60
+ * `:collection_synchronize` Use collections to generate cache entries for individuals. Update the existing cached principal collection when retrieving subsets of the principal collection or individuals. Default: `false`
61
+ * `:concurrent_write` Set to true to make concurrent writes to cache after successful API response. Default: `false`
62
+ * Requires the [concurrent-ruby](https://rubygems.org/gems/concurrent-ruby) gem
64
63
  * `:logger` The logger to which CachedResource messages should be written. Default: The `Rails.logger` if available, or an `ActiveSupport::Logger`
65
- * `:cache` The cache store that CacheResource should use. Default: The `Rails.cache` if available, or an `ActiveSupport::Cache::MemoryStore`
66
- * `:cache_collections` Set to false to always remake a request for collections. Default: `true`
64
+ * `:race_condition_ttl` The race condition ttl, to prevent [dog pile effect](https://en.wikipedia.org/wiki/Cache_stampede) or [cache stampede](https://en.wikipedia.org/wiki/Cache_stampede). Default: 86400
65
+ * `:ttl_randomization_scale` A Range from which a random value will be selected to scale the ttl. Default: `1..2`
66
+ * `:ttl_randomization` Enable ttl randomization. Default: `false`
67
+ * `:ttl` The time in seconds until the cache should expire. Default: `604800`
67
68
 
68
69
  You can set them like this:
69
70
 
@@ -25,4 +25,5 @@ Gem::Specification.new do |s|
25
25
 
26
26
  s.add_development_dependency "rake"
27
27
  s.add_development_dependency "rspec"
28
+ s.add_development_dependency "concurrent-ruby", '~> 1.2', '>= 1.2.3'
28
29
  end
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "~> 7.1.0"
@@ -18,6 +18,16 @@ module CachedResource
18
18
  # and establishing the necessary methods.
19
19
  def setup_cached_resource!(options)
20
20
  @cached_resource = CachedResource::Configuration.new(options)
21
+ if @cached_resource.concurrent_write
22
+ begin
23
+ send :require, 'concurrent/promise'
24
+ rescue LoadError
25
+ @cached_resource.logger.error(
26
+ "`concurrent_write` option is enabled, but `concurrent-ruby` is not an installed dependency"
27
+ )
28
+ raise
29
+ end
30
+ end
21
31
  send :include, CachedResource::Caching
22
32
  @cached_resource
23
33
  end
@@ -45,7 +45,7 @@ module CachedResource
45
45
  cache_collection_synchronize(object, *arguments) if cached_resource.collection_synchronize
46
46
  return object if !cached_resource.cache_collections && is_any_collection?(*arguments)
47
47
  cache_write(key, object, *arguments)
48
- cache_read(key)
48
+ object
49
49
  end
50
50
 
51
51
  # If this is a pure, unadulterated "all" request
@@ -82,7 +82,7 @@ module CachedResource
82
82
  # Avoid cache nil or [] objects
83
83
  def should_cache?(object)
84
84
  return false unless cached_resource.enabled
85
- object.respond_to?(:empty?) ? !object.empty? : !!object
85
+ object.present?
86
86
  end
87
87
 
88
88
  # Determine if the given arguments represent
@@ -110,7 +110,7 @@ module CachedResource
110
110
  next restored unless respond_to?(:collection_parser)
111
111
  collection_parser.new(restored).tap do |parser|
112
112
  parser.resource_class = self
113
- parser.original_params = json['original_params']
113
+ parser.original_params = json['original_params'].deep_symbolize_keys
114
114
  end
115
115
  else
116
116
  full_dup(cache)
@@ -123,6 +123,14 @@ module CachedResource
123
123
 
124
124
  # Write an entry to the cache for the given key and value.
125
125
  def cache_write(key, object, *arguments)
126
+ if cached_resource.concurrent_write
127
+ Concurrent::Promise.execute { _cache_write(key, object, *arguments) } && true
128
+ else
129
+ _cache_write(key, object, *arguments)
130
+ end
131
+ end
132
+
133
+ def _cache_write(key, object, *arguments)
126
134
  options = arguments[1] || {}
127
135
  params = options[:params]
128
136
  prefix_options, query_options = split_options(params)
@@ -24,18 +24,20 @@ module CachedResource
24
24
  # :cache, default: Rails.cache or ActiveSupport::Cache::MemoryStore.new,
25
25
  # :logger, default: Rails.logger or ActiveSupport::Logger.new(NilIO.new),
26
26
  # :cache_collections, default: true
27
+ # :concurrent_write, default: false
27
28
  def initialize(options={})
28
29
  super({
29
30
  :enabled => true,
31
+ :cache => defined?(Rails.cache) && Rails.cache || CACHE,
32
+ :cache_collections => true,
33
+ :collection_arguments => [:all],
34
+ :collection_synchronize => false,
35
+ :concurrent_write => false,
36
+ :logger => defined?(Rails.logger) && Rails.logger || LOGGER,
30
37
  :race_condition_ttl => 86400,
31
38
  :ttl => 604800,
32
39
  :ttl_randomization => false,
33
- :ttl_randomization_scale => 1..2,
34
- :collection_synchronize => false,
35
- :collection_arguments => [:all],
36
- :cache => defined?(Rails.cache) && Rails.cache || CACHE,
37
- :logger => defined?(Rails.logger) && Rails.logger || LOGGER,
38
- :cache_collections => true
40
+ :ttl_randomization_scale => 1..2
39
41
  }.merge(options))
40
42
  end
41
43
 
@@ -72,4 +74,4 @@ module CachedResource
72
74
  end
73
75
 
74
76
  end
75
- end
77
+ end
@@ -1,3 +1,3 @@
1
1
  module CachedResource
2
- VERSION = "7.2.0"
2
+ VERSION = "8.0.0"
3
3
  end
@@ -66,19 +66,27 @@ describe CachedResource do
66
66
  end
67
67
  end
68
68
 
69
- it "should cache a response" do
70
- result = Thing.find(1)
71
- read_from_cache("thing/1").should == result
72
- end
69
+ shared_examples "caching" do
70
+ it "should cache a response" do
71
+ result = Thing.find(1)
72
+ read_from_cache("thing/1").should == result
73
+ end
74
+
75
+ it "shouldn't cache nil response" do
76
+ Thing.find(:all, :params => { :name => '42' })
77
+ read_from_cache("thing/all/name/42").should == nil
78
+ end
73
79
 
74
- it "shouldn't cache nil response" do
75
- Thing.find(:all, :params => { :name => '42' })
76
- read_from_cache("thing/all/name/42").should == nil
80
+ it "shouldn't cache blank response" do
81
+ Thing.find(:all, :params => { :name => '43' })
82
+ read_from_cache("thing/all/name/43").should == nil
83
+ end
77
84
  end
78
85
 
79
- it "shouldn't cache [] response" do
80
- Thing.find(:all, :params => { :name => '43' })
81
- read_from_cache("thing/all/name/43").should == nil
86
+ include_examples "caching"
87
+
88
+ context 'when concurrency is turned on' do
89
+ include_examples "caching"
82
90
  end
83
91
 
84
92
  it "should cache a response for a string primary key" do
@@ -234,12 +242,12 @@ describe CachedResource do
234
242
  end
235
243
 
236
244
  non_cached = Thing.where(name: 'ada')
237
- non_cached.original_params.should == { 'name' => 'ada' }
245
+ non_cached.original_params.should == { :name => 'ada' }
238
246
  non_cached.map(&:id).should == @thing_collection.map { |h| h[:id]}
239
247
 
240
248
  cached = read_from_cache('thing/all/{:params=>{:name=>"ada"}}')
241
249
  cached.should be_instance_of(CustomCollection)
242
- cached.original_params.should == { 'name' => 'ada' }
250
+ cached.original_params.should == { :name => 'ada' }
243
251
  cached.resource_class.should == Thing
244
252
  cached.map(&:id).should == @thing_collection.map { |h| h[:id]}
245
253
 
@@ -249,11 +257,11 @@ describe CachedResource do
249
257
  non_cached = cached.where(major: 'CS')
250
258
  end
251
259
 
252
- non_cached.original_params.should == { 'name' => 'ada', 'major' => 'CS' }
260
+ non_cached.original_params.should == { :name => 'ada', :major => 'CS' }
253
261
  non_cached.resource_class.should == Thing
254
262
  non_cached.map(&:id).should == @thing_collection2.map { |h| h[:id]}
255
- cached = read_from_cache('thing/all/{:params=>{"name"=>"ada",:major=>"cs"}}')
256
- cached.original_params.should == { 'name' => 'ada', 'major' => 'CS' }
263
+ cached = read_from_cache('thing/all/{:params=>{:name=>"ada",:major=>"cs"}}')
264
+ cached.original_params.should == { :name => 'ada', :major => 'CS' }
257
265
  cached.resource_class.should == Thing
258
266
  cached.map(&:id).should == @thing_collection2.map { |h| h[:id]}
259
267
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cached_resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morgan Brown
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-27 00:00:00.000000000 Z
11
+ date: 2024-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -80,6 +80,26 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: concurrent-ruby
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.2.3
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '1.2'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 1.2.3
83
103
  description: Enables request-based caching for ActiveResource
84
104
  email: cached_resource@email.mhgbrown.is
85
105
  executables: []
@@ -101,6 +121,7 @@ files:
101
121
  - gemfiles/6.0.gemfile
102
122
  - gemfiles/6.1.gemfile
103
123
  - gemfiles/7.0.gemfile
124
+ - gemfiles/7.1.gemfile
104
125
  - lib/cached_resource.rb
105
126
  - lib/cached_resource/cached_resource.rb
106
127
  - lib/cached_resource/caching.rb