commit ba69ba689f60213f8c8a2433fd84d6f3319afd84
parent 26a20dafcb36935e4d2eb362c1da3ee066fd4899
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Mon, 17 Aug 2026 15:15:19 +0200
re-try on serialization failure
Diffstat:
1 file changed, 48 insertions(+), 4 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-wire-debit.c b/src/auditor/taler-helper-auditor-wire-debit.c
@@ -206,11 +206,23 @@ struct ReserveClosure
static struct GNUNET_CONTAINER_MultiHashMap *reserve_closures;
/**
+ * How often do we retry the transaction after a serialization
+ * failure before we give up?
+ */
+#define MAX_RETRIES 3
+
+/**
* Return value from main().
*/
static int global_ret;
/**
+ * Number of serialization failures we have retried since the last
+ * successfully committed transaction.
+ */
+static unsigned int retries;
+
+/**
* State of the current database transaction with
* the auditor DB.
*/
@@ -599,21 +611,49 @@ commit (enum GNUNET_DB_QueryStatus qs)
goto handle_db_error;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Transaction concluded!\n");
+ retries = 0;
if (1 == test_mode)
GNUNET_SCHEDULER_shutdown ();
return;
handle_db_error:
TALER_AUDITORDB_rollback (TALER_ARL_adb);
- for (unsigned int max_retries = 3; max_retries>0; max_retries--)
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
{
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- break;
+ if (MAX_RETRIES < ++retries)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to commit the transaction after %u retries, terminating\n",
+ (unsigned int) MAX_RETRIES);
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Serialization issue, trying again\n");
- qs = begin_transaction ();
+ /* Any bank request still in flight belongs to the attempt we are
+ abandoning. #process_debits() would leave it alone and start
+ nothing, so the restarted audit would never make progress. */
+ for (struct WireAccount *wa = wa_head;
+ NULL != wa;
+ wa = wa->next)
+ {
+ if (NULL != wa->dhh)
+ {
+ TALER_BANK_debit_history_cancel (wa->dhh);
+ wa->dhh = NULL;
+ }
+ if (NULL != wa->dhh_task)
+ {
+ GNUNET_SCHEDULER_cancel (wa->dhh_task);
+ wa->dhh_task = NULL;
+ }
+ }
+ if (GNUNET_DB_STATUS_HARD_ERROR != begin_transaction ())
+ return; /* the retry continues asynchronously from here */
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Hard database error, terminating\n");
+ global_ret = EXIT_FAILURE;
GNUNET_SCHEDULER_shutdown ();
}
@@ -1662,6 +1702,10 @@ begin_transaction (void)
NULL != wa;
wa = wa->next)
{
+ /* we are called again after a serialization failure, so the labels
+ may already have been computed */
+ GNUNET_free (wa->label_wire_out_serial_id);
+ GNUNET_free (wa->label_wire_off_out);
GNUNET_asprintf (&wa->label_wire_out_serial_id,
"wire-%s-%s",
wa->ai->section_name,