aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-02-24 13:53:09 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-24 13:53:19 +0100
commitfd9ba53c492835b52bd75a5ae113b7bcc81fe161 (patch)
treeccb61b10436e0fdc5cb068595fad26e910bdabb2
parent10b9023575b14e581cfd952b75039e71488f5a8f (diff)
make_coin_known can experience serialization failures, add retry logic
-rw-r--r--src/exchange/taler-exchange-httpd_db.c13
-rw-r--r--src/exchange/taler-exchange-httpd_db.h13
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c24
-rw-r--r--src/exchange/taler-exchange-httpd_melt.c23
4 files changed, 48 insertions, 25 deletions
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index f621d8c87..d383c471d 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -29,19 +29,6 @@
#include "taler-exchange-httpd_responses.h"
-/**
- * How often should we retry a transaction before giving up
- * (for transactions resulting in serialization/dead locks only).
- *
- * The current value is likely too high for production. We might want to
- * benchmark good values once we have a good database setup. The code is
- * expected to work correctly with any positive value, albeit inefficiently if
- * we too aggressively force clients to retry the HTTP request merely because
- * we have database serialization issues.
- */
-#define MAX_TRANSACTION_COMMIT_RETRIES 100
-
-
enum GNUNET_DB_QueryStatus
TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
struct MHD_Connection *connection,
diff --git a/src/exchange/taler-exchange-httpd_db.h b/src/exchange/taler-exchange-httpd_db.h
index 7c954ffe1..bca97cf0a 100644
--- a/src/exchange/taler-exchange-httpd_db.h
+++ b/src/exchange/taler-exchange-httpd_db.h
@@ -28,6 +28,19 @@
/**
+ * How often should we retry a transaction before giving up
+ * (for transactions resulting in serialization/dead locks only).
+ *
+ * The current value is likely too high for production. We might want to
+ * benchmark good values once we have a good database setup. The code is
+ * expected to work correctly with any positive value, albeit inefficiently if
+ * we too aggressively force clients to retry the HTTP request merely because
+ * we have database serialization issues.
+ */
+#define MAX_TRANSACTION_COMMIT_RETRIES 100
+
+
+/**
* Ensure coin is known in the database, and handle conflicts and errors.
*
* @param coin the coin to make known
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index ea319f23a..66cbe04ca 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -442,12 +442,24 @@ TEH_handler_deposit (struct MHD_Connection *connection,
enum GNUNET_DB_QueryStatus qs;
/* make sure coin is 'known' in database */
- qs = TEH_make_coin_known (&deposit.coin,
- connection,
- &dc.known_coin_id,
- &mhd_ret);
- /* no transaction => no serialization failures should be possible */
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++)
+ {
+ qs = TEH_make_coin_known (&deposit.coin,
+ connection,
+ &dc.known_coin_id,
+ &mhd_ret);
+ /* no transaction => no serialization failures should be possible */
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ "make_coin_known");
+ }
if (qs < 0)
return mhd_ret;
}
diff --git a/src/exchange/taler-exchange-httpd_melt.c b/src/exchange/taler-exchange-httpd_melt.c
index 049fd09a0..4db1b2469 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -237,12 +237,23 @@ database_melt (struct MHD_Connection *connection,
MHD_RESULT mhd_ret = MHD_NO;
enum GNUNET_DB_QueryStatus qs;
- qs = TEH_make_coin_known (&rmc->refresh_session.coin,
- connection,
- &rmc->known_coin_id,
- &mhd_ret);
- /* no transaction => no serialization failures should be possible */
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
+ for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++)
+ {
+ qs = TEH_make_coin_known (&rmc->refresh_session.coin,
+ connection,
+ &rmc->known_coin_id,
+ &mhd_ret);
+ if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
+ break;
+ }
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ {
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ "make_coin_known");
+ }
if (qs < 0)
return mhd_ret;
}