Applying something basic like `order id like xyz` filter can result in
full table scan on years of data. This isn't necessary most of the time.
Interactive queries are usually done on recent data, so add this filter
to ensure only recent data is checked first.
Users can remove this filter if they want to.
Steps to reproduce:
- enable developer mode (doesn't happen in prod)
- Save a document with set only once fields
- Reload the page (requests meta again which is now polluted)
This is new category of bug surfaced because meta objects now live
longer than request and all kinds of weird `self._cached_property`
starts getting serialized.
Co-Authored-By: ruthra kumar <ruthra@erpnext.com>
* fix: meta
* fix: test case
save is required:
1. Fetch values
```python
def get_invalid_links(self, is_submittable=False):
"""Return list of invalid links and also update fetch values if not set."""
...
```
2. Is triggered by
```python
def _validate_links(self):
if self.flags.ignore_links or self._action == "cancel":
return
...
```
3. Which is triggered by either `_save` or `insert`
----
`reload` does not trigger link fetch
```python
def reload(self) -> "Self":
"""Reload document from database"""
return self.load_from_db()
```
Neither does the new calling path which does not excempt Document
from caching when initializing meta.
It can be proven that this revert would be an alternative fix. But this
seems design by accident and there's no preceivable reason to excempt
Document args from being cached normally.
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index c4321f0128..87452c812c 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -70,11 +70,10 @@ def get_meta(doctype: str | dict | DocRef, cached=True) -> "_Meta":
Returns:
Meta object for the given doctype.
"""
- if cached and (
- doctype_name := getattr(doctype, "doctype", doctype)
- if not isinstance(doctype, dict)
- else doctype.get("doctype")
- ):
+ if cached and not isinstance(doctype, Document):
+ doctype_name = (
+ getattr(doctype, "doctype", doctype) if not isinstance(doctype, dict) else doctype.get("doctype")
+ )
if meta := frappe.cache.hget("doctype_meta", doctype_name):
return meta
Therefore, we comply the test.
* refactor: improve maintainability with a simple dispatcher
* refactor: improve maintainability with a init dispatcher on Document
* refactor: improve maintainability with an init dispatcher on meta