avoid using failing fallback package suppliers for 10 minutes
- still keep retrying primary package supplier
1 parent 42063af commit a3554dc7d1417364237afe7d4f2b8d4e3377c0d7
@Martin Nowak Martin Nowak authored on 23 Dec 2018
Showing 1 changed file
View
43
source/dub/packagesuppliers/fallback.d
import std.typecons : AutoImplement;
 
package abstract class AbstractFallbackPackageSupplier : PackageSupplier
{
protected PackageSupplier[] m_suppliers;
protected import core.time : minutes;
protected import std.datetime : Clock, SysTime;
 
static struct Pair { PackageSupplier ps; SysTime failTime; }
protected Pair[] m_suppliers;
 
this(PackageSupplier[] suppliers)
{
assert(suppliers.length);
m_suppliers = suppliers;
m_suppliers.length = suppliers.length;
foreach (i, ps; suppliers)
m_suppliers[i].ps = ps;
}
 
override @property string description()
{
import std.algorithm.iteration : map;
import std.format : format;
return format("%s (fallbacks %-(%s, %))", m_suppliers[0].description, m_suppliers[1 .. $].map!(x => x.description));
return format("%s (fallbacks %-(%s, %))", m_suppliers[0].ps.description,
m_suppliers[1 .. $].map!(pair => pair.ps.description));
}
 
// Workaround https://issues.dlang.org/show_bug.cgi?id=2525
abstract override Version[] getVersions(string package_id);
import dub.internal.vibecompat.core.log : logDiagnostic;
 
Exception firstEx;
try
return m_suppliers[0].%1$s(args);
return m_suppliers[0].ps.%1$s(args);
catch (Exception e)
{
logDiagnostic("Package supplier %%s failed with '%%s', trying fallbacks.",
m_suppliers[0].description, e.msg);
m_suppliers = m_suppliers[1 .. $];
m_suppliers[0].ps.description, e.msg);
firstEx = e;
}
 
foreach (fallback; m_suppliers)
immutable now = Clock.currTime;
foreach (ref pair; m_suppliers[1 .. $])
{
if (pair.failTime > now - 10.minutes)
continue;
try
{
scope (success) logDiagnostic("Fallback %%s succeeded", fallback.description);
return fallback.%1$s(args);
scope (success) logDiagnostic("Fallback %%s succeeded", pair.ps.description);
return pair.ps.%1$s(args);
}
catch(Exception e)
catch (Exception e)
{
pair.failTime = now;
logDiagnostic("Fallback package supplier %%s failed with '%%s'.",
fallback.description, e.msg);
m_suppliers = m_suppliers[1 .. $];
pair.ps.description, e.msg);
}
}
throw firstEx;
}.format(__traits(identifier, func));