commit 9e7328a389f25fe4500a0b45280c8b793be28bf1
parent bbe200d9b5686db6dd8f33a0edd31324efc94ec6
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 27 Apr 2025 23:28:01 +0200
work on #9780
Diffstat:
12 files changed, 93 insertions(+), 17 deletions(-)
diff --git a/src/backend/taler-merchant-depositcheck.c b/src/backend/taler-merchant-depositcheck.c
@@ -950,6 +950,7 @@ update_exchange_keys (void *cls,
{
enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute earliest_retry;
if (NULL != keys)
{
@@ -958,6 +959,7 @@ update_exchange_keys (void *cls,
}
qs = db_plugin->select_exchange_keys (db_plugin->cls,
exchange_url,
+ &earliest_retry,
&keys);
if (qs < 0)
{
diff --git a/src/backend/taler-merchant-exchangekeyupdate.c b/src/backend/taler-merchant-exchangekeyupdate.c
@@ -287,10 +287,12 @@ add_restriction (json_t *restrictions,
* depending on the return value.
*
* @param keys information to persist
+ * @param first_retry earliest we may retry fetching the keys
* @return transaction status
*/
static enum GNUNET_DB_QueryStatus
-insert_keys_data (const struct TALER_EXCHANGE_Keys *keys)
+insert_keys_data (const struct TALER_EXCHANGE_Keys *keys,
+ struct GNUNET_TIME_Absolute first_retry)
{
enum GNUNET_DB_QueryStatus qs;
@@ -317,7 +319,8 @@ insert_keys_data (const struct TALER_EXCHANGE_Keys *keys)
}
qs = db_plugin->insert_exchange_keys (db_plugin->cls,
- keys);
+ keys,
+ first_retry);
if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -442,10 +445,12 @@ insert_keys_data (const struct TALER_EXCHANGE_Keys *keys)
* that may care about them).
*
* @param keys the keys to store
+ * @param first_retry earliest we may retry fetching the keys
* @return true on success
*/
static bool
-store_keys (struct TALER_EXCHANGE_Keys *keys)
+store_keys (struct TALER_EXCHANGE_Keys *keys,
+ struct GNUNET_TIME_Absolute first_retry)
{
enum GNUNET_DB_QueryStatus qs;
@@ -461,7 +466,8 @@ store_keys (struct TALER_EXCHANGE_Keys *keys)
return false;
}
- qs = insert_keys_data (keys);
+ qs = insert_keys_data (keys,
+ first_retry);
if (0 > qs)
{
db_plugin->rollback (db_plugin->cls);
@@ -507,6 +513,7 @@ cert_cb (
{
struct Exchange *e = cls;
struct GNUNET_TIME_Absolute n;
+ struct GNUNET_TIME_Absolute first_retry;
e->conn = NULL;
switch (kr->hr.http_status)
@@ -535,7 +542,10 @@ cert_cb (
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Got new keys for %s, updating database\n",
e->exchange_url);
- if (! store_keys (keys))
+ first_retry = GNUNET_TIME_relative_to_absolute (
+ EXCHANGE_MAXFREQ);
+ if (! store_keys (keys,
+ first_retry))
{
GNUNET_break (0);
break;
@@ -544,9 +554,7 @@ cert_cb (
/* Reset back-off */
e->retry_delay = EXCHANGE_MAXFREQ;
/* limit retry */
- e->first_retry
- = GNUNET_TIME_relative_to_absolute (
- EXCHANGE_MAXFREQ);
+ e->first_retry = first_retry;
/* Limit by expiration */
n = GNUNET_TIME_absolute_max (e->first_retry,
keys->key_data_expiration.abs_time);
@@ -599,6 +607,10 @@ download_keys (void *cls)
}
e->retry_delay
= GNUNET_TIME_STD_BACKOFF (e->retry_delay);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Downloading keys from %s (%s)\n",
+ e->exchange_url,
+ e->force_retry ? "forced" : "regular");
e->conn = TALER_EXCHANGE_get_keys (ctx,
e->exchange_url,
e->force_retry
@@ -825,6 +837,7 @@ accept_exchanges (void *cls,
qs = db_plugin->select_exchange_keys (db_plugin->cls,
url,
+ &e->first_retry,
&keys);
if (qs < 0)
{
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c
@@ -887,9 +887,11 @@ reload_exchange_keys (struct TMH_Exchange *exchange)
{
enum GNUNET_DB_QueryStatus qs;
struct TALER_EXCHANGE_Keys *keys;
+ struct GNUNET_TIME_Absolute first_retry;
qs = TMH_db->select_exchange_keys (TMH_db->cls,
exchange->url,
+ &first_retry,
&keys);
if (qs < 0)
{
@@ -907,6 +909,7 @@ reload_exchange_keys (struct TMH_Exchange *exchange)
"Loading latest keys of `%s' from database\n",
exchange->url);
exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
+ exchange->first_retry = first_retry;
if (NULL == exchange->currency)
exchange->currency = GNUNET_strdup (keys->currency);
if (0 != strcmp (keys->currency,
diff --git a/src/backend/taler-merchant-kyccheck.c b/src/backend/taler-merchant-kyccheck.c
@@ -1077,9 +1077,11 @@ find_keys (const char *exchange_url)
enum GNUNET_DB_QueryStatus qs;
struct TALER_EXCHANGE_Keys *keys;
struct Exchange *e;
+ struct GNUNET_TIME_Absolute first_retry;
qs = db_plugin->select_exchange_keys (db_plugin->cls,
exchange_url,
+ &first_retry,
&keys);
if (qs < 0)
{
diff --git a/src/backend/taler-merchant-reconciliation.c b/src/backend/taler-merchant-reconciliation.c
@@ -325,9 +325,11 @@ sync_keys (struct Exchange *e)
{
enum GNUNET_DB_QueryStatus qs;
struct TALER_EXCHANGE_Keys *keys;
+ struct GNUNET_TIME_Absolute first_retry;
qs = db_plugin->select_exchange_keys (db_plugin->cls,
e->exchange_url,
+ &first_retry,
&keys);
if (qs < 0)
{
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
@@ -33,6 +33,7 @@ sql_DATA = \
merchant-0014.sql \
merchant-0015.sql \
merchant-0016.sql \
+ merchant-0017.sql \
drop.sql
BUILT_SOURCES = \
diff --git a/src/backenddb/merchant-0017.sql b/src/backenddb/merchant-0017.sql
@@ -0,0 +1,35 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2025 Taler Systems SA
+--
+-- TALER is free software; you can redistribute it and/or modify it under the
+-- terms of the GNU General Public License as published by the Free Software
+-- Foundation; either version 3, or (at your option) any later version.
+--
+-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+-- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+--
+
+-- @file merchant-0015.sql
+-- @brief Tables for statistics
+-- @author Christian Grothoff
+
+
+BEGIN;
+
+-- Check patch versioning is in place.
+SELECT _v.register_patch('merchant-0017', NULL, NULL);
+
+SET search_path TO merchant;
+
+ALTER TABLE merchant_exchange_keys
+ ADD first_retry INT8 NOT NULL DEFAULT (0);
+
+COMMENT ON COLUMN merchant_exchange_keys.first_retry
+ IS 'Absolute time when this merchant may retry to fetch the keys from this exchange at the earliest';
+
+COMMIT;
diff --git a/src/backenddb/pg_insert_exchange_keys.c b/src/backenddb/pg_insert_exchange_keys.c
@@ -27,13 +27,16 @@
enum GNUNET_DB_QueryStatus
-TMH_PG_insert_exchange_keys (void *cls,
- const struct TALER_EXCHANGE_Keys *keys)
+TMH_PG_insert_exchange_keys (
+ void *cls,
+ const struct TALER_EXCHANGE_Keys *keys,
+ struct GNUNET_TIME_Absolute first_retry)
{
struct PostgresClosure *pg = cls;
json_t *jkeys = TALER_EXCHANGE_keys_to_json (keys);
struct GNUNET_PQ_QueryParam params[] = {
TALER_PQ_query_param_json (jkeys),
+ GNUNET_PQ_query_param_absolute_time (&first_retry),
GNUNET_PQ_query_param_timestamp (&keys->last_denom_issue_date),
GNUNET_PQ_query_param_string (keys->exchange_url),
GNUNET_PQ_query_param_end
@@ -45,16 +48,18 @@ TMH_PG_insert_exchange_keys (void *cls,
"insert_exchange_keys",
"INSERT INTO merchant_exchange_keys"
"(keys_json"
+ ",first_retry"
",expiration_time"
",exchange_url"
- ") VALUES ($1, $2, $3);");
+ ") VALUES ($1, $2, $3, $4);");
PREPARE (pg,
"update_exchange_keys",
"UPDATE merchant_exchange_keys SET"
" keys_json=$1"
- ",expiration_time=$2"
+ ",first_retry=$2"
+ ",expiration_time=$3"
" WHERE"
- " exchange_url=$3;");
+ " exchange_url=$4;");
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
"update_exchange_keys",
params);
diff --git a/src/backenddb/pg_insert_exchange_keys.h b/src/backenddb/pg_insert_exchange_keys.h
@@ -31,10 +31,13 @@
*
* @param cls plugin closure
* @param keys data to store
+ * @param first_retry earliest we may retry fetching the keys
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
-TMH_PG_insert_exchange_keys (void *cls,
- const struct TALER_EXCHANGE_Keys *keys);
+TMH_PG_insert_exchange_keys (
+ void *cls,
+ const struct TALER_EXCHANGE_Keys *keys,
+ struct GNUNET_TIME_Absolute first_retry);
#endif
diff --git a/src/backenddb/pg_select_exchange_keys.c b/src/backenddb/pg_select_exchange_keys.c
@@ -29,6 +29,7 @@
enum GNUNET_DB_QueryStatus
TMH_PG_select_exchange_keys (void *cls,
const char *exchange_url,
+ struct GNUNET_TIME_Absolute *first_retry,
struct TALER_EXCHANGE_Keys **keys)
{
struct PostgresClosure *pg = cls;
@@ -38,6 +39,8 @@ TMH_PG_select_exchange_keys (void *cls,
};
json_t *jkeys;
struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_absolute_time ("first_retry",
+ first_retry),
TALER_PQ_result_spec_json ("keys_json",
&jkeys),
GNUNET_PQ_result_spec_end
@@ -48,7 +51,8 @@ TMH_PG_select_exchange_keys (void *cls,
PREPARE (pg,
"select_exchange_keys",
"SELECT"
- " keys_json"
+ " first_retry"
+ ",keys_json"
" FROM merchant_exchange_keys"
" WHERE exchange_url=$1;");
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
diff --git a/src/backenddb/pg_select_exchange_keys.h b/src/backenddb/pg_select_exchange_keys.h
@@ -31,12 +31,14 @@
*
* @param cls plugin closure
* @param exchange_url base URL of the exchange
+ * @param[out] first_retry set to earliest we may retry fetching the keys
* @param[out] keys set to the keys of the exchange
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
TMH_PG_select_exchange_keys (void *cls,
const char *exchange_url,
+ struct GNUNET_TIME_Absolute *first_retry,
struct TALER_EXCHANGE_Keys **keys);
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
@@ -3664,12 +3664,14 @@ struct TALER_MERCHANTDB_Plugin
*
* @param cls plugin closure
* @param exchange_url base URL of the exchange
+ * @param[out] first_retry set to earliest we may retry fetching the keys
* @param[out] keys set to the keys of the exchange
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
(*select_exchange_keys)(void *cls,
const char *exchange_url,
+ struct GNUNET_TIME_Absolute *first_retry,
struct TALER_EXCHANGE_Keys **keys);
@@ -3678,11 +3680,13 @@ struct TALER_MERCHANTDB_Plugin
*
* @param cls plugin closure
* @param keys data to store
+ * @param first_retry earliest we may retry fetching the keys
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
(*insert_exchange_keys)(void *cls,
- const struct TALER_EXCHANGE_Keys *keys);
+ const struct TALER_EXCHANGE_Keys *keys,
+ struct GNUNET_TIME_Absolute first_retry);
/**