Files
astrololo/README.md
gitea 16d35c16dc Szkielet aplikacji trójwarstwowej (prezentacja / logika / dane)
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>
2026-06-26 17:35:09 +02:00

4.0 KiB
Raw Permalink Blame History

astrololo

Aplikacja w modelu trójwarstwowym, w pełni modułowa: trzy niezależne usługi, każda komunikuje się wyłącznie z sąsiadem (nigdy „przez głowę”).

┌──────────────────────┐   formularz (w dół)   ┌──────────────────────┐   zapytanie (w dół)   ┌──────────────────────┐
│  PREZENTACJA (:8000) │ ───────────────────▶ │   LOGICZNA (:8001)   │ ───────────────────▶ │  BAZODANOWA (:8002)  │
│  strona WWW + form   │ ◀─────────────────── │  reguły biznesowe    │ ◀─────────────────── │  wyszukiwanie danych │
└──────────────────────┘   wyniki (w górę)     └──────────────────────┘   dane (w górę)       └──────────────────────┘
        HTML/UI                                    pośrednik + logika                         Excel(+cache) ▸ SQL

Każda warstwa to osobny katalog, osobny requirements.txt, osobny Dockerfile i osobne README. Komunikacja przez HTTP/JSON. Warstwa zna tylko adres warstwy bezpośrednio pod nią — nic o jej wnętrzu.

Warstwa Katalog Zna w dół Zadanie
Prezentacji services/presentation LOGIC_URL serwuje stronę, przekazuje formularz, renderuje wyniki
Logiczna services/logic DATA_URL reguły biznesowe, tłumaczenie zapytań, opracowanie wyników
Bazodanowa services/data pliki Excela / SQL tylko wyszukiwanie danych i podanie ich w górę

Szybki start (Docker)

make sample      # przykładowe pliki .xlsx do warstwy bazodanowej
make up          # zbuduj i uruchom 3 warstwy
# otwórz http://localhost:8000

Szybki start (lokalnie, 3 terminale)

cd services/data && pip install -r requirements.txt && python scripts/make_sample_data.py
make dev-data            # terminal 1  -> :8002
make dev-logic           # terminal 2  -> :8001
make dev-presentation    # terminal 3  -> :8000

Modułowość — dowód

  • Wymień prezentację (np. na SPA/React) → reszta bez zmian, kontrakt /api/query stały.
  • Wymień bazę (Excel → SQL) → prezentacja i logika bez zmian (patrz niżej).
  • Każdą warstwę da się uruchomić, testować i wdrażać osobno.

Wydajność warstwy Excela — cache 4-poziomowy

Dziś dane to setki dużych .xlsx, przeszukiwanych po wykrytym nagłówku i układzie kolumn. To kosztowne, więc warstwa bazodanowa ma cache (szczegóły: services/data/README.md):

  1. Schemat (L1, SQLite) — wykryty nagłówek + mapowanie kolumn zapisane raz na wersję pliku.
  2. Dane (L2, Parquet) — znormalizowany arkusz; kolejne odczyty 10100× szybsze niż .xlsx.
  3. Zapytania (L3, in-memory TTL/LRU) — powtarzalne wyszukiwania natychmiast (łatwo podmienić na Redis).
  4. Odwrócony indeks (L4, SQLite)wartość → plik; otwieramy tylko trafione pliki zamiast skanu setek.

Unieważnianie automatyczne: klucz cache = odcisk pliku (mtime+rozmiar, opcjonalnie sha256). Zmiana pliku → przebudowa tylko jego wpisów.

Droga na przyszłość — migracja do SQL

Warstwa bazodanowa ukrywa źródło za interfejsem DataProvider (wzorzec Repository). Migracja:

make migrate                 # ETL: tym samym loaderem Excel -> tabela 'records' + indeksy
export DATA_PROVIDER=sql      # przełącz całą warstwę

SqlDataProvider realizuje ten sam kontrakt /search, więc warstwa logiczna i prezentacji nie zmieniają ani jednej linii. Odwrócony indeks z L4 (SQLite) jest już pomostem — rozbudowa o wszystkie kolumny = docelowa baza.