| |
---|
| | 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)); |
---|
| | |