commit 1d9fa76053c5523de38c1cf58f3887ed33fae4dc
parent 736e6a16715b4e43fcb79596a65cfebabda35c59
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 7 Aug 2026 00:15:20 +0200
handle soft error with retries
Diffstat:
2 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c b/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c
@@ -485,20 +485,40 @@ start:
"made blind signatures!\n");
/* save new receipts to date and save receipts Request (blinded signatures,
- * charity id, amount, hash over bkps) to make it idempotent*/
- qs_insert_ir
- = DONAUDB_do_insert_receipt_issued (DH_context,
- year,
- num_bkps,
- du_sigs,
- (uint64_t) charity_id,
- &h_receipts,
- &receipts_sum,
- &smaller_than_max_per_year);
+ * charity id, amount, hash over bkps) to make it idempotent.
+ * Two concurrent requests for the same charity update the same
+ * `charities' row and thus serialize against each other; the database
+ * reports that as a soft error, which means "retry me". */
+ for (unsigned int retries = 0;
+ retries < MAX_TRANSACTION_COMMIT_RETRIES;
+ retries++)
+ {
+ qs_insert_ir
+ = DONAUDB_do_insert_receipt_issued (DH_context,
+ year,
+ num_bkps,
+ du_sigs,
+ (uint64_t) charity_id,
+ &h_receipts,
+ &receipts_sum,
+ &smaller_than_max_per_year);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs_insert_ir)
+ break;
+ }
switch (qs_insert_ir)
{
- case GNUNET_DB_STATUS_HARD_ERROR:
case GNUNET_DB_STATUS_SOFT_ERROR:
+ /* still failing after MAX_TRANSACTION_COMMIT_RETRIES attempts */
+ free_bkps (num_bkps,
+ bkps);
+ json_decref (blind_signatures);
+ for (unsigned int i = 0; i<num_bkps; i++)
+ GNUNET_CRYPTO_blinded_sig_decref (du_sigs[i].blinded_sig);
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_SOFT_FAILURE,
+ NULL);
+ case GNUNET_DB_STATUS_HARD_ERROR:
GNUNET_break (0);
free_bkps (num_bkps,
bkps);
diff --git a/src/donau/donau-httpd_post-batch-submit.c b/src/donau/donau-httpd_post-batch-submit.c
@@ -27,6 +27,7 @@
#include "taler/taler_mhd_lib.h"
#include "taler/taler_signatures.h"
#include "donau-httpd_post-batch-submit.h"
+#include "donau-httpd_db.h"
#include "donau-httpd_get-keys.h"
#include "donau-database/insert_receipts_submitted.h"
@@ -246,12 +247,26 @@ DH_handler_post_batch_submit (struct DH_RequestContext *rc,
{
enum GNUNET_DB_QueryStatus qs;
- qs = DONAUDB_insert_receipts_submitted (DH_context,
- &irc.h_donor_tax_id,
- num_dr,
- irc.donation_receipts,
- irc.donation_year);
+ /* Concurrent submissions can serialize against each other; the
+ database reports that as a soft error, which means "retry me". */
+ for (unsigned int retries = 0;
+ retries < MAX_TRANSACTION_COMMIT_RETRIES;
+ retries++)
+ {
+ qs = DONAUDB_insert_receipts_submitted (DH_context,
+ &irc.h_donor_tax_id,
+ num_dr,
+ irc.donation_receipts,
+ irc.donation_year);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
free_irc (&irc);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return TALER_MHD_reply_with_error (rc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_SOFT_FAILURE,
+ "insert_receipts_submitted");
if (qs < 0)
{
GNUNET_break (0);