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
					
				
					 4 changed files with 48 additions and 1 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue