mirror of
https://github.com/migatu/astrololo.git
synced 2026-07-14 13:34:38 +00:00
16d35c16dc
Trzy niezależne usługi FastAPI komunikujące się przez HTTP/JSON, każda zna tylko adres warstwy bezpośrednio pod nią: - presentation (:8000) — strona WWW + formularz - logic (:8001) — reguły biznesowe, pośrednik - data (:8002) — wyszukiwanie danych za interfejsem DataProvider Warstwa danych: czytanie setek plików .xlsx z wykrywaniem nagłówka i mapowaniem układu kolumn na schemat kanoniczny, z 4-poziomowym cache (schemat L1, Parquet L2, wyniki zapytań L3, odwrócony indeks L4) i unieważnianiem po odcisku pliku. Gotowa ścieżka migracji do SQL (ingest/to_sql.py + SqlDataProvider, przełączane przez DATA_PROVIDER). Zawiera docker-compose, Makefile, generator danych przykładowych. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
1.5 KiB
Python
46 lines
1.5 KiB
Python
"""Cache schematu: wykryty wiersz nagłówka + mapowanie kolumn, per (plik, arkusz).
|
|
|
|
POZIOM 1 cache. Najdroższe jest samo wykrywanie nagłówka i wnioskowanie układu
|
|
kolumn. Robimy to RAZ na wersję pliku i zapisujemy w SQLite. Kolejne odczyty
|
|
pomijają skanowanie.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
|
|
class SchemaCache:
|
|
def __init__(self, cache_dir: Path) -> None:
|
|
self._db = sqlite3.connect(str(cache_dir / "schema.db"), check_same_thread=False)
|
|
self._db.execute(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS schema_cache (
|
|
fingerprint TEXT,
|
|
sheet TEXT,
|
|
header_row INTEGER,
|
|
mapping TEXT,
|
|
PRIMARY KEY (fingerprint, sheet)
|
|
)
|
|
"""
|
|
)
|
|
self._db.commit()
|
|
|
|
def get(self, fp: str, sheet: str) -> tuple[int, dict[str, str]] | None:
|
|
cur = self._db.execute(
|
|
"SELECT header_row, mapping FROM schema_cache WHERE fingerprint=? AND sheet=?",
|
|
(fp, sheet),
|
|
)
|
|
row = cur.fetchone()
|
|
if row is None:
|
|
return None
|
|
return int(row[0]), json.loads(row[1])
|
|
|
|
def put(self, fp: str, sheet: str, header_row: int, mapping: dict[str, str]) -> None:
|
|
self._db.execute(
|
|
"INSERT OR REPLACE INTO schema_cache VALUES (?,?,?,?)",
|
|
(fp, sheet, header_row, json.dumps(mapping, ensure_ascii=False)),
|
|
)
|
|
self._db.commit()
|