mirror of
https://github.com/inventree/InvenTree.git
synced 2025-11-30 01:10:00 +00:00
Implement caching for unit registry: (#10870)
* Implement caching for unit registry: - Registry could become out of sync across sessions - Implement a simple caching system * Simplify code
This commit is contained in:
@@ -2,30 +2,76 @@
|
||||
|
||||
import logging
|
||||
import re
|
||||
from hashlib import md5
|
||||
from typing import Optional
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import pint
|
||||
|
||||
_unit_registry = None
|
||||
|
||||
import structlog
|
||||
|
||||
from common.settings import get_global_setting, set_global_setting
|
||||
from InvenTree.cache import get_session_cache, set_session_cache
|
||||
|
||||
_UNIT_REG_CACHE_KEY = 'unit_registry_hash'
|
||||
_unit_registry = None
|
||||
_unit_registry_hash: str = ''
|
||||
|
||||
logger = structlog.get_logger('inventree')
|
||||
|
||||
# Disable log output for Pint library
|
||||
logging.getLogger('pint').setLevel(logging.ERROR)
|
||||
|
||||
|
||||
def get_unit_registry_hash():
|
||||
"""Return a hash representing the current state of the unit registry.
|
||||
|
||||
We use this to determine if we need to reload the unit registry,
|
||||
due to changes in the database.
|
||||
"""
|
||||
# Look in the session cache first (faster, and potentially newer)
|
||||
registry_hash = get_session_cache(_UNIT_REG_CACHE_KEY)
|
||||
|
||||
if registry_hash is None:
|
||||
registry_hash = get_global_setting(
|
||||
'_UNIT_REGISTRY_HASH', create=False, backup_value=''
|
||||
)
|
||||
|
||||
if registry_hash:
|
||||
set_session_cache(_UNIT_REG_CACHE_KEY, registry_hash)
|
||||
|
||||
return registry_hash
|
||||
|
||||
|
||||
def set_unit_registry_hash(registry_hash: str):
|
||||
"""Save the hash representing the current state of the unit registry.
|
||||
|
||||
Because most of the registry is static, we only need to consider the
|
||||
CustomUnit entries in the database.
|
||||
"""
|
||||
global _unit_registry_hash
|
||||
_unit_registry_hash = registry_hash
|
||||
|
||||
# Save to both the global settings and the session cache
|
||||
set_global_setting('_UNIT_REGISTRY_HASH', registry_hash)
|
||||
set_session_cache(_UNIT_REG_CACHE_KEY, registry_hash)
|
||||
|
||||
|
||||
def get_unit_registry():
|
||||
"""Return a custom instance of the Pint UnitRegistry."""
|
||||
global _unit_registry
|
||||
global _unit_registry_hash
|
||||
|
||||
# Cache the unit registry for speedier access
|
||||
if _unit_registry is None:
|
||||
return reload_unit_registry()
|
||||
|
||||
# Check if the unit registry has changed
|
||||
if _unit_registry_hash != get_unit_registry_hash():
|
||||
logger.info('Unit registry hash has changed, reloading unit registry')
|
||||
return reload_unit_registry()
|
||||
|
||||
return _unit_registry
|
||||
|
||||
|
||||
@@ -60,9 +106,16 @@ def reload_unit_registry():
|
||||
try:
|
||||
from common.models import CustomUnit
|
||||
|
||||
# Calculate a hash of all custom units
|
||||
hash_md5 = md5()
|
||||
|
||||
for cu in CustomUnit.objects.all():
|
||||
try:
|
||||
reg.define(cu.fmt_string())
|
||||
fmt = cu.fmt_string()
|
||||
reg.define(fmt)
|
||||
|
||||
hash_md5.update(fmt.encode('utf-8'))
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(
|
||||
'Failed to load custom unit: %s - %s', cu.fmt_string(), e
|
||||
@@ -71,6 +124,9 @@ def reload_unit_registry():
|
||||
# Once custom units are loaded, save registry
|
||||
_unit_registry = reg
|
||||
|
||||
# Update the unit registry hash
|
||||
set_unit_registry_hash(hash_md5.hexdigest())
|
||||
|
||||
except Exception:
|
||||
# Database is not ready, or CustomUnit model is not available
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user