commit 149b730bedd237f705b05d0bce34a035133a9fea
parent ebd83c59606ffcf69e193f1c16dfc65c1f561d2e
Author: Antoine A <>
Date: Thu, 6 Nov 2025 20:13:31 +0100
magnet-bank: improve logging
Diffstat:
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(