diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c index c7dbdb4d8..4a664da52 100644 --- a/src/benchmark/taler-exchange-benchmark.c +++ b/src/benchmark/taler-exchange-benchmark.c @@ -70,13 +70,14 @@ enum BenchmarkError { #define FIRST_INSTRUCTION -1 #define CMD_TRANSFER_TO_EXCHANGE(label, amount) \ - TALER_TESTING_cmd_fakebank_transfer (label, amount, \ + TALER_TESTING_cmd_fakebank_transfer_retry \ + (TALER_TESTING_cmd_fakebank_transfer (label, amount, \ exchange_bank_account.bank_base_url, \ USER_ACCOUNT_NUMBER, \ exchange_bank_account.no, \ "dummy_user", \ "dummy_password", \ - "http://example.com/") + "http://example.com/")) /** * Information about an account extracted from a payto://-URL. diff --git a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c index 28449d519..4e7812aec 100644 --- a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c +++ b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c @@ -120,9 +120,56 @@ struct FakebankTransferState * transfer subject). */ const char *config_filename; + + /** + * Task scheduled to try later. + */ + struct GNUNET_SCHEDULER_Task *retry_task; + + /** + * How long do we wait until we retry? + */ + struct GNUNET_TIME_Relative backoff; + + /** + * Was this command modified via + * #TALER_TESTING_cmd_fakebank_transfer_with_retry to + * enable retries? + */ + int do_retry; }; +/** + * Run the "fakebank transfer" CMD. + * + * @param cls closure. + * @param cmd CMD being run. + * @param is interpreter state. + */ +static void +fakebank_transfer_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is); + + +/** + * Task scheduled to re-try #fakebank_transfer_run. + * + * @param cls a `struct FakebankTransferState` + */ +static void +do_retry (void *cls) +{ + struct FakebankTransferState *fts = cls; + + fts->retry_task = NULL; + fakebank_transfer_run (fts, + NULL, + fts->is); +} + + /** * This callback will process the fakebank response to the wire * transfer. It just checks whether the HTTP response code is @@ -151,6 +198,27 @@ add_incoming_cb (void *cls, fts->serial_id = serial_id; if (MHD_HTTP_OK != http_status) { + if (GNUNET_YES == fts->do_retry) + { + if ( (0 == http_status) || + (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) || + (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Retrying fakebank transfer failed with %u/%d\n", + http_status, + (int) ec); + /* on DB conflicts, do not use backoff */ + if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) + fts->backoff = GNUNET_TIME_UNIT_ZERO; + else + fts->backoff = GNUNET_TIME_STD_BACKOFF (fts->backoff); + fts->retry_task = GNUNET_SCHEDULER_add_delayed (fts->backoff, + &do_retry, + fts); + return; + } + } GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fakebank returned HTTP status %u/%d\n", @@ -328,6 +396,11 @@ fakebank_transfer_cleanup (void *cls, cmd->label); TALER_BANK_admin_add_incoming_cancel (fts->aih); } + if (NULL != fts->retry_task) + { + GNUNET_SCHEDULER_cancel (fts->retry_task); + fts->retry_task = NULL; + } GNUNET_free (fts); } @@ -633,4 +706,24 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance return cmd; } + +/** + * Modify a fakebank transfer command to enable retries when the + * reserve is not yet full or we get other transient errors from the + * fakebank. + * + * @param cmd a fakebank transfer command + * @return the command with retries enabled + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd) +{ + struct FakebankTransferState *fts; + + GNUNET_assert (&fakebank_transfer_run == cmd.run); + fts = cmd.cls; + fts->do_retry = GNUNET_YES; + return cmd; +} + /* end of testing_api_cmd_fakebank_transfer.c */ diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 0db27d0e6..83523dfc4 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -620,6 +620,7 @@ TALER_TESTING_cmd_fakebank_transfer_with_ref const char *ref, const char *exchange_url); + /** * Create "fakebank transfer" CMD, letting the caller specifying * the merchant instance. This version is useful when a tip @@ -664,6 +665,19 @@ TALER_TESTING_cmd_fakebank_transfer_with_instance const char *exchange_url, const char *config_filename); + +/** + * Modify a fakebank transfer command to enable retries when the + * reserve is not yet full or we get other transient errors from the + * fakebank. + * + * @param cmd a fakebank transfer command + * @return the command with retries enabled + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd); + + /** * Make a "wirewatch" CMD. *