If fallback is enabled, temporarily disable substituters after a failure
Otherwise, we just keep asking the substituter for other .narinfo files, which can take a very long time due to retries/timeouts.
This commit is contained in:
parent
33c3f91885
commit
bba3f0a308
|
@ -3682,6 +3682,12 @@ void SubstitutionGoal::tryNext()
|
||||||
} catch (InvalidPath &) {
|
} catch (InvalidPath &) {
|
||||||
tryNext();
|
tryNext();
|
||||||
return;
|
return;
|
||||||
|
} catch (SubstituterDisabled &) {
|
||||||
|
if (settings.tryFallback) {
|
||||||
|
tryNext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw;
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
if (settings.tryFallback) {
|
if (settings.tryFallback) {
|
||||||
printError(e.what());
|
printError(e.what());
|
||||||
|
|
|
@ -13,6 +13,14 @@ private:
|
||||||
|
|
||||||
Path cacheUri;
|
Path cacheUri;
|
||||||
|
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
bool enabled = true;
|
||||||
|
std::chrono::steady_clock::time_point disabledUntil;
|
||||||
|
};
|
||||||
|
|
||||||
|
Sync<State> _state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HttpBinaryCacheStore(
|
HttpBinaryCacheStore(
|
||||||
|
@ -46,8 +54,33 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void maybeDisable()
|
||||||
|
{
|
||||||
|
auto state(_state.lock());
|
||||||
|
if (state->enabled && settings.tryFallback) {
|
||||||
|
int t = 60;
|
||||||
|
printError("disabling binary cache '%s' for %s seconds", getUri(), t);
|
||||||
|
state->enabled = false;
|
||||||
|
state->disabledUntil = std::chrono::steady_clock::now() + std::chrono::seconds(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkEnabled()
|
||||||
|
{
|
||||||
|
auto state(_state.lock());
|
||||||
|
if (state->enabled) return;
|
||||||
|
if (std::chrono::steady_clock::now() > state->disabledUntil) {
|
||||||
|
state->enabled = true;
|
||||||
|
debug("re-enabling binary cache '%s'", getUri());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw SubstituterDisabled("substituter '%s' is disabled", getUri());
|
||||||
|
}
|
||||||
|
|
||||||
bool fileExists(const std::string & path) override
|
bool fileExists(const std::string & path) override
|
||||||
{
|
{
|
||||||
|
checkEnabled();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DownloadRequest request(cacheUri + "/" + path);
|
DownloadRequest request(cacheUri + "/" + path);
|
||||||
request.head = true;
|
request.head = true;
|
||||||
|
@ -59,6 +92,7 @@ protected:
|
||||||
bucket is unlistable, so treat 403 as 404. */
|
bucket is unlistable, so treat 403 as 404. */
|
||||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
||||||
return false;
|
return false;
|
||||||
|
maybeDisable();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,12 +120,14 @@ protected:
|
||||||
|
|
||||||
void getFile(const std::string & path, Sink & sink) override
|
void getFile(const std::string & path, Sink & sink) override
|
||||||
{
|
{
|
||||||
|
checkEnabled();
|
||||||
auto request(makeRequest(path));
|
auto request(makeRequest(path));
|
||||||
try {
|
try {
|
||||||
getDownloader()->download(std::move(request), sink);
|
getDownloader()->download(std::move(request), sink);
|
||||||
} catch (DownloadError & e) {
|
} catch (DownloadError & e) {
|
||||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
||||||
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri());
|
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache '%s'", path, getUri());
|
||||||
|
maybeDisable();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,15 +135,18 @@ protected:
|
||||||
void getFile(const std::string & path,
|
void getFile(const std::string & path,
|
||||||
Callback<std::shared_ptr<std::string>> callback) override
|
Callback<std::shared_ptr<std::string>> callback) override
|
||||||
{
|
{
|
||||||
|
checkEnabled();
|
||||||
|
|
||||||
auto request(makeRequest(path));
|
auto request(makeRequest(path));
|
||||||
|
|
||||||
getDownloader()->enqueueDownload(request,
|
getDownloader()->enqueueDownload(request,
|
||||||
{[callback](std::future<DownloadResult> result) {
|
{[callback, this](std::future<DownloadResult> result) {
|
||||||
try {
|
try {
|
||||||
callback(result.get().data);
|
callback(result.get().data);
|
||||||
} catch (DownloadError & e) {
|
} catch (DownloadError & e) {
|
||||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
||||||
return callback(std::shared_ptr<std::string>());
|
return callback(std::shared_ptr<std::string>());
|
||||||
|
maybeDisable();
|
||||||
callback.rethrow();
|
callback.rethrow();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
callback.rethrow();
|
callback.rethrow();
|
||||||
|
|
|
@ -880,6 +880,7 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
|
||||||
narInfo ? narInfo->fileSize : 0,
|
narInfo ? narInfo->fileSize : 0,
|
||||||
info->narSize};
|
info->narSize};
|
||||||
} catch (InvalidPath) {
|
} catch (InvalidPath) {
|
||||||
|
} catch (SubstituterDisabled) {
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
if (settings.tryFallback)
|
if (settings.tryFallback)
|
||||||
printError(e.what());
|
printError(e.what());
|
||||||
|
|
|
@ -23,6 +23,7 @@ MakeError(BuildError, Error) /* denotes a permanent build failure */
|
||||||
MakeError(InvalidPath, Error)
|
MakeError(InvalidPath, Error)
|
||||||
MakeError(Unsupported, Error)
|
MakeError(Unsupported, Error)
|
||||||
MakeError(SubstituteGone, Error)
|
MakeError(SubstituteGone, Error)
|
||||||
|
MakeError(SubstituterDisabled, Error)
|
||||||
|
|
||||||
|
|
||||||
struct BasicDerivation;
|
struct BasicDerivation;
|
||||||
|
|
Loading…
Reference in a new issue