172 lines
5.4 KiB
Markdown
172 lines
5.4 KiB
Markdown
# Supabase Pinger
|
|
|
|
Tool Python dockerizzato pensato per mantenere "attivo" un database Supabase in free tier, evitando che venga spento e parcheggiato per inattivita'.
|
|
|
|
L'idea e' semplice: il container resta in esecuzione fino a quando non viene fermato esplicitamente e, a intervalli regolari, esegue un'operazione verso il database Supabase per generare attivita' sufficiente a non far decadere l'istanza.
|
|
|
|
In piu', il servizio espone una webapp/API con FastAPI servita da Uvicorn:
|
|
|
|
- dashboard in stile SmokePing;
|
|
- API read-only per stato e storico;
|
|
- documentazione Swagger in `/docs` e OpenAPI in `/openapi.json`.
|
|
|
|
## Obiettivo
|
|
|
|
I progetti Supabase in free tier possono diventare temporaneamente inaccessibili se rimangono inattivi troppo a lungo. Questo progetto serve a:
|
|
|
|
- mantenere raggiungibile il database nel tempo;
|
|
- centralizzare la configurazione in un file `.env`;
|
|
- fornire anche un file `.env.example` come modello;
|
|
- girare in un container Docker sempre attivo, finche' non viene arrestato manualmente.
|
|
|
|
## Come funziona
|
|
|
|
Il servizio viene eseguito all'interno di un container Docker e resta attivo in modo continuativo. A ogni ciclo:
|
|
|
|
1. legge la configurazione dal file `.env`;
|
|
2. apre una connessione al database Supabase/PostgreSQL;
|
|
3. esegue una query o un'operazione leggera di keep-alive;
|
|
4. salva un campione storico (successo/errore + latenza) in uno storage locale a buffer circolare dimensionato per 48 ore;
|
|
5. attende l'intervallo configurato;
|
|
6. ripete il processo fino allo stop del container.
|
|
|
|
## Configurazione
|
|
|
|
La configurazione deve essere persistita in un file `.env`, non hardcoded nel codice o nel Dockerfile.
|
|
|
|
E' consigliato mantenere nel repository anche un file `.env.example` con le sole chiavi, senza valori reali, per documentare le variabili richieste.
|
|
|
|
### Esempio di `.env.example`
|
|
|
|
```env
|
|
SUPABASE_DB_HOST=aws-1-eu-central-1.pooler.supabase.com
|
|
SUPABASE_DB_PORT=6543
|
|
SUPABASE_DB_NAME=postgres
|
|
SUPABASE_DB_USER=postgres.<project-ref>
|
|
SUPABASE_DB_PASSWORD=
|
|
PING_INTERVAL_MINUTES=4320
|
|
PING_QUERY=SELECT 1;
|
|
TZ=Europe/Rome
|
|
WEB_HOST=0.0.0.0
|
|
WEB_PORT=8080
|
|
RRD_DB_PATH=data/connection_rrd.sqlite3
|
|
RRD_RETENTION_HOURS=48
|
|
```
|
|
|
|
### Significato delle variabili
|
|
|
|
- `SUPABASE_DB_HOST`: hostname del connection pooler Supabase (consigliato per compatibilita' IPv4).
|
|
- `SUPABASE_DB_PORT`: porta del pooler PostgreSQL, normalmente `6543`.
|
|
- `SUPABASE_DB_NAME`: nome del database.
|
|
- `SUPABASE_DB_USER`: utente di connessione nel formato `postgres.<project-ref>` quando si usa il pooler.
|
|
- `SUPABASE_DB_PASSWORD`: password di connessione.
|
|
- `PING_INTERVAL_MINUTES`: intervallo tra un keep-alive e il successivo. Default `4320` (72 ore, circa 3 volte a settimana).
|
|
- `PING_QUERY`: query leggera da eseguire per generare attivita'.
|
|
- `TZ`: timezone del container per logging e scheduling coerenti.
|
|
- `WEB_HOST`: host di bind del server Uvicorn.
|
|
- `WEB_PORT`: porta HTTP della webapp/API.
|
|
- `RRD_DB_PATH`: path del database storico locale (RRD-like a buffer circolare).
|
|
- `RRD_RETENTION_HOURS`: retention dello storico, default `48`.
|
|
|
|
## API e Swagger
|
|
|
|
Endpoint principali:
|
|
|
|
- `GET /api/status`: ultimo campione disponibile;
|
|
- `GET /api/history?hours=48`: storico campioni (finestra max 48h);
|
|
- `GET /`: dashboard web in stile SmokePing;
|
|
- `GET /docs`: Swagger UI;
|
|
- `GET /openapi.json`: schema OpenAPI.
|
|
|
|
## Docker
|
|
|
|
Il container deve rimanere in esecuzione continua. In pratica, il processo Python non deve terminare dopo il primo ping, ma restare in loop fino a interruzione esplicita.
|
|
|
|
### Build
|
|
|
|
```bash
|
|
docker build -t supabase-pinger .
|
|
```
|
|
|
|
### Avvio con file `.env`
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name supabase-pinger \
|
|
--env-file .env \
|
|
-p 8080:8080 \
|
|
--restart unless-stopped \
|
|
supabase-pinger
|
|
```
|
|
|
|
L'opzione `--restart unless-stopped` e' la piu' adatta a questo caso: il container viene mantenuto attivo e riparte automaticamente dopo reboot o crash, ma si ferma se viene arrestato intenzionalmente.
|
|
|
|
### Arresto
|
|
|
|
```bash
|
|
docker stop supabase-pinger
|
|
```
|
|
|
|
## Esempio con Docker Compose
|
|
|
|
```yaml
|
|
services:
|
|
supabase-pinger:
|
|
build: .
|
|
container_name: supabase-pinger
|
|
env_file:
|
|
- .env
|
|
ports:
|
|
- "8080:8080"
|
|
restart: unless-stopped
|
|
```
|
|
|
|
Avvio:
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Stop:
|
|
|
|
```bash
|
|
docker compose down
|
|
```
|
|
|
|
## Struttura del progetto
|
|
|
|
```text
|
|
.
|
|
|-- .env # credenziali locali (non versionato)
|
|
|-- .env.example # modello variabili senza segreti
|
|
|-- .gitignore
|
|
|-- app.py # app FastAPI + collector keep-alive
|
|
|-- docker-compose.yml
|
|
|-- Dockerfile
|
|
|-- prd.md # product requirements document
|
|
|-- progress.md # piano e stato di sviluppo
|
|
|-- README.md
|
|
|-- tests/
|
|
`-- requirements.txt
|
|
```
|
|
|
|
## Test
|
|
|
|
Esecuzione test:
|
|
|
|
```bash
|
|
pytest -q
|
|
```
|
|
|
|
## Note operative
|
|
|
|
- Non committare mai il file `.env` con credenziali reali.
|
|
- Committa solo `.env.example` con valori vuoti o fittizi.
|
|
- Usa query di keep-alive molto leggere, ad esempio `SELECT 1;`.
|
|
- Mantieni intervalli ragionevoli: troppo frequenti sono inutili, troppo lunghi rischiano di non prevenire il parcheggio del database.
|
|
- Se il progetto viene eseguito su un host sempre acceso, Docker con policy `unless-stopped` e' sufficiente per il requisito di esecuzione continua.
|
|
|
|
## Scopo del repository
|
|
|
|
Questo repository ospita un servizio minimale e operativo, pensato per un solo compito: impedire che un database Supabase free tier diventi temporaneamente non disponibile per inattivita'.
|