# Warstwa bazodanowa (`data`) Niezależna usługa. **Jedyne zadanie:** wyszukać dane i podać je w górę. Nie zna warstwy logicznej ani prezentacji — komunikacja wyłącznie przez HTTP/JSON (`models.py`). ## API - `POST /search` → `SearchQuery` → `SearchResult` - `GET /health` → `HealthInfo` ## Architektura wewnętrzna ``` providers/ wymienna implementacja (wzorzec Repository) base.py interfejs DataProvider ← kontrakt excel_provider dziś: Excel + 4 poziomy cache sql_provider jutro: SQL (ten sam interfejs) factory.py DATA_PROVIDER=excel|sql excel/ wykrywanie nagłówka + mapowanie układu kolumn (jedyne miejsce znające .xlsx) cache/ fingerprint, schema(L1), frame/parquet(L2), query(L3), index(L4) ingest/ build_index.py (warmup), to_sql.py (migracja ETL) ``` ## Cache — dlaczego szybko | Poziom | Co cache'uje | Zysk | |-------|---------------|------| | L1 `schema.db` | wykryty nagłówek + układ kolumn per plik | brak ponownego skanu heurystyką | | L2 Parquet | znormalizowany arkusz | 10–100× szybciej niż parsowanie `.xlsx` | | L3 `QueryCache` | wynik zapytania (TTL/LRU) | powtarzalne zapytania natychmiast | | L4 `index.db` | odwrócony indeks wartość→plik | otwieramy tylko trafione pliki, nie setki | Unieważnianie: klucz = odcisk pliku (`mtime+rozmiar`, opcjonalnie `sha256`). Zmiana pliku → inny odcisk → automatyczny przebudowa. ## Uruchomienie lokalne ```bash pip install -r requirements.txt python scripts/make_sample_data.py # przykładowe .xlsx python -m app.ingest.build_index # (opcjonalnie) prebuild indeksu uvicorn app.main:app --port 8002 ``` ## Migracja do SQL (gdy nadejdzie czas) ```bash python -m app.ingest.to_sql # Excel -> tabela 'records' + indeksy export DATA_PROVIDER=sql # przełącz warstwę — reszta systemu bez zmian ```