Ленивое разрешение тайм-аута. Автоматический выключатель выдает исключение ArgumentOutOfRangeException.
-
19-09-2019 - |
Вопрос
Айенде опубликовало модификация к Дэви Брайону автоматический выключатель, при этом он изменил разрешение тайм-аута на ленивую модель.
private readonly DateTime expiry;
public OpenState(CircuitBreaker outer)
: base(outer)
{
expiry = DateTime.UtcNow + outer.timeout;
}
public override void ProtectedCodeIsAboutToBeCalled()
{
if(DateTime.UtcNow < expiry)
throw new OpenCircuitException();
outer.MoveToHalfOpenState();
}
Однако, конструктор может потерпеть неудачу потому что TimeSpan
может быстро переполнить максимальное значение DateTime
.Например, когда время ожидания автоматического выключателя равно максимальному значению TimeSpan.
Обнаружено исключение System.ArgumentOutOfRangeException.
Message="Добавленное или вычтенное значение приводит к непредставимому значению DateTime."
...
в System.DateTime.op_Addition(DateTime d, TimeSpan t)
Как нам избежать этой проблемы и сохранить ожидаемое поведение?
Решение
Посчитайте немного математики
Определите, если таймаут больше остатка максимального значения a DateTime
и нынешний DateTime
.Максимум TimeSpan
обычно указывает функционально бесконечный тайм-аут (что делает это «одноразовым» автоматическим выключателем).
public OpenState(CircuitBreaker outer)
: base(outer)
{
DateTime now = DateTime.UtcNow;
expiry = outer.Timeout > (DateTime.MaxValue - now)
? DateTime.MaxValue
: now + outer.Timeout;
}