Question

Ayende posted a modification to Davy Brion's circuit breaker, wherein he changed the timeout resolution to a lazy model.

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

However, the constructor can fail because a TimeSpan can quickly overflow the maximum value of a DateTime. For example, when the circuit breaker’s timeout is the maximum value of a TimeSpan.

System.ArgumentOutOfRangeException was caught

Message="The added or subtracted value results in an un-representable DateTime."

...

at System.DateTime.op_Addition(DateTime d, TimeSpan t)

How do we avoid this problem and maintain the expected behavior?

Was it helpful?

Solution

Do a little bit of math

Determine if the timeout is greater than the remainder of the maximum value of a DateTime and the current DateTime. A maximum TimeSpan usually indicates a functionally infinite timeout (making this a "one-time" circuit breaker).

public OpenState(CircuitBreaker outer)
    : base(outer)
{
    DateTime now = DateTime.UtcNow;
    expiry = outer.Timeout > (DateTime.MaxValue - now) 
        ? DateTime.MaxValue
        : now + outer.Timeout;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top