Closes #932 `connect-timeout` gets replaced by an exponential backoff for the download timeout where the initial value is controlled by the setting `initial-connect-timeout`. Per iteration, the upper limit of the timeout is increased set to timeout := min(max_connect_timeout, initial_connect_timeout * 2^i) I decided to move the entire timeout / tracking of attempts into its own class to not make the filetransfer implementation more complex. Also, that allows us to write unit-tests for it. Setting `--download-attempts` to `0` is forbidden now and an exception will be thrown. For `--offline` we set it to `1`, the behavior is equivalent to what it was before: whether the max tries were exceeded is only checked after the first download exception got thrown, i.e. there's still one attempt being made. The end-result - with timeouts being caused by a wrongly set proxy - looks like this: $ env HTTPS_PROXY=1.1.1.1 nix store ping --store https://example.com warning: error: unable to download 'https://example.com/nix-cache-info': Connection timed out after 5006 milliseconds (curl error code=28); retrying in 422ms ms (attempt 1/5) warning: error: unable to download 'https://example.com/nix-cache-info': Connection timed out after 10010 milliseconds (curl error code=28); retrying in 1003ms ms (attempt 2/5) warning: error: unable to download 'https://example.com/nix-cache-info': Connection timed out after 20020 milliseconds (curl error code=28); retrying in 2018ms ms (attempt 3/5) warning: error: unable to download 'https://example.com/nix-cache-info': Connection timed out after 40007 milliseconds (curl error code=28); retrying in 4087ms ms (attempt 4/5) error: unable to download 'https://example.com/nix-cache-info': Connection timed out after 80074 milliseconds (curl error code=28) Change-Id: I9e8d08d78275bcf60080d663febc9e075243d36b
53 lines
1.4 KiB
C++
53 lines
1.4 KiB
C++
#include <gtest/gtest.h>
|
|
#include <lix/libutil/backoff.hh>
|
|
|
|
namespace nix {
|
|
TEST(Backoff, defaults)
|
|
{
|
|
auto initial = 5;
|
|
auto backoff = backoffTimeouts(
|
|
5, std::chrono::seconds(300), std::chrono::seconds(initial), std::chrono::milliseconds(1000)
|
|
);
|
|
|
|
BackoffTiming timings = *backoff.next();
|
|
ASSERT_EQ(10000, timings.downloadTimeout.count());
|
|
ASSERT_LE(1500, timings.waitTime.count());
|
|
ASSERT_GE(2500, timings.waitTime.count());
|
|
|
|
timings = *backoff.next();
|
|
ASSERT_EQ(20000, timings.downloadTimeout.count());
|
|
ASSERT_LE(3500, timings.waitTime.count());
|
|
ASSERT_GE(4500, timings.waitTime.count());
|
|
|
|
ASSERT_TRUE(backoff.next().has_value());
|
|
|
|
timings = *backoff.next();
|
|
ASSERT_EQ(80000, timings.downloadTimeout.count());
|
|
ASSERT_LE(15500, timings.waitTime.count());
|
|
ASSERT_GE(16500, timings.waitTime.count());
|
|
|
|
ASSERT_FALSE(backoff.next().has_value());
|
|
}
|
|
|
|
TEST(Backoff, capped)
|
|
{
|
|
auto initial = 10;
|
|
auto upper = 300;
|
|
auto backoff = backoffTimeouts(
|
|
7,
|
|
std::chrono::seconds(upper),
|
|
std::chrono::seconds(initial),
|
|
std::chrono::milliseconds(1000)
|
|
);
|
|
|
|
BackoffTiming timings = *backoff.next();
|
|
*backoff.next();
|
|
*backoff.next();
|
|
*backoff.next();
|
|
*backoff.next();
|
|
timings = *backoff.next();
|
|
ASSERT_EQ(300000, timings.downloadTimeout.count());
|
|
ASSERT_FALSE(backoff.next().has_value());
|
|
}
|
|
}
|