Socle technique des schémas
Les tables présentes dans tout schéma de service. Elles ne portent aucune donnée métier : elles sont la condition pour qu'un service publie, consomme et rejoue sans produire de doublon. La forme de référence est celle du code — outbox_events est déjà créée dans les bases de service.
1. Publication — outbox_events
Un service ne publie jamais directement sur Kafka depuis sa logique métier : il écrit l'événement dans sa propre base, dans la même transaction que le changement d'état, et un relais publie ensuite. Sans cela, un crash entre le commit et la publication perd l'événement — ou publie un événement dont le changement d'état a été annulé.
create table outbox_events (
id bigserial primary key,
event_id varchar(40) not null unique,
event_type varchar(100) not null,
subject varchar(50) not null,
payload text not null,
occurred_at timestamptz not null,
published boolean not null default false,
published_at timestamptz
);
create index idx_outbox_pending on outbox_events (published, id);
2. Idempotence de consommation — processed_events
Kafka garantit l'at-least-once : un même événement sera parfois livré deux fois. Le consommateur mémorise donc les identifiants déjà traités et ignore les rejeux.
create table processed_events (
event_id varchar(40) primary key,
processed_at timestamptz not null
);
3. Idempotence des commandes — idempotency_keys
Côté API, un client qui rejoue un POST (réseau coupé, bouton cliqué deux fois) ne doit pas créer deux dossiers. La clé fournie par l'appelant est mémorisée avec une empreinte de la requête et la ressource produite.
create table idempotency_keys (
key varchar(80) primary key,
fingerprint integer not null,
claim_number varchar(15) not null,
created_at timestamptz not null
);
L'empreinte sert à distinguer deux cas : même clé, même requête → renvoyer la ressource déjà créée ; même clé, requête différente → refuser, car le client réutilise une clé pour autre chose.
4. Projections locales — known_<entité>
Un service a souvent besoin d'une donnée détenue par un autre — le numéro de dossier, le nom d'une compagnie. Deux mauvaises réponses : l'appel synchrone à chaque lecture (couplage temporel), ou la table maître dupliquée (deux sources de vérité). La bonne réponse est une copie locale en lecture seule, alimentée par événements et nommée explicitement.
create table known_claims (
claim_number varchar(15) primary key,
victim_first_name varchar(100) not null,
victim_last_name varchar(100) not null,
opened_at timestamptz not null,
registered_at timestamptz not null
);
5. Créées par l'outil — databasechangelog
Liquibase crée et maintient databasechangelog et databasechangeloglock. Elles ne se déclarent pas, mais elles ont un rôle direct dans la reprise : le pipeline de migration lit databasechangelog pour vérifier que la base cible est bien à la version de schéma attendue avant de charger quoi que ce soit, et s'arrête proprement en cas d'écart. C'est ce contrôle qui transforme « le schéma cible est censé exister » en fait vérifié à l'exécution.
Récapitulatif
| Table | Obligatoire pour | État réel |
|---|---|---|
| outbox_events | Tout service qui détient un état et publie des événements — soit 14 des 15 services métier. svc-audit-trail en est dépourvu : terminal, il ne publie pas. Les BFF et edges non plus : sans état local, l'outbox n'a pas d'objet. | CRÉÉE 14 services |
| processed_events | Tout service qui consomme des événements. | 1 service |
| idempotency_keys | Tout service exposant une API de commande. | 1 service |
| known_<entité> | Selon les dépendances de lecture du service. | 1 service |
| databasechangelog | Toutes les bases de service. | AUTOMATIQUE |
La table qui ne devrait pas être là — audit_logs
Douze schémas modélisés portent une table audit_logs locale (entity_type, entity_id, action, old_value, new_value, performed_by, performed_at), alors que svc-audit-trail centralise la piste d'audit en consommant tous les topics. Les deux ne peuvent pas être « la » piste d'audit exigée par les CDC.
L'arbitrage à rendre :
- Journal central seul — cohérent avec l'architecture événementielle, mais l'audit dépend alors de la chaîne Kafka : si un événement n'est pas publié, l'action n'est pas tracée.
- Trace technique locale assumée — la table reste, mais elle est nommée et documentée comme une trace de débogage sans valeur probante, et svc-audit-trail demeure la seule piste opposable.
Recommandation : la seconde, à condition de l'écrire. Une table d'audit dont personne ne sait si elle fait foi est pire que pas de table du tout.