44 lines
1.2 KiB
Python
44 lines
1.2 KiB
Python
"""Key-Value settings store with Redis projection."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from sqlalchemy import JSON, String
|
|
from sqlalchemy.orm import Mapped, Session, mapped_column
|
|
|
|
from core.db import Base
|
|
from core.events import event_bus
|
|
from core.redis_client import redis_client
|
|
|
|
|
|
class Setting(Base):
|
|
__tablename__ = "settings"
|
|
|
|
key: Mapped[str] = mapped_column(String(128), primary_key=True)
|
|
value: Mapped[dict] = mapped_column(JSON)
|
|
|
|
|
|
def get_setting(db: Session, key: str, default: Any = None) -> Any:
|
|
row = db.get(Setting, key)
|
|
return row.value.get("v") if row else default
|
|
|
|
|
|
def set_setting(db: Session, key: str, value: Any) -> None:
|
|
row = db.get(Setting, key)
|
|
if row:
|
|
row.value = {"v": value}
|
|
else:
|
|
row = Setting(key=key, value={"v": value})
|
|
db.add(row)
|
|
db.commit()
|
|
redis_client.set(f"setting:{key}", json.dumps(value))
|
|
event_bus.publish("core.settings_updated", {"key": key, "value": value}, db=db)
|
|
|
|
|
|
def get_setting_cached(key: str, default: Any = None) -> Any:
|
|
raw = redis_client.get(f"setting:{key}")
|
|
if raw is None:
|
|
return default
|
|
return json.loads(raw)
|