mirror of
https://github.com/NixOS/nix
synced 2025-06-30 07:33:16 +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.
This commit is contained in:
parent
15fa70cd1b
commit
a67cf5a358
7 changed files with 156 additions and 119 deletions
38
src/libutil/retry.hh
Normal file
38
src/libutil/retry.hh
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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) \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue