iknow_view_models 3.10.0 → 3.10.1
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 417eb3615156fa48cf438ead03e2ea33e323c5baa7d411b1e0fafcea5050acb1
|
4
|
+
data.tar.gz: cdede3ad865389a0d006725819595aec6da1ea417e9d061452ef3198a39af3d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ada26778b54ffb60a825d408fe40f05c8a4aa93cbac7b5519b2338b5afb4cadfda0d1eb7b359b65584f88fbb9cadea4a35a7d2ba0aad9fb8e4d8ec9d5f894e03
|
7
|
+
data.tar.gz: b70d2b42d4a599c3d284dbb96c4506c8ff7b6104108ebcb7126c554fcd671eb0bad04dc4df5a1006f76af272a71c5ca46f54736bf4961821dd7f22160d46fada
|
@@ -30,8 +30,21 @@ class ViewModel::ActiveRecord::Cache
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def render_from_cache(viewmodel_class, ids, initial_viewmodels: nil, migration_versions: {}, locked: false, serialize_context: viewmodel_class.new_serialize_context)
|
33
|
-
|
34
|
-
|
33
|
+
ignore_existing = false
|
34
|
+
begin
|
35
|
+
worker = CacheWorker.new(migration_versions: migration_versions, serialize_context: serialize_context, ignore_existing: ignore_existing)
|
36
|
+
worker.render_from_cache(viewmodel_class, ids, initial_viewmodels: initial_viewmodels, locked: locked)
|
37
|
+
rescue StaleCachedReference
|
38
|
+
# If the cache contents contained a unresolvable stale reference, retry
|
39
|
+
# while ignoring existing cached values (thereby updating the cache). This
|
40
|
+
# will have the side-effect of duplicate Before/AfterVisit callbacks.
|
41
|
+
if ignore_existing
|
42
|
+
raise
|
43
|
+
else
|
44
|
+
ignore_existing = true
|
45
|
+
retry
|
46
|
+
end
|
47
|
+
end
|
35
48
|
end
|
36
49
|
end
|
37
50
|
|
@@ -76,18 +89,25 @@ class ViewModel::ActiveRecord::Cache
|
|
76
89
|
migration_versions: migration_versions, serialize_context: serialize_context)
|
77
90
|
end
|
78
91
|
|
92
|
+
class StaleCachedReference < StandardError
|
93
|
+
def initialize(error)
|
94
|
+
super("Cached value contained stale reference: #{error.message}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
79
98
|
class CacheWorker
|
80
99
|
SENTINEL = Object.new
|
81
100
|
WorklistEntry = Struct.new(:ref_name, :viewmodel)
|
82
101
|
|
83
102
|
attr_reader :migration_versions, :serialize_context, :resolved_references
|
84
103
|
|
85
|
-
def initialize(migration_versions:, serialize_context:)
|
104
|
+
def initialize(migration_versions:, serialize_context:, ignore_existing: false)
|
86
105
|
@worklist = {} # Hash[type_name, Hash[id, WorklistEntry]]
|
87
106
|
@resolved_references = {} # Hash[refname, json]
|
88
107
|
@migration_versions = migration_versions
|
89
108
|
@migrated_cache_versions = {}
|
90
109
|
@serialize_context = serialize_context
|
110
|
+
@ignore_existing = ignore_existing
|
91
111
|
end
|
92
112
|
|
93
113
|
def render_from_cache(viewmodel_class, ids, initial_viewmodels: nil, locked: false)
|
@@ -104,7 +124,7 @@ class ViewModel::ActiveRecord::Cache
|
|
104
124
|
|
105
125
|
ids_to_render = ids.to_set
|
106
126
|
|
107
|
-
if viewmodel_class < CacheableView
|
127
|
+
if viewmodel_class < CacheableView && !@ignore_existing
|
108
128
|
# Load existing serializations from the cache
|
109
129
|
cached_serializations = load_from_cache(viewmodel_class.viewmodel_cache, ids)
|
110
130
|
cached_serializations.each do |id, data|
|
@@ -168,7 +188,7 @@ class ViewModel::ActiveRecord::Cache
|
|
168
188
|
@resolved_references[entry.ref_name] = SENTINEL
|
169
189
|
end
|
170
190
|
|
171
|
-
if viewmodel_class < CacheableView
|
191
|
+
if viewmodel_class < CacheableView && !@ignore_existing
|
172
192
|
cached_serializations = load_from_cache(viewmodel_class.viewmodel_cache, required_entries.keys)
|
173
193
|
cached_serializations.each do |id, data|
|
174
194
|
ref_name = required_entries.delete(id).ref_name
|
@@ -181,8 +201,18 @@ class ViewModel::ActiveRecord::Cache
|
|
181
201
|
h[id] = entry.viewmodel if entry.viewmodel
|
182
202
|
end
|
183
203
|
|
184
|
-
viewmodels =
|
185
|
-
|
204
|
+
viewmodels =
|
205
|
+
begin
|
206
|
+
find_and_preload_viewmodels(viewmodel_class, required_entries.keys,
|
207
|
+
available_viewmodels: available_viewmodels)
|
208
|
+
rescue ViewModel::DeserializationError::NotFound => e
|
209
|
+
# We encountered a reference to an entity that does not exist.
|
210
|
+
# If this reference was potentially found in cached data, it
|
211
|
+
# could be stale: we can retry without using the cache.
|
212
|
+
# If the reference was obtained directly, it indicates invalid
|
213
|
+
# data such as an invalid foreign key, and we cannot recover.
|
214
|
+
raise StaleCachedReference.new(e)
|
215
|
+
end
|
186
216
|
|
187
217
|
loaded_serializations = serialize_and_cache(viewmodels)
|
188
218
|
loaded_serializations.each do |id, data|
|
@@ -209,11 +209,27 @@ class ViewModel::ActiveRecord
|
|
209
209
|
end
|
210
210
|
|
211
211
|
it 'returns the right serialization with provided locked initial viewmodel' do
|
212
|
-
locked_root_view = viewmodel_class.new(model_class.lock(
|
212
|
+
locked_root_view = viewmodel_class.new(model_class.lock('FOR SHARE').find(root.id))
|
213
213
|
fetched_result = parse_result(fetch_with_cache(initial_viewmodels: [locked_root_view], locked: true))
|
214
214
|
|
215
215
|
value(fetched_result).must_equal(serialize_from_database)
|
216
216
|
end
|
217
|
+
|
218
|
+
it 'handles a stale cached reference' do
|
219
|
+
# Fetch to populate the cache
|
220
|
+
initial_result = parse_result(fetch_with_cache)
|
221
|
+
value(initial_result).must_equal(serialize_from_database)
|
222
|
+
|
223
|
+
# Destroy the shared child and its cache without invalidating the cached parent cache
|
224
|
+
root.update_columns(shared_id: nil)
|
225
|
+
shared.destroy!
|
226
|
+
shared_viewmodel_class.viewmodel_cache.clear
|
227
|
+
|
228
|
+
fetched_result = parse_result(fetch_with_cache)
|
229
|
+
value(fetched_result).must_equal(serialize_from_database)
|
230
|
+
fetched_view = fetched_result.first.first
|
231
|
+
value(fetched_view['shared']).must_be_nil
|
232
|
+
end
|
217
233
|
end
|
218
234
|
|
219
235
|
describe 'with migrations' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iknow_view_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.10.
|
4
|
+
version: 3.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iKnow Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|