Use Validator List (VL) cache files in more scenarios

- If any [validator_list_keys] are not available after all
  [validator_list_sites] have had a chance to be queried, then fall
  back to loading cache files. Currently, cache files are only used if
  no sites are defined, or the request to one of them has an error. It
  does not include cases where not enough sites are defined, or if a
  site returns an invalid VL (or something else entirely).
- Resolves #5320
This commit is contained in:
Ed Hennis
2025-02-26 15:19:27 -05:00
parent b18dece145
commit a08910446a

View File

@@ -148,7 +148,12 @@ ValidatorSite::load(
{ {
try try
{ {
sites_.emplace_back(uri); // This is not super efficient, but it doesn't happen often.
bool found = std::ranges::any_of(sites_, [&uri](auto const& site) {
return site.loadedResource->uri == uri;
});
if (!found)
sites_.emplace_back(uri);
} }
catch (std::exception const& e) catch (std::exception const& e)
{ {
@@ -210,6 +215,17 @@ ValidatorSite::setTimer(
std::lock_guard<std::mutex> const& site_lock, std::lock_guard<std::mutex> const& site_lock,
std::lock_guard<std::mutex> const& state_lock) std::lock_guard<std::mutex> const& state_lock)
{ {
if (!sites_.empty() && //
std::ranges::all_of(sites_, [](auto const& site) {
return site.lastRefreshStatus.has_value();
}))
{
// If all of the sites have been handled at least once (including
// errors and timeouts), call missingSite, which will load the cache
// files for any lists that are still unavailable.
missingSite(site_lock);
}
auto next = std::min_element( auto next = std::min_element(
sites_.begin(), sites_.end(), [](Site const& a, Site const& b) { sites_.begin(), sites_.end(), [](Site const& a, Site const& b) {
return a.nextRefresh < b.nextRefresh; return a.nextRefresh < b.nextRefresh;
@@ -322,13 +338,16 @@ ValidatorSite::onRequestTimeout(std::size_t siteIdx, error_code const& ec)
// processes a network error. Usually, this function runs first, // processes a network error. Usually, this function runs first,
// but on extremely rare occasions, the response handler can run // but on extremely rare occasions, the response handler can run
// first, which will leave activeResource empty. // first, which will leave activeResource empty.
auto const& site = sites_[siteIdx]; auto& site = sites_[siteIdx];
if (site.activeResource) if (site.activeResource)
JLOG(j_.warn()) << "Request for " << site.activeResource->uri JLOG(j_.warn()) << "Request for " << site.activeResource->uri
<< " took too long"; << " took too long";
else else
JLOG(j_.error()) << "Request took too long, but a response has " JLOG(j_.error()) << "Request took too long, but a response has "
"already been processed"; "already been processed";
if (!site.lastRefreshStatus)
site.lastRefreshStatus.emplace(Site::Status{
clock_type::now(), ListDisposition::invalid, "timeout"});
} }
std::lock_guard lock_state{state_mutex_}; std::lock_guard lock_state{state_mutex_};