File size: 1,799 Bytes
a9710f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2ea771
a9710f3
 
 
c2ea771
a9710f3
 
 
 
 
 
 
 
 
 
c2ea771
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import hashlib
from datetime import datetime, timedelta
from typing import Any

from pydantic import BaseModel

from cbh.api.common.models import CacheEntryModel
from cbh.core.config import settings
from cbh.core.wrappers import background_task


def build_cache_key(*parts: Any) -> str:
    raw = "|".join("" if part is None else str(part) for part in parts)
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()


def _serialize(value: Any) -> Any:
    if isinstance(value, BaseModel):
        return value.model_dump(mode="json")
    if isinstance(value, list):
        return [_serialize(item) for item in value]
    if isinstance(value, dict):
        return {key: _serialize(item) for key, item in value.items()}
    return value


async def get_cache(namespace: str, key: str) -> Any | None:
    entry = await settings.DB_CLIENT.caches.find_one({"namespace": namespace, "key": key})
    if not entry:
        return None
    deleted_at = entry.get("deletedAt")
    if isinstance(deleted_at, datetime) and deleted_at < datetime.now():
        return None
    return entry.get("value")


async def set_cache(
    namespace: str,
    key: str,
    value: Any,
    ttl_seconds: int | None = None,
) -> None:
    ttl = ttl_seconds if ttl_seconds is not None else settings.LINE_CHECK_CACHE_TTL_SECONDS
    document = CacheEntryModel(
        namespace=namespace,
        key=key,
        value=_serialize(value),
    ).to_mongo()
    document["deletedAt"] = datetime.now() + timedelta(seconds=ttl)
    await settings.DB_CLIENT.caches.update_one(
        {"namespace": namespace, "key": key},
        {"$set": document},
        upsert=True,
    )


@background_task()
async def invalidate_line_check_cache() -> None:
    await settings.DB_CLIENT.caches.delete_many({"namespace": "linecheck"})