merchant

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

commit 9e7328a389f25fe4500a0b45280c8b793be28bf1
parent bbe200d9b5686db6dd8f33a0edd31324efc94ec6
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 27 Apr 2025 23:28:01 +0200

work on #9780

Diffstat:
Msrc/backend/taler-merchant-depositcheck.c | 2++
Msrc/backend/taler-merchant-exchangekeyupdate.c | 29+++++++++++++++++++++--------
Msrc/backend/taler-merchant-httpd_exchanges.c | 3+++
Msrc/backend/taler-merchant-kyccheck.c | 2++
Msrc/backend/taler-merchant-reconciliation.c | 2++
Msrc/backenddb/Makefile.am | 1+
Asrc/backenddb/merchant-0017.sql | 35+++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_exchange_keys.c | 15++++++++++-----
Msrc/backenddb/pg_insert_exchange_keys.h | 7+++++--
Msrc/backenddb/pg_select_exchange_keys.c | 6+++++-
Msrc/backenddb/pg_select_exchange_keys.h | 2++
Msrc/include/taler_merchantdb_plugin.h | 6+++++-
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); /**