[IMP] base: cover filestore gc with tests
closes odoo/odoo#96242 Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
committed by
Julien Castiaux
parent
ea85539c9b
commit
4ec4ca4a83
@@ -174,6 +174,12 @@ class IrAttachment(models.Model):
|
||||
cr.execute("SET LOCAL lock_timeout TO '10s'")
|
||||
cr.execute("LOCK ir_attachment IN SHARE MODE")
|
||||
|
||||
self._gc_file_store_unsafe()
|
||||
|
||||
# commit to release the lock
|
||||
cr.commit()
|
||||
|
||||
def _gc_file_store_unsafe(self):
|
||||
# retrieve the file names from the checklist
|
||||
checklist = {}
|
||||
for dirpath, _, filenames in os.walk(self._full_path('checklist')):
|
||||
@@ -185,10 +191,10 @@ class IrAttachment(models.Model):
|
||||
# Clean up the checklist. The checklist is split in chunks and files are garbage-collected
|
||||
# for each chunk.
|
||||
removed = 0
|
||||
for names in cr.split_for_in_conditions(checklist):
|
||||
for names in self.env.cr.split_for_in_conditions(checklist):
|
||||
# determine which files to keep among the checklist
|
||||
cr.execute("SELECT store_fname FROM ir_attachment WHERE store_fname IN %s", [names])
|
||||
whitelist = set(row[0] for row in cr.fetchall())
|
||||
self.env.cr.execute("SELECT store_fname FROM ir_attachment WHERE store_fname IN %s", [names])
|
||||
whitelist = set(row[0] for row in self.env.cr.fetchall())
|
||||
|
||||
# remove garbage files, and clean up checklist
|
||||
for fname in names:
|
||||
@@ -203,8 +209,6 @@ class IrAttachment(models.Model):
|
||||
with tools.ignore(OSError):
|
||||
os.unlink(filepath)
|
||||
|
||||
# commit to release the lock
|
||||
cr.commit()
|
||||
_logger.info("filestore gc %d checked, %d removed", len(checklist), removed)
|
||||
|
||||
@api.depends('store_fname', 'db_datas', 'file_size')
|
||||
|
||||
@@ -7,6 +7,7 @@ import os
|
||||
|
||||
from PIL import Image
|
||||
|
||||
import odoo
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tools import image_to_base64
|
||||
@@ -231,6 +232,34 @@ class TestIrAttachment(TransactionCase):
|
||||
self.assertEqual(document3.store_fname, self.blob1_fname)
|
||||
self.assertEqual(document3.checksum, self.blob1_hash)
|
||||
|
||||
def test_12_gc(self):
|
||||
# the data needs to be unique so that no other attachment link
|
||||
# the file so that the gc removes it
|
||||
unique_blob = os.urandom(16)
|
||||
a1 = self.Attachment.create({'name': 'a1', 'raw': unique_blob})
|
||||
store_path = os.path.join(self.filestore, a1.store_fname)
|
||||
self.assertTrue(os.path.isfile(store_path), 'file exists')
|
||||
a1.unlink()
|
||||
self.Attachment._gc_file_store_unsafe()
|
||||
self.assertFalse(os.path.isfile(store_path), 'file removed')
|
||||
|
||||
def test_13_rollback(self):
|
||||
self.registry.enter_test_mode(self.cr)
|
||||
self.addCleanup(self.registry.leave_test_mode)
|
||||
self.cr = self.registry.cursor()
|
||||
self.addCleanup(self.cr.close)
|
||||
self.env = odoo.api.Environment(self.cr, odoo.SUPERUSER_ID, {})
|
||||
|
||||
# the data needs to be unique so that no other attachment link
|
||||
# the file so that the gc removes it
|
||||
unique_blob = os.urandom(16)
|
||||
a1 = self.Attachment.create({'name': 'a1', 'raw': unique_blob})
|
||||
store_path = os.path.join(self.filestore, a1.store_fname)
|
||||
self.assertTrue(os.path.isfile(store_path), 'file exists')
|
||||
self.env.cr.rollback()
|
||||
self.Attachment._gc_file_store_unsafe()
|
||||
self.assertFalse(os.path.isfile(store_path), 'file removed')
|
||||
|
||||
|
||||
class TestPermissions(TransactionCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user