libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit e54b73cfeb3b402fb012606c2ea9d7427706c9ee
parent 6b942f6213e6b2ad53b252b88a79e14bac58be71
Author: Antoine A <>
Date:   Tue, 13 Oct 2026 11:16:32 +0200

common: lock for commit ordered ids

Diffstat:
Mdatabase-versioning/libeufin-bank-procedures.sql | 4++++
Mdatabase-versioning/libeufin-nexus-procedures.sql | 41++++++++++++++++++++++++-----------------
2 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/database-versioning/libeufin-bank-procedures.sql b/database-versioning/libeufin-bank-procedures.sql @@ -486,6 +486,8 @@ PERFORM FROM bank_accounts ORDER BY bank_account_id FOR UPDATE; +-- Lock for transaction history and revenue id commit ordering +LOCK TABLE bank_account_transactions IN SHARE ROW EXCLUSIVE MODE; -- now actually create the bank transaction. -- debtor side: INSERT INTO bank_account_transactions ( @@ -642,6 +644,8 @@ DECLARE local_amount taler_amount; local_taler_in_id INT8; BEGIN +-- Lock for incoming history id commit ordering +LOCK TABLE taler_exchange_incoming IN SHARE ROW EXCLUSIVE MODE; -- Register incoming transaction INSERT INTO taler_exchange_incoming ( metadata, diff --git a/database-versioning/libeufin-nexus-procedures.sql b/database-versioning/libeufin-nexus-procedures.sql @@ -173,6 +173,8 @@ IF out_initiated AND NOT out_found THEN END IF; IF NOT out_found THEN + -- Lock for outgoing history id commit ordering + LOCK TABLE outgoing_transactions IN SHARE ROW EXCLUSIVE MODE; -- Store the transaction in the database INSERT INTO outgoing_transactions ( amount @@ -335,6 +337,8 @@ IF out_found THEN PERFORM pg_notify('nexus_revenue_tx', out_tx_id::text); END IF; ELSE + -- Lock for revenue id commit ordering + LOCK TABLE incoming_transactions IN SHARE ROW EXCLUSIVE MODE; -- Store the transaction in the database INSERT INTO incoming_transactions ( amount @@ -373,6 +377,8 @@ IF in_type IS NOT NULL AND NOT out_talerable AND out_bounce_id IS NULL THEN WHERE ( incoming_transaction_id IS NULL AND account_pub = in_metadata AND in_type=type AND type='reserve' ) OR authorization_pub = local_authorization_pub; + -- Lock for incoming history id commit ordering + LOCK TABLE talerable_incoming_transactions IN SHARE ROW EXCLUSIVE MODE; -- We cannot use ON CONFLICT here because conversion use a trigger before insertion that isn't idempotent INSERT INTO talerable_incoming_transactions ( incoming_transaction_id @@ -706,25 +712,26 @@ IF out_reserve_pub_reuse OR out_subject_reuse THEN END IF; IF in_recurrent THEN - -- Finalize one pending right now - WITH moved_tx AS ( - DELETE FROM pending_recurrent_incoming_transactions - WHERE incoming_transaction_id = ( - SELECT incoming_transaction_id - FROM pending_recurrent_incoming_transactions - JOIN incoming_transactions USING (incoming_transaction_id) - WHERE authorization_pub = in_authorization_pub - ORDER BY execution_time ASC - LIMIT 1 - ) - RETURNING incoming_transaction_id + -- Finalize one pending right now. + DELETE FROM pending_recurrent_incoming_transactions + WHERE incoming_transaction_id = ( + SELECT incoming_transaction_id + FROM pending_recurrent_incoming_transactions + JOIN incoming_transactions USING (incoming_transaction_id) + WHERE authorization_pub = in_authorization_pub + ORDER BY execution_time ASC + LIMIT 1 ) - INSERT INTO talerable_incoming_transactions (incoming_transaction_id, type, metadata, authorization_pub, authorization_sig) - SELECT moved_tx.incoming_transaction_id, in_type, in_account_pub, in_authorization_pub, in_authorization_sig - FROM moved_tx - RETURNING incoming_transaction_id, taler_in_id INTO talerable_tx, local_taler_in_id; + RETURNING incoming_transaction_id INTO talerable_tx; IF talerable_tx IS NOT NULL THEN - PERFORM pg_notify('nexus_incoming_tx', local_taler_in_id::text); + -- Lock for incoming history id commit ordering + LOCK TABLE talerable_incoming_transactions IN SHARE ROW EXCLUSIVE MODE; + INSERT INTO talerable_incoming_transactions (incoming_transaction_id, type, metadata, authorization_pub, authorization_sig) + VALUES (talerable_tx, in_type, in_account_pub, in_authorization_pub, in_authorization_sig) + RETURNING incoming_transaction_id, taler_in_id INTO talerable_tx, local_taler_in_id; + IF talerable_tx IS NOT NULL THEN + PERFORM pg_notify('nexus_incoming_tx', local_taler_in_id::text); + END IF; END IF; ELSE -- Bounce all pending