smart_cache_tenant 0.2.0 → 0.3.0

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
  SHA256:
3
- metadata.gz: a93f98aff4e2b9f648df7da645a638e272db90a42b4953fbf5496b9046f5f56a
4
- data.tar.gz: 05bf862690128e59b1f154f272d1761ce9da8cdb156796b5dc782c2932081490
3
+ metadata.gz: 20af159441d25b27dbcf6b128dc18a820c7271a44d7ddfd11743b600911aa907
4
+ data.tar.gz: 34e7d995c651f2034bfb0f583beff24479414c9e7e737faf2734880c900ce863
5
5
  SHA512:
6
- metadata.gz: 51849b0dcec7fd037cb92e0900159cd23da5dce5732b2f5bb562b367878bc8b0c7608e3b5038c9b0767f5b7dafa08d5c80651d886165ebd1b677a5521589731b
7
- data.tar.gz: cd03d5da66ff96284e1c83effe0c8897acd2443dbb5839cf421d02b439207bca2feefde5f70af23b8314910d313cfd89b6f2304f3e0acf2715017f8e391af0af
6
+ metadata.gz: 9c1568821feb22552554776c1c412d866bb59367af4cb628ddcede07c2e465ee22ce8db47dde0033b0674df5fe81c5bc1a1e257e9506777a0b90ed978529c69b
7
+ data.tar.gz: b2c9215c5bcf704814eabdea230eebd656eeaa62c480641624d7ba10c41651ebc953426e73c109a3f6de1c3db1591f3d45029258fbc0b9b747e174df2e1ebe3a
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require spec_helper
2
+ --format documentation
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2026-05-02
4
+
5
+ - Fixed tenant version invalidation path in `VersionStore.bump!` when `tenant_column` is configured and `tenant_id` is blank.
6
+ - Added wildcard invalidation behavior to clear tenant-scoped version keys on global bulk invalidation scenarios.
7
+ - Added Rails 7 runtime dependency declaration in the gemspec.
8
+ - Added a development bootstrap for `bin/console` with a minimal Rails + ActiveRecord environment.
9
+ - Added a complete RSpec suite covering cached reads, version store behavior, `after_commit` invalidation, and bulk write invalidation (`insert_all`, `upsert_all`, `update_all`).
10
+
3
11
  ## [0.2.0] - 2026-05-01
4
12
 
5
13
  - Added all features and improvements for the first major release.
data/README.md CHANGED
@@ -257,7 +257,11 @@ This is useful during rollout to confirm which queries are being served from cac
257
257
 
258
258
  ## Development
259
259
 
260
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
260
+ After checking out the repo, run `bin/setup` to install dependencies.
261
+
262
+ Run `bin/console` to start an interactive prompt with a minimal Rails + ActiveRecord environment (SQLite in-memory and Rails cache configured). A sample `ConsoleProject` model is available to validate cache behavior quickly.
263
+
264
+ Run `bundle exec rspec` to execute the automated tests.
261
265
 
262
266
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
263
267
 
@@ -18,15 +18,15 @@ module SmartCacheTenant
18
18
 
19
19
  def bump_smart_cache_for_class_bulk_write!(attributes)
20
20
  return unless try(:smart_cache_enabled?)
21
- return if attributes.blank?
21
+ return if attributes.respond_to?(:empty?) && attributes.empty?
22
22
 
23
23
  tenant_column = SmartCacheTenant.config.tenant_column
24
- tenant_ids = Array(attributes).filter_map do |row|
24
+ tenant_ids = Array(attributes).map do |row|
25
25
  next unless row.respond_to?(:[])
26
26
  next if tenant_column.blank?
27
27
 
28
28
  row[tenant_column] || row[tenant_column.to_sym] || row[tenant_column.to_s]
29
- end.compact.uniq
29
+ end.compact_blank.uniq
30
30
 
31
31
  if tenant_ids.empty?
32
32
  SmartCacheTenant::VersionStore.bump!(self)
@@ -55,21 +55,21 @@ module SmartCacheTenant
55
55
  end
56
56
  end
57
57
 
58
- def update_all(updates)
58
+ def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
59
59
  result = super
60
- bump_smart_cache_for_bulk_write!(affected_rows: result)
60
+ bump_smart_cache_for_class_bulk_write!(attributes: attributes)
61
61
  result
62
62
  end
63
63
 
64
- def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
64
+ def upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
65
65
  result = super
66
- bump_smart_cache_for_bulk_write!(tenant_ids: tenant_ids_from_bulk_attributes(attributes)) if attributes.present?
66
+ bump_smart_cache_for_class_bulk_write!(attributes: attributes)
67
67
  result
