Riguardo a coding, contribuzioni, eventi, API
Nella piattaforma si fa ampio uso del Pattern Event Sourcing è quindi fondamentale che il formato degli eventi sia stabile e documentato.
Per ogni evento ci aspettiamo almeno i seguenti campi:
Campo | Valore | Formato | Annotazioni |
---|---|---|---|
Attenzione: se si genera un evento, a partire da un evento esistente, si sta creando una nuova entità che avrà i propri valori event_id
, event_created_at
, event_version
, app_id
: non si deve mai ricopiare questi valori dall'evento originario.
I consumatori devono essere sempre attenti alla versione di eventi che supportano: la versione deve essere esplicitamente supportata ed eventi di una versione non supportata devono essere scartati
Nei log è possibile dare evidenza del fatto che si è incontrato un evento non supportato, ma non va loggato come errore è sufficiente dare l'informazione a livello DEBUG.
Le date vanno sempre espresse nello standard ISO8601, in particolare, le date non devono contenere i millisecondi, e devono contenere il formato della timezone Europe/Rome.
Es: 2022-06-22T15:11:20+02:00
Facciamo in generale riferimento alle linee guida di Zalando:
Le collezioni devono essere facilmente navigabili, per questo abbiamo adottato il seguente standard:
Le GET sulle risorse devono supportare i query parameters convenzionali:
sort
offset
limit
Su alcuni campi è utile implementare anche l'opzione di paginazione cursor-based:
GET /payments?created_since=$timeStamp
Fare riferimento alla RFC 7807
Tutti i microservizi che compongono la piattaforma devo rispettare i seguenti standard e regole generali
Tutti i servizi devono rispettare i , descritti in modo anche più dettagliato nell'articolo
Dockerfile
e docker-compose.yml
devono essere presenti nella root del repo (.dockerignore
se serve) per facilitare l'avvio in locale dell'applicativo e farne saggiare l'utilizzo;
se necessario usare un docker-compose.dev.yml
per aggiungere tool utili per lavorare in locale durante lo sviluppo.
il servizio deve gestire correttamente i segnali inviati da docker per fare uno shutdown pulito e senza interrompere l'esecuzione in fasi critiche per la consistenza dei dati.
la configurazione *deve avvenire mediante variabili d'ambiente
la configurazione può essere fatta anche tramite un file di environment (.env
) o parametri da cli
se http, deve essere presente un /status
entrypoint che risponde 200 se va tutto bene, uno status code diverso in caso contrario
se non http, l'healthcheck può essere un controllo su un file o su un processo
l'health check, se disponibile, deve essere inserito nel Dockerfile
Il log deve supportare almeno tre livelli: debug
, info
e error
.
A debug
deve essere comprensibile il flusso logico dell'applicativo, a info
ci si aspetta di leggere 1 riga per ogni evento o chiamata ricevuta dall'applicativo, a error
invece non si deve vedere nulla se non ci sono errori: per capirsi, a ERROR, il rate dei log che si alza dovrebbe essere indice che ci sono problemi per i quali è importante attrarre l'attenzione degli amministratori.
Se sono previste chiamate http, deve avere un log stile webserver, con indicazione dell'IP chiamante (con supporto di X-Forwarded-
headers, timestamp, path servito, etc... fate riferimento allo standard ncsa o apache log format, in tutti i framework ci sono librerie che li producono gratis.
Non mi schiare log http e log multiriga (stacktrace o similari): per esempio inviare lo stacktrace a stderr
e riservare stdout
ai log http
Se possibile implementare log in formato json, ma solo se si può produrre solo del JSON, mischiare testo semplice e JSON non è di grande utilità.
sentry support
configurazione di sentry sul repo gitlab
se http, deve esistere l'entrypoint /metrics
che espone metriche in formato prometheus.
un servizio può mostrare metriche sulle chiamate (status code, timing), anche se solitamente le possiamo prendere altrove (traefik), - un servizio deve mostrare metriche specifiche dell'app, in particolare delle condizioni di errore (counters) e dei tempi di risposta di eventuali servizi esterni richiamati da questo (histograms).
sui sistemi di deploy e orchestrazione che usiamo ci sono sempre dei modi di eseguire task stile cron, inutile reimplementare quella logica dentro la propria App.
è indispensabile invece rendere il proprio software idempotente: deve essere rieseguibile più volte sugli stessi dati senza fare danno.
il modo più semplice per implementare una chiamata a tempo è implementare un comando da cli che possa essere eseguito con la stessa immagine con cui gira l'applicativo.
in docker c'e' sempre un mapping tra esterno e interno, inutile parametrizzare questi aspetti in modo particolarmente flessibile.
linting del codice e enforcemente dei coding styles
pubblicazione su Developers Italia
id
identificativo unico dell'entità oggetto dell'evento
UUID
Es: in un pagamento è l'ID del pagamento, in una pratica è l'application_id etc...
event_id
identificativo unico dell'evento
UUID
Non deve esserci per nessun motivo due volte lo stesso ID
event_version
versione dell'evento
Integer or Float
Se il formato è solo un intero (Es: 1, 2, etc..) cambia ad ogni singolo cambiamento. Se si usa un float 1.0
, 1.1
, etc... il formato deve essere retrocompatibile se cambia la parte decimale, non retrocompatible se cambia la parte intera.
event_created_at
data dell'evento
ISO8601
Ricordarsi di usare il formato della timezone Europe/Rome (Es: 2022-06-22T15:11:20+02:00
)
app_id
Nome e versione dell'applicativo che ha generato l'evento
$application:$version
Utile per motivi di debug (Es: payment-dispatcher:1.0.15).