identity_cache 1.5.6 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +7 -6
- data/.ruby-version +1 -1
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +31 -20
- data/dev.yml +2 -10
- data/gemfiles/Gemfile.latest-release +1 -0
- data/gemfiles/Gemfile.min-supported +1 -1
- data/gemfiles/Gemfile.rails-edge +1 -0
- data/lib/identity_cache/parent_model_expiration.rb +4 -0
- data/lib/identity_cache/version.rb +1 -1
- data/lib/identity_cache.rb +70 -21
- data/shipit.rubygems.yml +4 -1
- metadata +6 -7
- data/isogun.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cb45582de9a181e4b32595a183630023ba9af3a84ed5123308eada240420ab8
|
4
|
+
data.tar.gz: 46ce8b2795adbd03ca67d69ba9ddd725ac1b7bcbf56ac85344ee220380495ad4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a4053d1a93c89a058593fc998dad0c77ac32aae4d691db3087bd88743bae2aa76193112262e0ac536468c3ddc14ceef5fd34e2d770d7e8d3129d83df65d604d
|
7
|
+
data.tar.gz: e397cb05b4d7bc5a3a6304fc4346ac63318c043c44dee032730af30c23a19d42168f0390039d6986aeef33dfda28e99dda831ca23dca8ea217a356d736dccd6e
|
data/.github/workflows/ci.yml
CHANGED
@@ -19,11 +19,11 @@ jobs:
|
|
19
19
|
ruby: '3.0'
|
20
20
|
gemfile: "Gemfile.min-supported"
|
21
21
|
- name: 'Latest released & run rubocop'
|
22
|
-
ruby: '3.
|
22
|
+
ruby: '3.3'
|
23
23
|
gemfile: "Gemfile.latest-release"
|
24
24
|
rubocop: true
|
25
25
|
- name: 'Rails edge'
|
26
|
-
ruby: '3.
|
26
|
+
ruby: '3.3'
|
27
27
|
gemfile: "Gemfile.rails-edge"
|
28
28
|
edge: true
|
29
29
|
|
@@ -69,25 +69,26 @@ jobs:
|
|
69
69
|
run: |
|
70
70
|
sudo apt-get update
|
71
71
|
sudo apt-get -y install libmemcached-dev libmysqlclient-dev libpq-dev libsasl2-dev
|
72
|
+
|
72
73
|
- uses: actions/checkout@v2
|
73
74
|
- name: Set up Ruby
|
74
75
|
uses: ruby/setup-ruby@v1
|
75
76
|
with:
|
76
77
|
ruby-version: ${{ matrix.entry.ruby }}
|
77
|
-
|
78
|
-
|
79
|
-
gem install bundler
|
80
|
-
bundle install --jobs 4 --retry 3
|
78
|
+
bundler-cache: true
|
79
|
+
|
81
80
|
- name: Test with mysql
|
82
81
|
env:
|
83
82
|
DB: mysql2
|
84
83
|
run: bundle exec rake test
|
84
|
+
|
85
85
|
- name: Test with postgres and memcached_store
|
86
86
|
env:
|
87
87
|
DB: postgresql
|
88
88
|
POSTGRES_PASSWORD: postgres
|
89
89
|
ADAPTER: memcached
|
90
90
|
run: bundle exec rake test
|
91
|
+
|
91
92
|
- name: Run rubocop
|
92
93
|
if: matrix.entry.rubocop
|
93
94
|
run: bundle exec rubocop
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.4
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 1.6.1
|
6
|
+
|
7
|
+
- Fix deprecation warnings on Active Record 7.2. (#575)
|
8
|
+
|
9
|
+
## 1.6.0
|
10
|
+
|
11
|
+
- Introduce `.with_deferred_parent_expiration`, which takes a block and avoids duplicate parent cache expiry. (#569)
|
12
|
+
|
5
13
|
## 1.5.6
|
6
14
|
|
7
15
|
- Minor performance improvements on association read
|
data/Gemfile
CHANGED
@@ -9,9 +9,9 @@ gem "rubocop-shopify", "~> 2.9.0", require: false
|
|
9
9
|
|
10
10
|
gem "mysql2", "~> 0.5.3", platform: :mri
|
11
11
|
gem "pg", ">= 0.18", "< 2.0", platform: :mri
|
12
|
-
gem "memcached", "
|
12
|
+
gem "memcached", github: "Shopify/memcached", branch: "1-0-stable-shopify", platform: :mri
|
13
13
|
gem "memcached_store", "~> 2.3.2", platform: :mri
|
14
|
-
gem "dalli", "~> 2.
|
14
|
+
gem "dalli", "~> 3.2.3"
|
15
15
|
gem "cityhash", "~> 0.6.0", platform: :mri
|
16
16
|
|
17
17
|
gem "byebug", platform: :mri
|
data/Gemfile.lock
CHANGED
@@ -1,52 +1,59 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/Shopify/memcached.git
|
3
|
+
revision: 54a89bae698896a00fd2ceeb142dada6285f73ed
|
4
|
+
branch: 1-0-stable-shopify
|
5
|
+
specs:
|
6
|
+
memcached (1.9.0)
|
7
|
+
|
1
8
|
PATH
|
2
9
|
remote: .
|
3
10
|
specs:
|
4
|
-
identity_cache (1.
|
11
|
+
identity_cache (1.6.1)
|
5
12
|
activerecord (>= 7.0)
|
6
13
|
ar_transaction_changes (~> 1.1)
|
7
14
|
|
8
15
|
GEM
|
9
16
|
remote: https://rubygems.org/
|
10
17
|
specs:
|
11
|
-
activemodel (7.
|
12
|
-
activesupport (= 7.
|
13
|
-
activerecord (7.
|
14
|
-
activemodel (= 7.
|
15
|
-
activesupport (= 7.
|
18
|
+
activemodel (7.2.0)
|
19
|
+
activesupport (= 7.2.0)
|
20
|
+
activerecord (7.2.0)
|
21
|
+
activemodel (= 7.2.0)
|
22
|
+
activesupport (= 7.2.0)
|
16
23
|
timeout (>= 0.4.0)
|
17
|
-
activesupport (7.
|
24
|
+
activesupport (7.2.0)
|
18
25
|
base64
|
19
26
|
bigdecimal
|
20
|
-
concurrent-ruby (~> 1.0, >= 1.
|
27
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
21
28
|
connection_pool (>= 2.2.5)
|
22
29
|
drb
|
23
30
|
i18n (>= 1.6, < 2)
|
31
|
+
logger (>= 1.4.2)
|
24
32
|
minitest (>= 5.1)
|
25
|
-
|
26
|
-
tzinfo (~> 2.0)
|
33
|
+
securerandom (>= 0.3)
|
34
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
27
35
|
ar_transaction_changes (1.1.9)
|
28
36
|
activerecord (>= 5.2.0)
|
29
37
|
ast (2.4.2)
|
30
38
|
base64 (0.2.0)
|
31
|
-
bigdecimal (3.1.
|
39
|
+
bigdecimal (3.1.8)
|
32
40
|
byebug (11.1.3)
|
33
41
|
cityhash (0.6.0)
|
34
|
-
concurrent-ruby (1.
|
42
|
+
concurrent-ruby (1.3.4)
|
35
43
|
connection_pool (2.4.1)
|
36
|
-
dalli (2.
|
44
|
+
dalli (3.2.3)
|
37
45
|
drb (2.2.1)
|
38
|
-
i18n (1.14.
|
46
|
+
i18n (1.14.5)
|
39
47
|
concurrent-ruby (~> 1.0)
|
40
48
|
json (2.7.1)
|
41
49
|
language_server-protocol (3.17.0.3)
|
42
|
-
|
50
|
+
logger (1.6.0)
|
43
51
|
memcached_store (2.3.4)
|
44
52
|
activesupport (>= 6)
|
45
53
|
memcached (~> 1.8)
|
46
|
-
minitest (5.
|
54
|
+
minitest (5.25.1)
|
47
55
|
mocha (2.1.0)
|
48
56
|
ruby2_keywords (>= 0.0.5)
|
49
|
-
mutex_m (0.2.0)
|
50
57
|
mysql2 (0.5.6)
|
51
58
|
parallel (1.24.0)
|
52
59
|
parser (3.3.0.5)
|
@@ -57,7 +64,8 @@ GEM
|
|
57
64
|
rainbow (3.1.1)
|
58
65
|
rake (13.1.0)
|
59
66
|
regexp_parser (2.9.0)
|
60
|
-
rexml (3.2.
|
67
|
+
rexml (3.2.8)
|
68
|
+
strscan (>= 3.0.9)
|
61
69
|
rubocop (1.61.0)
|
62
70
|
json (~> 2.3)
|
63
71
|
language_server-protocol (>= 3.17.0)
|
@@ -75,8 +83,10 @@ GEM
|
|
75
83
|
rubocop (~> 1.33)
|
76
84
|
ruby-progressbar (1.13.0)
|
77
85
|
ruby2_keywords (0.0.5)
|
86
|
+
securerandom (0.3.1)
|
78
87
|
spy (1.0.5)
|
79
88
|
stackprof (0.2.26)
|
89
|
+
strscan (3.1.0)
|
80
90
|
timeout (0.4.1)
|
81
91
|
tzinfo (2.0.6)
|
82
92
|
concurrent-ruby (~> 1.0)
|
@@ -84,14 +94,15 @@ GEM
|
|
84
94
|
|
85
95
|
PLATFORMS
|
86
96
|
arm64-darwin-22
|
97
|
+
arm64-darwin-23
|
87
98
|
x86_64-linux
|
88
99
|
|
89
100
|
DEPENDENCIES
|
90
101
|
byebug
|
91
102
|
cityhash (~> 0.6.0)
|
92
|
-
dalli (~> 2.
|
103
|
+
dalli (~> 3.2.3)
|
93
104
|
identity_cache!
|
94
|
-
memcached
|
105
|
+
memcached!
|
95
106
|
memcached_store (~> 2.3.2)
|
96
107
|
minitest (~> 5.14)
|
97
108
|
mocha (~> 2.0)
|
data/dev.yml
CHANGED
@@ -1,18 +1,10 @@
|
|
1
1
|
name: identity-cache
|
2
2
|
|
3
3
|
up:
|
4
|
-
- homebrew:
|
5
|
-
- mysql-client@5.7:
|
6
|
-
or: [mysql@5.7]
|
7
|
-
conflicts: [mysql-connector-c, mysql, mysql-client]
|
8
4
|
- ruby
|
9
|
-
- isogun
|
10
5
|
- bundler
|
11
|
-
|
12
|
-
|
13
|
-
RAILGUN_HOST: identity-cache.railgun
|
14
|
-
MYSQL_HOST: identity-cache.railgun
|
15
|
-
MEMCACHED_HOST: identity-cache.railgun
|
6
|
+
- memcached
|
7
|
+
- mysql
|
16
8
|
|
17
9
|
commands:
|
18
10
|
test:
|
@@ -6,7 +6,7 @@ gem "ar_transaction_changes", "~> 1.1.0"
|
|
6
6
|
gem "activerecord", "~> 7.0.0"
|
7
7
|
gem "mysql2", "~> 0.5"
|
8
8
|
gem "pg", "~> 1.1"
|
9
|
-
gem "memcached", "
|
9
|
+
gem "memcached", github: "Shopify/memcached", branch: "1-0-stable-shopify"
|
10
10
|
gem "memcached_store", "~> 2.3.2"
|
11
11
|
gem "dalli", "~> 2.7.11"
|
12
12
|
gem "cityhash", "~> 0.6.0"
|
data/gemfiles/Gemfile.rails-edge
CHANGED
@@ -5,6 +5,7 @@ gem "activerecord", github: "rails/rails", branch: "main"
|
|
5
5
|
gem "activesupport", github: "rails/rails", branch: "main"
|
6
6
|
gem "mysql2", "~> 0.5"
|
7
7
|
gem "pg", "~> 1.1"
|
8
|
+
gem "memcached", github: "Shopify/memcached", branch: "1-0-stable-shopify"
|
8
9
|
gem "memcached_store"
|
9
10
|
gem "dalli"
|
10
11
|
gem "cityhash"
|
@@ -47,6 +47,10 @@ module IdentityCache
|
|
47
47
|
add_parents_to_cache_expiry_set(parents_to_expire)
|
48
48
|
parents_to_expire.select! { |parent| parent.class.primary_cache_index_enabled }
|
49
49
|
parents_to_expire.reduce(true) do |all_expired, parent|
|
50
|
+
if Thread.current[:idc_deferred_parent_expiration]
|
51
|
+
Thread.current[:idc_parent_records_for_cache_expiry] << parent
|
52
|
+
next parent
|
53
|
+
end
|
50
54
|
parent.expire_primary_index && all_expired
|
51
55
|
end
|
52
56
|
end
|
data/lib/identity_cache.rb
CHANGED
@@ -60,6 +60,8 @@ module IdentityCache
|
|
60
60
|
|
61
61
|
class InverseAssociationError < StandardError; end
|
62
62
|
|
63
|
+
class NestedDeferredParentBlockError < StandardError; end
|
64
|
+
|
63
65
|
class UnsupportedScopeError < StandardError; end
|
64
66
|
|
65
67
|
class UnsupportedAssociationError < StandardError; end
|
@@ -115,27 +117,36 @@ module IdentityCache
|
|
115
117
|
!readonly
|
116
118
|
end
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
pool.
|
120
|
+
# Rails wraps each of your tests in a transaction, so that any changes
|
121
|
+
# made to the database during the test can be rolled back afterwards.
|
122
|
+
# These transactions are flagged as "unjoinable", which tries to make
|
123
|
+
# your application behave as if they weren't there. In particular:
|
124
|
+
#
|
125
|
+
# - Opening another transaction during the test creates a savepoint,
|
126
|
+
# which can be rolled back independently of the main transaction.
|
127
|
+
# - When those nested transactions complete, any `after_commit`
|
128
|
+
# callbacks for records modified during the transaction will run,
|
129
|
+
# even though the changes haven't actually been committed yet.
|
130
|
+
#
|
131
|
+
# By ignoring unjoinable transactions, IdentityCache's behaviour
|
132
|
+
# during your test suite will more closely match production.
|
133
|
+
#
|
134
|
+
# When there are no open transactions, `current_transaction` returns a
|
135
|
+
# special `NullTransaction` object that is unjoinable, meaning we will
|
136
|
+
# use the cache.
|
137
|
+
if ActiveRecord::ConnectionAdapters::ConnectionPool.method_defined?(:active_connection)
|
138
|
+
def should_use_cache? # :nodoc:
|
139
|
+
ActiveRecord::Base.connection_handler.connection_pool_list(ActiveRecord::Base.current_role).none? do |pool|
|
140
|
+
pool.active_connection? &&
|
141
|
+
pool.active_connection.current_transaction.joinable?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
else
|
145
|
+
def should_use_cache? # :nodoc:
|
146
|
+
ActiveRecord::Base.connection_handler.connection_pool_list(ActiveRecord::Base.current_role).none? do |pool|
|
147
|
+
pool.active_connection? &&
|
148
|
+
pool.connection.current_transaction.joinable?
|
149
|
+
end
|
139
150
|
end
|
140
151
|
end
|
141
152
|
|
@@ -191,6 +202,44 @@ module IdentityCache
|
|
191
202
|
result
|
192
203
|
end
|
193
204
|
|
205
|
+
# Executes a block with deferred parent expiration, ensuring that the parent
|
206
|
+
# records' cache expiration is deferred until the block completes. When the block
|
207
|
+
# completes, it triggers expiration of the primary index for the parent records.
|
208
|
+
# Raises a NestedDeferredParentBlockError if a deferred parent expiration block
|
209
|
+
# is already active on the current thread.
|
210
|
+
#
|
211
|
+
# == Parameters:
|
212
|
+
# No parameters.
|
213
|
+
#
|
214
|
+
# == Raises:
|
215
|
+
# NestedDeferredParentBlockError if a deferred parent expiration block is already active.
|
216
|
+
#
|
217
|
+
# == Yield:
|
218
|
+
# Runs the provided block with deferred parent expiration.
|
219
|
+
#
|
220
|
+
# == Returns:
|
221
|
+
# The result of executing the provided block.
|
222
|
+
#
|
223
|
+
# == Ensures:
|
224
|
+
# Cleans up thread-local variables related to deferred parent expiration regardless
|
225
|
+
# of whether the block raises an exception.
|
226
|
+
def with_deferred_parent_expiration
|
227
|
+
raise NestedDeferredParentBlockError if Thread.current[:idc_deferred_parent_expiration]
|
228
|
+
|
229
|
+
Thread.current[:idc_deferred_parent_expiration] = true
|
230
|
+
Thread.current[:idc_parent_records_for_cache_expiry] = Set.new
|
231
|
+
|
232
|
+
result = yield
|
233
|
+
|
234
|
+
Thread.current[:idc_deferred_parent_expiration] = nil
|
235
|
+
Thread.current[:idc_parent_records_for_cache_expiry].each(&:expire_primary_index)
|
236
|
+
|
237
|
+
result
|
238
|
+
ensure
|
239
|
+
Thread.current[:idc_deferred_parent_expiration] = nil
|
240
|
+
Thread.current[:idc_parent_records_for_cache_expiry].clear
|
241
|
+
end
|
242
|
+
|
194
243
|
def with_fetch_read_only_records(value = true)
|
195
244
|
old_value = Thread.current[:identity_cache_fetch_read_only_records]
|
196
245
|
Thread.current[:identity_cache_fetch_read_only_records] = value
|
data/shipit.rubygems.yml
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: identity_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
@@ -11,10 +11,10 @@ authors:
|
|
11
11
|
- Tobias Lutke
|
12
12
|
- Arthur Neves
|
13
13
|
- Francis Bogsanyi
|
14
|
-
autorequire:
|
14
|
+
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2024-
|
17
|
+
date: 2024-08-21 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activerecord
|
@@ -127,7 +127,6 @@ files:
|
|
127
127
|
- gemfiles/Gemfile.min-supported
|
128
128
|
- gemfiles/Gemfile.rails-edge
|
129
129
|
- identity_cache.gemspec
|
130
|
-
- isogun.yml
|
131
130
|
- lib/identity_cache.rb
|
132
131
|
- lib/identity_cache/belongs_to_caching.rb
|
133
132
|
- lib/identity_cache/cache_fetcher.rb
|
@@ -177,7 +176,7 @@ homepage: https://github.com/Shopify/identity_cache
|
|
177
176
|
licenses: []
|
178
177
|
metadata:
|
179
178
|
allowed_push_host: https://rubygems.org
|
180
|
-
post_install_message:
|
179
|
+
post_install_message:
|
181
180
|
rdoc_options: []
|
182
181
|
require_paths:
|
183
182
|
- lib
|
@@ -192,8 +191,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
191
|
- !ruby/object:Gem::Version
|
193
192
|
version: '0'
|
194
193
|
requirements: []
|
195
|
-
rubygems_version: 3.5.
|
196
|
-
signing_key:
|
194
|
+
rubygems_version: 3.5.17
|
195
|
+
signing_key:
|
197
196
|
specification_version: 4
|
198
197
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
199
198
|
at the model level, and adds a number of convenience methods for accessing those
|