1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 00:11:17 +02:00

Fix 'error 9 while decompressing xz file'

Once we've started writing data to a Sink, we can't restart a download
request, because then we end up writing duplicate data to the
Sink. Therefore we shouldn't handle retries in Downloader but at a
higher level (in particular, in copyStorePath()).

Fixes #2952.

(cherry picked from commit a67cf5a358)
This commit is contained in:
Eelco Dolstra 2019-06-24 21:48:52 +02:00
parent 2fef4dd296
commit 78fa47a7f0
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
7 changed files with 156 additions and 119 deletions

38
src/libutil/retry.hh Normal file
View file

@ -0,0 +1,38 @@
#pragma once
#include "logging.hh"
#include <functional>
#include <cmath>
#include <random>
#include <thread>
namespace nix {
inline unsigned int retrySleepTime(unsigned int attempt)
{
std::random_device rd;
std::mt19937 mt19937;
return 250.0 * std::pow(2.0f,
attempt - 1 + std::uniform_real_distribution<>(0.0, 0.5)(mt19937));
}
template<typename C>
C retry(unsigned int attempts, std::function<C()> && f)
{
unsigned int attempt = 0;
while (true) {
try {
return f();
} catch (BaseError & e) {
++attempt;
if (attempt >= attempts || !e.isTransient())
throw;
auto ms = retrySleepTime(attempt);
warn("%s; retrying in %d ms", e.what(), ms);
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
}
}
}

View file

@ -109,6 +109,8 @@ public:
const string & msg() const { return err; }
const string & prefix() const { return prefix_; }
BaseError & addPrefix(const FormatOrString & fs);
virtual bool isTransient() { return false; }
};
#define MakeError(newClass, superClass) \