91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
import logging
|
|
|
|
from molodetz.cache import TTLCache
|
|
from molodetz.constants import SETTINGS_DEFAULTS
|
|
from molodetz.database.core import db, now_iso
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_settings_cache = TTLCache(ttl=60, max_size=100)
|
|
_version_cache = TTLCache(ttl=1, max_size=100)
|
|
_local_versions = {}
|
|
|
|
|
|
def read_cache_version(name):
|
|
cached = _version_cache.get(name)
|
|
if cached is not None:
|
|
return cached
|
|
try:
|
|
if "cache_state" not in db.tables:
|
|
return 0
|
|
row = db["cache_state"].find_one(name=name)
|
|
version = int(row["version"]) if row else 0
|
|
except Exception as exc:
|
|
logger.warning("cache version read failed for %s: %s", name, exc)
|
|
return 0
|
|
_version_cache.set(name, version)
|
|
return version
|
|
|
|
|
|
def sync_local_cache(name, cache):
|
|
version = read_cache_version(name)
|
|
if _local_versions.get(name) != version:
|
|
cache.clear()
|
|
_local_versions[name] = version
|
|
|
|
|
|
def bump_cache_version(name, cache=None):
|
|
try:
|
|
with db:
|
|
db.query(
|
|
"INSERT INTO cache_state (name, version, updated_at) VALUES (:name, 1, :stamp) "
|
|
"ON CONFLICT(name) DO UPDATE SET version = version + 1, updated_at = excluded.updated_at",
|
|
name=name,
|
|
stamp=now_iso(),
|
|
)
|
|
except Exception as exc:
|
|
logger.warning("cache version bump failed for %s: %s", name, exc)
|
|
_version_cache.pop(name)
|
|
if cache is not None:
|
|
cache.clear()
|
|
_local_versions.pop(name, None)
|
|
|
|
|
|
def get_setting(key, default=None):
|
|
if default is None:
|
|
default = SETTINGS_DEFAULTS.get(key, "")
|
|
sync_local_cache("settings", _settings_cache)
|
|
cached = _settings_cache.get(key)
|
|
if cached is not None:
|
|
return cached
|
|
value = default
|
|
if "site_settings" in db.tables:
|
|
row = db["site_settings"].find_one(key=key)
|
|
if row is not None and row.get("value") is not None:
|
|
value = str(row["value"])
|
|
_settings_cache.set(key, value)
|
|
return value
|
|
|
|
|
|
def get_int_setting(key, default):
|
|
try:
|
|
return int(get_setting(key, str(default)))
|
|
except (TypeError, ValueError):
|
|
return default
|
|
|
|
|
|
def set_setting(key, value):
|
|
table = db["site_settings"]
|
|
stamp = now_iso()
|
|
with db:
|
|
if table.find_one(key=key) is None:
|
|
table.insert({"uid": f"setting_{key}", "key": key, "value": str(value), "updated_at": stamp})
|
|
else:
|
|
table.update({"key": key, "value": str(value), "updated_at": stamp}, ["key"])
|
|
bump_cache_version("settings", _settings_cache)
|
|
|
|
|
|
def all_settings():
|
|
return {key: get_setting(key, default) for key, default in SETTINGS_DEFAULTS.items()}
|