aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-08-10 12:39:47 +0200
committerChristian Grothoff <christian@grothoff.org>2018-08-10 12:39:47 +0200
commit866df0fb66fb4a7c472c54e2a1ea1981334612c3 (patch)
tree7135f6f527930596249b07e86a20737f934c3315 /src
parent04055de75a7ea909c5c04af096e50a93d6bca727 (diff)
add retry support to withdraw test logic
Diffstat (limited to 'src')
-rw-r--r--src/exchange-lib/testing_api_cmd_withdraw.c95
-rw-r--r--src/include/taler_testing_lib.h12
2 files changed, 106 insertions, 1 deletions
diff --git a/src/exchange-lib/testing_api_cmd_withdraw.c b/src/exchange-lib/testing_api_cmd_withdraw.c
index 35c5a50ef..c70754999 100644
--- a/src/exchange-lib/testing_api_cmd_withdraw.c
+++ b/src/exchange-lib/testing_api_cmd_withdraw.c
@@ -24,6 +24,7 @@
*/
#include "platform.h"
#include "taler_json_lib.h"
+#include <microhttpd.h>
#include <gnunet/gnunet_curl_lib.h>
#include "exchange_api_handle.h"
#include "taler_signatures.h"
@@ -88,14 +89,61 @@ struct WithdrawState
struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
/**
+ * Task scheduled to try later.
+ */
+ struct GNUNET_SCHEDULER_Task *retry_task;
+
+ /**
+ * How long do we wait until we retry?
+ */
+ struct GNUNET_TIME_Relative backoff;
+
+ /**
* Expected HTTP response code to the request.
*/
unsigned int expected_response_code;
+ /**
+ * Was this command modified via
+ * #TALER_TESTING_cmd_withdraw_with_retry to
+ * enable retries?
+ */
+ int do_retry;
+
};
/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the commaind being run.
+ * @param is interpreter state.
+ */
+static void
+withdraw_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is);
+
+
+/**
+ * Task scheduled to re-try #withdraw_run.
+ *
+ * @param cls a `struct WithdrawState`
+ */
+static void
+do_retry (void *cls)
+{
+ struct WithdrawState *ws = cls;
+
+ ws->retry_task = NULL;
+ withdraw_run (ws,
+ NULL,
+ ws->is);
+}
+
+
+/**
* "reserve withdraw" operation callback; checks that the
* response code is expected and store the exchange signature
* in the state.
@@ -119,6 +167,24 @@ reserve_withdraw_cb (void *cls,
ws->wsh = NULL;
if (ws->expected_response_code != http_status)
{
+ if (GNUNET_YES == ws->do_retry)
+ {
+ if ( (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
+ (TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == ec) ||
+ (TALER_EC_WITHDRAW_RESERVE_UNKNOWN == ec) ||
+ (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
+ {
+ /* on DB conflicts, do not use backoff */
+ if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
+ ws->backoff = GNUNET_TIME_UNIT_ZERO;
+ else
+ ws->backoff = GNUNET_TIME_STD_BACKOFF (ws->backoff);
+ ws->retry_task = GNUNET_SCHEDULER_add_delayed (ws->backoff,
+ &do_retry,
+ ws);
+ return;
+ }
+ }
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d to command %s in %s:%u\n",
http_status,
@@ -164,7 +230,7 @@ reserve_withdraw_cb (void *cls,
* Run the command.
*
* @param cls closure.
- * @param cmd the commaind being run.
+ * @param cmd the command being run, NULL when called from #do_retry()
* @param is interpreter state.
*/
static void
@@ -176,6 +242,7 @@ withdraw_run (void *cls,
struct TALER_ReservePrivateKeyP *rp;
const struct TALER_TESTING_Command *create_reserve;
+ (void) cmd;
create_reserve = TALER_TESTING_interpreter_lookup_command
(is, ws->reserve_reference);
if (NULL == create_reserve)
@@ -232,6 +299,11 @@ withdraw_cleanup (void *cls,
TALER_EXCHANGE_reserve_withdraw_cancel (ws->wsh);
ws->wsh = NULL;
}
+ if (NULL != ws->retry_task)
+ {
+ GNUNET_SCHEDULER_cancel (ws->retry_task);
+ ws->retry_task = NULL;
+ }
if (NULL != ws->sig.rsa_signature)
{
GNUNET_CRYPTO_rsa_signature_free (ws->sig.rsa_signature);
@@ -413,4 +485,25 @@ TALER_TESTING_cmd_withdraw_denomination
return cmd;
}
+
+/**
+ * Modify a withdraw command to enable retries when the
+ * reserve is not yet full or we get other transient
+ * errors from the exchange.
+ *
+ * @param cmd a withdraw command
+ * @return the command with retries enabled
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd)
+{
+ struct WithdrawState *ws;
+
+ GNUNET_assert (&withdraw_run == cmd.run);
+ ws = cmd.cls;
+ ws->do_retry = GNUNET_YES;
+ return cmd;
+}
+
+
/* end of testing_api_cmd_withdraw.c */
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 708d73405..71bc8cdca 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -737,6 +737,18 @@ TALER_TESTING_cmd_withdraw_denomination
/**
+ * Modify a withdraw command to enable retries when the
+ * reserve is not yet full or we get other transient
+ * errors from the exchange.
+ *
+ * @param cmd a withdraw command
+ * @return the command with retries enabled
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd);
+
+
+/**
* Create a "wire" command.
*
* @param label the command label.