File size: 1,644 Bytes
eb1414a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15f1210
 
 
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
"""Async-safe TTL-LRU cache."""

from __future__ import annotations

import asyncio
import hashlib
import json
import time
from collections import OrderedDict

from app.config import cfg


class TTLCache:
    """Async-safe LRU cache with per-entry TTL."""

    def __init__(self, maxsize: int = 256, ttl: int = 3600):
        self._cache: OrderedDict = OrderedDict()
        self._maxsize = maxsize
        self._ttl = ttl
        self._lock = asyncio.Lock()

    def _key(self, *args) -> str:
        payload = json.dumps(args, ensure_ascii=False, sort_keys=True)
        return hashlib.sha256(payload.encode()).hexdigest()[:20]

    async def get(self, *args):
        async with self._lock:
            k = self._key(*args)
            if k in self._cache:
                value, ts = self._cache[k]
                if time.monotonic() - ts < self._ttl:
                    self._cache.move_to_end(k)
                    return value
                del self._cache[k]
        return None

    async def set(self, value, *args):
        async with self._lock:
            k = self._key(*args)
            self._cache[k] = (value, time.monotonic())
            self._cache.move_to_end(k)
            if len(self._cache) > self._maxsize:
                self._cache.popitem(last=False)


search_cache   = TTLCache(maxsize=cfg.CACHE_SIZE, ttl=cfg.CACHE_TTL)
analysis_cache = TTLCache(maxsize=cfg.CACHE_SIZE, ttl=cfg.CACHE_TTL)
rewrite_cache  = TTLCache(maxsize=cfg.CACHE_SIZE, ttl=cfg.CACHE_TTL * 6)
pipeline_cache = TTLCache(maxsize=128,            ttl=cfg.CACHE_TTL)
embed_cache    = TTLCache(maxsize=1024,           ttl=cfg.CACHE_TTL * 12)