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 +4 -4
- data/.rspec +2 -0
- data/CHANGELOG.md +8 -0
- data/README.md +5 -1
- data/lib/smart_cache_tenant/cacheable_persistence.rb +3 -3
- data/lib/smart_cache_tenant/cacheable_relation.rb +16 -14
- data/lib/smart_cache_tenant/model_callbacks.rb +5 -1
- data/lib/smart_cache_tenant/railtie.rb +2 -0
- data/lib/smart_cache_tenant/version.rb +1 -1
- data/lib/smart_cache_tenant/version_store.rb +7 -3
- metadata +52 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20af159441d25b27dbcf6b128dc18a820c7271a44d7ddfd11743b600911aa907
|
|
4
|
+
data.tar.gz: 34e7d995c651f2034bfb0f583beff24479414c9e7e737faf2734880c900ce863
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c1568821feb22552554776c1c412d866bb59367af4cb628ddcede07c2e465ee22ce8db47dde0033b0674df5fe81c5bc1a1e257e9506777a0b90ed978529c69b
|
|
7
|
+
data.tar.gz: b2c9215c5bcf704814eabdea230eebd656eeaa62c480641624d7ba10c41651ebc953426e73c109a3f6de1c3db1591f3d45029258fbc0b9b747e174df2e1ebe3a
|
data/.rspec
ADDED
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.
|
|
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.
|
|
21
|
+
return if attributes.respond_to?(:empty?) && attributes.empty?
|
|
22
22
|
|
|
23
23
|
tenant_column = SmartCacheTenant.config.tenant_column
|
|
24
|
-
tenant_ids = Array(attributes).
|
|
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.
|
|
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
|
|
58
|
+
def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
|
|
59
59
|
result = super
|
|
60
|
-
|
|
60
|
+
bump_smart_cache_for_class_bulk_write!(attributes: attributes)
|
|
61
61
|
result
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
def
|
|
64
|
+
def upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
|
|
65
65
|
result = super
|
|
66
|
-
|
|
66
|
+
bump_smart_cache_for_class_bulk_write!(attributes: attributes)
|
|
67
67
|
result
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
def
|
|
70
|
+
def update_all(updates)
|
|
71
71
|
result = super
|
|
72
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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(
|
|
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.
|
|
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
|
-
|
|
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
|
|
@@ -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
|
-
|
|
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.
|
|
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-
|
|
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
|