Skip to content

Commit

Permalink
[FIX] fs_file: Invalidate cache on write
Browse files Browse the repository at this point in the history
When a new value is assigned to a stored FSFile field, the cache must be invalidated and not contain the given value. This is required since when you access a stored FSFile field, teh FSFileValue returned must be linked to the attachment used to store the file in the storage
  • Loading branch information
lmignon committed Oct 22, 2023
1 parent 0396c9a commit 6b2b6d6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
20 changes: 18 additions & 2 deletions fs_file/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,16 @@ def write(self, records, value):
# determine records that are known to be not null
not_null = cache.get_records_different_from(records, self, None)

cache.update(records, self, itertools.repeat(cache_value))

if self.store:
# Be sure to invalidate the cache for the modified records since
# the value of the field has changed and the new value will be linked
# to the attachment record used to store the file in the storage.
cache.remove(records, self)
else:
# if the field is not stored and a value is set, we need to
# set the value in the cache since the value (the case for computed
# fields)
cache.update(records, self, itertools.repeat(cache_value))
# retrieve the attachments that store the values, and adapt them
if self.store and any(records._ids):
real_records = records.filtered("id")
Expand All @@ -353,6 +361,14 @@ def write(self, records, value):
# update the existing attachments
atts.write({"raw": content, "name": filename})
atts_records = records.browse(atts.mapped("res_id"))
# set new value in the cache since we have the reference to the
# attachment record and a new access to the field will nomore
# require to load the attachment record
for record in atts_records:
new_cache_value = self._convert_attachment_to_cache(
atts.filtered(lambda att: att.res_id == record.id)
)
cache.update(record, self, [new_cache_value], dirty=False)
# create the missing attachments
missing = real_records - atts_records
if missing:
Expand Down
14 changes: 14 additions & 0 deletions fs_file/tests/test_fs_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,17 @@ def test_fs_value_mimetype(self):
# from the content
value = FSFileValue(name="test", value=self.png_content)
self.assertEqual(value.mimetype, "image/png")

def test_cache_invalidation(self):
"""Test that the cache is invalidated when the FSFileValue is modified
When we assign a FSFileValue to a field, the value in the cache must
be invalidated and the new value must be computed. This is required
because the FSFileValue from the cache should always be linked to the
attachment record used to store the file in the storage.
"""
value = FSFileValue(name="test.png", value=self.create_content)
instance = self.env["test.model"].create({"fs_file": value})
self.assertNotEqual(instance.fs_file, value)
value = FSFileValue(name="test.png", value=self.write_content)
instance.write({"fs_file": value})
self.assertNotEqual(instance.fs_file, value)

0 comments on commit 6b2b6d6

Please sign in to comment.