|
- # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
- # License: MIT. See LICENSE
-
- import json
-
- import frappe
- from frappe.desk.notifications import clear_notifications, delete_notification_count_for
-
- common_default_keys = ["__default", "__global"]
-
- doctype_map_keys = (
- "energy_point_rule_map",
- "assignment_rule_map",
- "milestone_tracker_map",
- "event_consumer_document_type_map",
- )
-
- bench_cache_keys = ("assets_json",)
-
- global_cache_keys = (
- "app_hooks",
- "installed_apps",
- "all_apps",
- "app_modules",
- "module_app",
- "system_settings",
- "scheduler_events",
- "time_zone",
- "webhooks",
- "active_domains",
- "active_modules",
- "assignment_rule",
- "server_script_map",
- "wkhtmltopdf_version",
- "domain_restricted_doctypes",
- "domain_restricted_pages",
- "information_schema:counts",
- "sitemap_routes",
- "db_tables",
- "server_script_autocompletion_items",
- ) + doctype_map_keys
-
- user_cache_keys = (
- "bootinfo",
- "user_recent",
- "roles",
- "user_doc",
- "lang",
- "defaults",
- "user_permissions",
- "home_page",
- "linked_with",
- "desktop_icons",
- "portal_menu_items",
- "user_perm_can_read",
- "has_role:Page",
- "has_role:Report",
- "desk_sidebar_items",
- )
-
- doctype_cache_keys = (
- "doctype_meta",
- "doctype_form_meta",
- "table_columns",
- "last_modified",
- "linked_doctypes",
- "notifications",
- "workflow",
- "data_import_column_header_map",
- ) + doctype_map_keys
-
-
- def clear_user_cache(user=None):
- cache = frappe.cache()
-
- # this will automatically reload the global cache
- # so it is important to clear this first
- clear_notifications(user)
-
- if user:
- for name in user_cache_keys:
- cache.hdel(name, user)
- cache.delete_keys("user:" + user)
- clear_defaults_cache(user)
- else:
- for name in user_cache_keys:
- cache.delete_key(name)
- clear_defaults_cache()
- clear_global_cache()
-
-
- def clear_domain_cache(user=None):
- cache = frappe.cache()
- domain_cache_keys = ("domain_restricted_doctypes", "domain_restricted_pages")
- cache.delete_value(domain_cache_keys)
-
-
- def clear_global_cache():
- from frappe.website.utils import clear_website_cache
-
- clear_doctype_cache()
- clear_website_cache()
- frappe.cache().delete_value(global_cache_keys)
- frappe.cache().delete_value(bench_cache_keys)
- frappe.setup_module_map()
-
-
- def clear_defaults_cache(user=None):
- if user:
- for p in [user] + common_default_keys:
- frappe.cache().hdel("defaults", p)
- elif frappe.flags.in_install != "frappe":
- frappe.cache().delete_key("defaults")
-
-
- def clear_doctype_cache(doctype=None):
- clear_controller_cache(doctype)
- cache = frappe.cache()
-
- for key in ("is_table", "doctype_modules", "document_cache"):
- cache.delete_value(key)
-
- frappe.local.document_cache = {}
-
- def clear_single(dt):
- for name in doctype_cache_keys:
- cache.hdel(name, dt)
-
- if doctype:
- clear_single(doctype)
-
- # clear all parent doctypes
- for dt in frappe.get_all(
- "DocField", "parent", dict(fieldtype=["in", frappe.model.table_fields], options=doctype)
- ):
- 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)
- ):
- clear_single(dt.dt)
-
- # clear all notifications
- delete_notification_count_for(doctype)
-
- else:
- # clear all
- for name in doctype_cache_keys:
- cache.delete_value(name)
-
-
- def clear_controller_cache(doctype=None):
- if not doctype:
- del frappe.controllers
- frappe.controllers = {}
- return
-
- for site_controllers in frappe.controllers.values():
- site_controllers.pop(doctype, None)
-
-
- def get_doctype_map(doctype, name, filters=None, order_by=None):
- cache = frappe.cache()
- cache_key = frappe.scrub(doctype) + "_map"
- doctype_map = cache.hget(cache_key, name)
-
- if doctype_map is not None:
- # cached, return
- items = json.loads(doctype_map)
- else:
- # non cached, build cache
- try:
- items = frappe.get_all(doctype, filters=filters, order_by=order_by)
- cache.hset(cache_key, name, json.dumps(items))
- except frappe.db.TableMissingError:
- # executed from inside patch, ignore
- items = []
-
- return items
-
-
- def clear_doctype_map(doctype, name):
- frappe.cache().hdel(frappe.scrub(doctype) + "_map", name)
-
-
- def build_table_count_cache():
- if (
- frappe.flags.in_patch
- or frappe.flags.in_install
- or frappe.flags.in_migrate
- or frappe.flags.in_import
- or frappe.flags.in_setup_wizard
- ):
- return
-
- _cache = frappe.cache()
- table_name = frappe.qb.Field("table_name").as_("name")
- table_rows = frappe.qb.Field("table_rows").as_("count")
- information_schema = frappe.qb.Schema("information_schema")
-
- data = (frappe.qb.from_(information_schema.tables).select(table_name, table_rows)).run(
- as_dict=True
- )
- counts = {d.get("name").replace("tab", "", 1): d.get("count", None) for d in data}
- _cache.set_value("information_schema:counts", counts)
-
- return counts
-
-
- def build_domain_restriced_doctype_cache(*args, **kwargs):
- if (
- frappe.flags.in_patch
- or frappe.flags.in_install
- or frappe.flags.in_migrate
- or frappe.flags.in_import
- or frappe.flags.in_setup_wizard
- ):
- return
- _cache = frappe.cache()
- active_domains = frappe.get_active_domains()
- doctypes = frappe.get_all("DocType", filters={"restrict_to_domain": ("IN", active_domains)})
- doctypes = [doc.name for doc in doctypes]
- _cache.set_value("domain_restricted_doctypes", doctypes)
-
- return doctypes
-
-
- def build_domain_restriced_page_cache(*args, **kwargs):
- if (
- frappe.flags.in_patch
- or frappe.flags.in_install
- or frappe.flags.in_migrate
- or frappe.flags.in_import
- or frappe.flags.in_setup_wizard
- ):
- return
- _cache = frappe.cache()
- active_domains = frappe.get_active_domains()
- pages = frappe.get_all("Page", filters={"restrict_to_domain": ("IN", active_domains)})
- pages = [page.name for page in pages]
- _cache.set_value("domain_restricted_pages", pages)
-
- return pages
|