68
68
  end
69
69
 
70
- def upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
70
+ def update_all(updates)
71
71
  result = super
72
- bump_smart_cache_for_bulk_write!(tenant_ids: tenant_ids_from_bulk_attributes(attributes)) if attributes.present?
72
+ bump_smart_cache_for_class_bulk_write!(affected_rows: result)
73
73
  result
74
74
  end
75
75
 
@@ -160,24 +160,26 @@ module SmartCacheTenant
160
160
  nil
161
161
  end
162
162
 
163
- def tenant_ids_from_bulk_attributes(attributes)
163
+ def resolve_tenant_ids_from_bulk_attributes(attributes)
164
+ return if attributes.respond_to?(:empty?) && attributes.empty?
165
+
164
166
  tenant_column = SmartCacheTenant.config.tenant_column
165
- return [] if tenant_column.blank?
166
-
167
- Array(attributes).filter_map do |row|
167
+ Array(attributes).map do |row|
168
168
  next unless row.respond_to?(:[])
169
+ next if tenant_column.blank?
169
170
 
170
171
  row[tenant_column] || row[tenant_column.to_sym] || row[tenant_column.to_s]
171
- end.uniq
172
+ end.compact_blank.uniq
172
173
  end
173
174
 
174
- def bump_smart_cache_for_bulk_write!(tenant_ids: nil, affected_rows: nil)
175
+ def bump_smart_cache_for_class_bulk_write!(attributes: nil, affected_rows: nil)
175
176
  return unless klass.try(:smart_cache_enabled?)
177
+ return if attributes.respond_to?(:empty?) && attributes.empty?
176
178
  return if affected_rows.respond_to?(:zero?) && affected_rows.zero?
177
179
 
178
- resolved_tenant_ids = Array(tenant_ids).compact
180
+ resolved_tenant_ids = Array(resolve_tenant_ids_from_bulk_attributes(attributes))
179
181
  resolved_tenant_ids << resolve_tenant_id
180
- resolved_tenant_ids = resolved_tenant_ids.compact.uniq
182
+ resolved_tenant_ids = resolved_tenant_ids.compact_blank.uniq
181
183
 
182
184
  if resolved_tenant_ids.empty?
183
185
  SmartCacheTenant::VersionStore.bump!(klass)
@@ -27,7 +27,11 @@ module SmartCacheTenant
27
27
  end
28
28
 
29
29
  def smart_cache_bump!
30
- SmartCacheTenant::VersionStore.bump!(self.class, try(SmartCacheTenant.config.tenant_column))
30
+ self.class.smart_cache_bump!(try(SmartCacheTenant.config.tenant_column))
31
+ end
32
+
33
+ def smart_cached_version
34
+ self.class.smart_cached_version(try(SmartCacheTenant.config.tenant_column))
31
35
  end
32
36
 
33
37
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails/railtie'
4
+
3
5
  module SmartCacheTenant
4
6
  class Railtie < Rails::Railtie
5
7
  initializer 'smart_cache.initialize' do
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SmartCacheTenant
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -9,10 +9,14 @@ module SmartCacheTenant
9
9
 
10
10
  def self.bump!(model_klass, tenant_id = nil)
11
11
  key = build_key(model_klass, tenant_id)
12
- new_version = generate_version
13
- Rails.cache.write(key, new_version, expires_in: SmartCacheTenant.config.ttl)
14
12
 
15
- new_version
13
+ if SmartCacheTenant.config.tenant_column.present? && tenant_id.blank?
14
+ Rails.cache.delete_matched("#{key}:*")
15
+ else
16
+ new_version = generate_version
17
+ Rails.cache.write(key, new_version, expires_in: SmartCacheTenant.config.ttl)
18
+ new_version
19
+ end
16
20
  end
17
21
 
18
22
  def self.build_key(model_klass, tenant_id = nil)
metadata CHANGED
@@ -1,15 +1,63 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_cache_tenant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henrique A. Shiraishi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-01 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2026-05-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '7.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '8.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '7.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '8.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: sqlite3
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.7'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.7'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.13'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.13'
13
61
  description: SmartCacheTenant adds tenant-aware query caching on top of ActiveRecord
14
62
  by storing cached read results in Rails.cache and invalidating them through lightweight
15
63
  version keys.
@@ -19,6 +67,7 @@ executables: []
19
67
  extensions: []
20
68
  extra_rdoc_files: []
21
69
  files:
70
+ - ".rspec"
22
71
  - ".ruby-version"
23
72
  - CHANGELOG.md
24
73
  - LICENSE.txt