Idempotence et exécutions multiples
AvancéDans un système distribué, tout message et toute requête peuvent être livrés plus d'une fois : les traitements doivent l'accepter.
Table de messages traités#
CREATE TABLE messages_traites (
id_message text PRIMARY KEY,
traite_le timestamptz NOT NULL DEFAULT now()
);
BEGIN;
INSERT INTO messages_traites (id_message) VALUES ($1) ON CONFLICT DO NOTHING;
-- Si 0 ligne insérée : déjà traité, on s'arrête (COMMIT et retour).
-- Sinon : effectuer le traitement métier dans la même transaction.
COMMIT;
L'enregistrement du message et l'effet métier sont atomiques : soit les deux, soit aucun.
Verrous consultatifs#
Pour qu'une seule instance exécute une tâche planifiée à la fois (sans dépendre d'un composant externe) :
SELECT pg_try_advisory_lock(hashtext('rapport-quotidien')); -- true si le verrou est obtenu
-- ... travail ...
SELECT pg_advisory_unlock(hashtext('rapport-quotidien'));
pg_advisory_xact_lock libère automatiquement le verrou à la fin de la transaction, ce qui convient aussi derrière un pooleur en mode transaction.