merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit ec6a7c0478c517f334d013969cd492d3d52e49e8
parent 0e86dfd5135d9ee706224be894915ab873a57a77
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Tue, 14 Jul 2026 23:37:54 +0200

limit donau /keys fetches

Diffstat:
Msrc/backend/taler-merchant-donaukeyupdate.c | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 84 insertions(+), 3 deletions(-)

diff --git a/src/backend/taler-merchant-donaukeyupdate.c b/src/backend/taler-merchant-donaukeyupdate.c @@ -169,6 +169,27 @@ struct ForceCharityCtx * Handle to the charity update request. */ struct DONAU_CharityGetHandle *h; + + /** + * Scheduler task for retrying a failed /charity_id request. + * This task will trigger the next attempt to download the charity + * details if the previous request could not be started. + */ + struct GNUNET_SCHEDULER_Task *retry_task; + + /** + * The delay before the next retry for fetching /charity_id. + * Used to implement exponential backoff in case of failures. + */ + struct GNUNET_TIME_Relative retry_delay; + + /** + * A flag indicating whether this charity inquiry is currently + * rate-limited. If true, the inquiry was postponed because we + * were at the #OPEN_INQUIRY_LIMIT and must be re-driven from + * end_inquiry() once a slot frees up. + */ + bool limited; }; /** @@ -245,6 +266,15 @@ download_keys (void *cls); /** + * Function that initiates a /charity_id download for a Donau instance. + * + * @param cls closure with a `struct ForceCharityCtx *` + */ +static void +download_charity_id (void *cls); + + +/** * An inquiry finished, check if we need to start more. */ static void @@ -269,6 +299,19 @@ end_inquiry (void) if (at_limit) break; } + for (struct ForceCharityCtx *fcc = fcc_head; + NULL != fcc; + fcc = fcc->next) + { + if (at_limit) + break; + if (! fcc->limited) + continue; + fcc->limited = false; + /* done synchronously so that the active_inquiries + is updated immediately */ + download_charity_id (fcc); + } } if ( (! at_limit) && (0 == active_inquiries) && @@ -621,13 +664,14 @@ donau_charity_cb (void *cls, /** * Download the charity_id for a Donau instance. * - * @param cls closure with a `struct Donau *` + * @param cls closure with a `struct ForceCharityCtx *` */ static void download_charity_id (void *cls) { struct ForceCharityCtx *fcc = cls; + fcc->retry_task = NULL; /* nothing to do if a request is already outstanding */ if (NULL != fcc->h) return; @@ -638,6 +682,10 @@ download_charity_id (void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Cannot start more charity inquiries, already at limit\n"); + /* remember to re-drive this inquiry from end_inquiry() + once we are substantially below the limit again */ + fcc->limited = true; + at_limit = true; return; } @@ -655,6 +703,7 @@ download_charity_id (void *cls) if (NULL != fcc->h) { + fcc->retry_delay = GNUNET_TIME_UNIT_ZERO; active_inquiries++; } else @@ -662,8 +711,14 @@ download_charity_id (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to initiate DONAU_charity_get() for `%s'\n", fcc->donau_url); - /* we do NOT retry here – simply finish the (failed) inquiry */ - end_inquiry (); + /* no inquiry was started, so we must not call end_inquiry() here; + retry with exponential backoff instead */ + fcc->retry_delay + = GNUNET_TIME_STD_BACKOFF (fcc->retry_delay); + fcc->retry_task + = GNUNET_SCHEDULER_add_delayed (fcc->retry_delay, + &download_charity_id, + fcc); } } @@ -780,6 +835,12 @@ force_donau_charity_id (void *cls, fcc->donau_url); return; } + if (NULL != fcc->retry_task) + { + GNUNET_SCHEDULER_cancel (fcc->retry_task); + fcc->retry_task = NULL; + } + fcc->charity_id = charity_id; } download_charity_id (fcc); } @@ -894,6 +955,26 @@ shutdown_task (void *cls) d); GNUNET_free (d); } + while (NULL != fcc_head) + { + struct ForceCharityCtx *fcc = fcc_head; + + if (NULL != fcc->h) + { + DONAU_charity_get_cancel (fcc->h); + fcc->h = NULL; + } + if (NULL != fcc->retry_task) + { + GNUNET_SCHEDULER_cancel (fcc->retry_task); + fcc->retry_task = NULL; + } + GNUNET_CONTAINER_DLL_remove (fcc_head, + fcc_tail, + fcc); + GNUNET_free (fcc->donau_url); + GNUNET_free (fcc); + } if (NULL != eh) { TALER_MERCHANTDB_event_listen_cancel (eh);