File size: 1,389 Bytes
9459cd0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Cache layer: avoids re-downloading the same URL twice.
Key = SHA256(url). Cache index kept as a flat JSON file so it survives restarts.
"""
import hashlib
import json
import os
import threading

CACHE_DIR = "cache"
INDEX_PATH = os.path.join(CACHE_DIR, "index.json")
_lock = threading.Lock()


def _url_hash(url: str) -> str:
    return hashlib.sha256(url.encode("utf-8")).hexdigest()


def _load_index() -> dict:
    if not os.path.exists(INDEX_PATH):
        return {}
    with open(INDEX_PATH, "r") as f:
        return json.load(f)


def _save_index(index: dict):
    os.makedirs(CACHE_DIR, exist_ok=True)
    tmp = INDEX_PATH + ".tmp"
    with open(tmp, "w") as f:
        json.dump(index, f, indent=2)
    os.replace(tmp, INDEX_PATH)  # atomic write, avoids torn reads


def get_cached_path(url: str) -> str | None:
    with _lock:
        index = _load_index()
        entry = index.get(_url_hash(url))
        if entry and os.path.exists(entry["path"]):
            return entry["path"]
        return None


def register_cache(url: str, local_path: str):
    with _lock:
        index = _load_index()
        index[_url_hash(url)] = {"url": url, "path": local_path}
        _save_index(index)


def cache_path_for(url: str, ext: str) -> str:
    os.makedirs(os.path.join(CACHE_DIR, "files"), exist_ok=True)
    return os.path.join(CACHE_DIR, "files", f"{_url_hash(url)}{ext}")