taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

commit 149b730bedd237f705b05d0bce34a035133a9fea
parent ebd83c59606ffcf69e193f1c16dfc65c1f561d2e
Author: Antoine A <>
Date:   Thu,  6 Nov 2025 20:13:31 +0100

magnet-bank: improve logging

Diffstat:
Mtaler-magnet-bank/db/magnet-bank-0001.sql | 11+++++++++--
Mtaler-magnet-bank/db/magnet-bank-procedures.sql | 12+++++++++---
Mtaler-magnet-bank/src/db.rs | 51+++++++++++++++++++++++++++++++++++++++++++--------
Mtaler-magnet-bank/src/worker.rs | 49++++++++++++++++++++++++++++++++-----------------
4 files changed, 93 insertions(+), 30 deletions(-)

diff --git a/taler-magnet-bank/db/magnet-bank-0001.sql b/taler-magnet-bank/db/magnet-bank-0001.sql @@ -116,4 +116,11 @@ CREATE TABLE kv( key TEXT NOT NULL UNIQUE PRIMARY KEY, value JSONB NOT NULL ); -COMMENT ON TABLE kv IS 'KV table'; -\ No newline at end of file +COMMENT ON TABLE kv IS 'KV table'; + +CREATE TYPE register_result AS ENUM( + 'idempotent', + 'known', + 'recovered' +); +COMMENT ON TYPE register_result IS 'Status of a registered transaction'; +\ No newline at end of file diff --git a/taler-magnet-bank/db/magnet-bank-procedures.sql b/taler-magnet-bank/db/magnet-bank-procedures.sql @@ -128,7 +128,7 @@ CREATE FUNCTION register_tx_out( IN in_now INT8, -- Success return OUT out_tx_row_id INT8, - OUT out_new BOOLEAN + OUT out_result register_result ) LANGUAGE plpgsql AS $$ BEGIN @@ -136,8 +136,9 @@ BEGIN SELECT tx_out_id INTO out_tx_row_id FROM tx_out WHERE magnet_code = in_code; -out_new = NOT found; -IF out_new THEN +IF FOUND THEN + out_result = 'idempotent'; +ELSE -- Insert new outgoing transaction INSERT INTO tx_out ( magnet_code, @@ -167,6 +168,11 @@ IF out_new THEN status = 'success', status_msg = NULL WHERE magnet_code = in_code; + IF FOUND THEN + out_result = 'known'; + ELSE + out_result = 'recovered'; + END IF; IF in_wtid IS NOT NULL THEN -- Insert new outgoing talerable transaction diff --git a/taler-magnet-bank/src/db.rs b/taler-magnet-bank/src/db.rs @@ -236,9 +236,21 @@ pub enum TxOutKind { Talerable(OutgoingSubject), } +#[derive(Debug, Clone, Copy, PartialEq, Eq, sqlx::Type)] +#[allow(non_camel_case_types)] +#[sqlx(type_name = "register_result")] +pub enum RegisterResult { + /// Already registered + idempotent, + /// Initiated transaction + known, + /// Recovered unknown outgoing transaction + recovered, +} + #[derive(Debug, PartialEq, Eq)] pub struct AddOutgoingResult { - pub new: bool, + pub result: RegisterResult, pub row_id: u64, } @@ -250,7 +262,7 @@ pub async fn register_tx_out( ) -> sqlx::Result<AddOutgoingResult> { let query = sqlx::query( " - SELECT out_new, out_tx_row_id + SELECT out_result, out_tx_row_id FROM register_tx_out($1, ($2, $3)::taler_amount, $4, $5, $6, $7, $8, $9, $10, $11) ", ) @@ -278,7 +290,7 @@ pub async fn register_tx_out( .bind_timestamp(now) .try_map(|r: PgRow| { Ok(AddOutgoingResult { - new: r.try_get(0)?, + result: r.try_get(0)?, row_id: r.try_get_u64(1)?, }) }) @@ -1032,7 +1044,7 @@ mod test { let later = date.tomorrow().unwrap(); let tx = TxOut { code, - amount: amount("EUR:10"), + amount: amount("HUF:10"), subject: "subject".to_owned(), creditor: magnet_payto( "payto://iban/HU30162000031000163100000000?receiver-name=name", @@ -1040,13 +1052,36 @@ mod test { value_date: date, status: TxStatus::Completed, }; + assert!(matches!( + make_transfer( + &mut *db, + &TransferRequest { + request_uid: HashCode::rand(), + amount: amount("HUF:10"), + exchange_base_url: url("https://exchange.test.com/"), + wtid: ShortHashCode::rand(), + credit_account: payto( + "payto://iban/HU02162000031000164800000000?receiver-name=name" + ), + }, + &tx.creditor, + &now + ) + .await + .unwrap(), + TransferResult::Success { .. } + )); + db::initiated_submit_success(&mut *db, 1, &Timestamp::now(), tx.code) + .await + .expect("status success"); + // Insert assert_eq!( register_tx_out(&mut *db, &tx, first, &now) .await .expect("register tx out"), AddOutgoingResult { - new: true, + result: db::RegisterResult::known, row_id: id, } ); @@ -1064,11 +1099,11 @@ mod test { .await .expect("register tx out"), AddOutgoingResult { - new: false, + result: db::RegisterResult::idempotent, row_id: id, } ); - // Many + // Recovered assert_eq!( register_tx_out( &mut *db, @@ -1083,7 +1118,7 @@ mod test { .await .expect("register tx out"), AddOutgoingResult { - new: true, + result: db::RegisterResult::recovered, row_id: id + 1, } ); diff --git a/taler-magnet-bank/src/worker.rs b/taler-magnet-bank/src/worker.rs @@ -30,7 +30,7 @@ use tracing::{debug, error, info, trace, warn}; use crate::{ FullHuPayto, HuIban, config::AccountType, - db::{self, AddIncomingResult, Initiated, TxIn, TxOut, TxOutKind}, + db::{self, AddIncomingResult, Initiated, RegisterResult, TxIn, TxOut, TxOutKind}, failure_injection::{InjectedErr, fail_point}, magnet_api::{ api::{ApiErr, ErrKind}, @@ -216,31 +216,40 @@ impl Worker<'_> { &Timestamp::now(), ) .await?; - // TODO log status (known | recovered | founded) - if res.new { - match kind { + match res.result { + RegisterResult::idempotent => match kind { TxOutKind::Simple => { - warn!(target: "worker", "out (malformed) {tx_out}") + trace!(target: "worker", "out malformed {tx_out} already see") } TxOutKind::Bounce(_) => { - info!(target: "worker", "out (bounce) {tx_out}") + trace!(target: "worker", "out bounce {tx_out} already see") + } + TxOutKind::Talerable(_) => { + trace!(target: "worker", "out {tx_out} already see") + } + }, + RegisterResult::known => match kind { + TxOutKind::Simple => { + warn!(target: "worker", "out malformed {tx_out}") + } + TxOutKind::Bounce(_) => { + info!(target: "worker", "out bounce {tx_out}") } TxOutKind::Talerable(_) => { info!(target: "worker", "out {tx_out}") } - } - } else { - match kind { + }, + RegisterResult::recovered => match kind { TxOutKind::Simple => { - trace!(target: "worker", "out (malformed) {tx_out} already see") + warn!(target: "worker", "out malformed (recovered) {tx_out}") } TxOutKind::Bounce(_) => { - trace!(target: "worker", "out (bounce) {tx_out} already see") + warn!(target: "worker", "out bounce (recovered) {tx_out}") } TxOutKind::Talerable(_) => { - trace!(target: "worker", "out {tx_out} already see") + warn!(target: "worker", "out (recovered) {tx_out}") } - } + }, } } else { let bounced = match kind { @@ -273,10 +282,16 @@ impl Worker<'_> { &Timestamp::now(), ) .await?; - if res.new { - info!(target: "worker", "out {tx_out}"); - } else { - trace!(target: "worker", "out {tx_out} already seen"); + match res.result { + RegisterResult::idempotent => { + trace!(target: "worker", "out {tx_out} already seen"); + } + RegisterResult::known => { + info!(target: "worker", "out {tx_out}"); + } + RegisterResult::recovered => { + warn!(target: "worker", "out (recovered) {tx_out}"); + } } } else { let res = db::register_tx_out_failure(