# Candles cache: precompute wszystkich timeframe (1s…1d) Cel: przełączanie `tf` w UI ma być natychmiastowe. Backend ma **ciągle liczyć** i **przechowywać** świeczki dla wszystkich timeframe: `1s 3s 5s 15s 30s 1m 3m 5m 15m 30m 1h 4h 12h 1d` ## Jak to działa 1) Ticki (append-only) lądują w `drift_ticks`. 2) Worker `candles-cache-worker`: - liczy świeczki dla **każdego** `bucket_seconds` bezpośrednio z `drift_ticks`, - trzyma w DB “ostatnie N” świec (domyślnie `N=1024`) per `(symbol, source, tf)`, - jeśli danych historycznych jest mniej (np. brak wielu dni) — zapisuje tylko to, co istnieje, - robi backfill/warmup przy starcie i potem dopisuje “na bieżąco” w pętli. 3) API `GET /v1/chart` czyta **cache-first** z `drift_candles_cache` (fallback do on-demand funkcji, jeśli cache pusty). ## Tabela - `drift_candles_cache` (Timescale hypertable, partycjonowanie po `bucket`) - `bucket_seconds` = długość świecy w sekundach - `source=''` oznacza “(any)” (brak filtra po źródle ticków) ## Worker Plik: `services/candles-worker/candles-cache-worker.mjs` Env: - `CANDLES_SYMBOLS` (np. `SOL-PERP,PUMP-PERP`) - `CANDLES_SOURCES` (np. `any,drift_oracle`) - `CANDLES_TFS` (np. `1s,3s,5s,15s,...,1d`) - `CANDLES_TARGET_POINTS` (default `1024`) - `CANDLES_BACKFILL_DAYS` (opcjonalnie: wymusza minimalny warmup “co najmniej X dni”) - `CANDLES_POLL_MS` (default `5000`) ## Dlaczego to jest szybkie - najcięższe agregacje są robione raz i utrzymywane “na bieżąco”, - przełączenie `tf` to tylko query po gotowych wierszach (`order_by bucket desc limit N`), - “flow/brick stack” w `/v1/chart` jest liczone z cache “point candles” (np. `1s/3s/5s/15s/…`) bez skanowania `drift_ticks`.