fix: clear cache and prevent data access after DocType deletion (#34307)

* fix: clear cache and prevent data access after DocType deletion

* fix: Handle potential DB failures during migrate

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
Aarol D'Souza 2025-10-10 13:30:51 +05:30 committed by GitHub
parent 598ba6d63d
commit 4ecb9bc57d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 35 additions and 12 deletions

View file

@ -147,17 +147,26 @@ def _clear_doctype_cache_from_redis(doctype: str | None = None):
clear_single(doctype)
# clear all parent doctypes
try:
for dt in frappe.get_all(
"DocField", "parent", dict(fieldtype=["in", frappe.model.table_fields], options=doctype)
"DocField",
"parent",
dict(fieldtype=["in", frappe.model.table_fields], options=doctype),
ignore_ddl=True,
):
clear_single(dt.parent)
# clear all parent doctypes
if not frappe.flags.in_install:
for dt in frappe.get_all(
"Custom Field", "dt", dict(fieldtype=["in", frappe.model.table_fields], options=doctype)
"Custom Field",
"dt",
dict(fieldtype=["in", frappe.model.table_fields], options=doctype),
ignore_ddl=True,
):
clear_single(dt.dt)
except frappe.DoesNotExistError:
pass # core doctypes getting migrated.
# clear all notifications
delete_notification_count_for(doctype)

View file

@ -856,6 +856,16 @@ class TestDocType(IntegrationTestCase):
)
self.assertRaises(frappe.ValidationError, doctype.insert)
def test_delete_doc_clears_cache(self):
dt = new_doctype(
fields=[{"fieldname": "test_fdname", "fieldtype": "Data", "label": "Test Field"}],
).insert()
frappe.get_meta(dt.name)
frappe.delete_doc("DocType", dt.name, force=1, delete_permanently=False)
frappe.db.commit()
with self.assertRaises(frappe.DoesNotExistError):
frappe.get_meta(dt.name)
def new_doctype(
name: str | None = None,

View file

@ -144,6 +144,8 @@ def delete_doc(
# in case a doctype doesnt have any controller code nor any app and module
pass
frappe.clear_cache(doctype=name)
else:
# Lock the doc without waiting
try:

View file

@ -32,6 +32,7 @@ class TestFixtureImport(IntegrationTestCase):
self.assertFalse(frappe.db.exists("DocType", "temp_doctype"))
self.create_new_doctype("temp_doctype")
frappe.db.commit()
dummy_name_list = ["jhon", "jane"]
path_to_exported_fixtures = self.insert_dummy_data_and_export("temp_doctype", dummy_name_list)
@ -39,9 +40,6 @@ class TestFixtureImport(IntegrationTestCase):
import_doc(path_to_exported_fixtures)
delete_doc("DocType", "temp_doctype", delete_permanently=True)
os.remove(path_to_exported_fixtures)
self.assertEqual(frappe.db.count("temp_doctype"), len(dummy_name_list))
data = frappe.get_all("temp_doctype", "member_name")
@ -53,6 +51,10 @@ class TestFixtureImport(IntegrationTestCase):
self.assertEqual(set(dummy_name_list), imported_data)
delete_doc("DocType", "temp_doctype", delete_permanently=True)
frappe.db.commit()
os.remove(path_to_exported_fixtures)
def test_singles_fixtures_import(self):
self.assertFalse(frappe.db.exists("DocType", "temp_singles"))