// Recursive, retry-logic, state-machine function public async Task <Todo> Start() { // let's keep track of our function's status Console.WriteLine(); Console.WriteLine("status: " + Status.ToString()); Console.WriteLine("retries: " + Retries.ToString()); // if Start() is called with the CircuitBreaker status being OPEN if (Status == Status.OPEN) { try { // lets do our initial call return(await Call().ConfigureAwait(false)); } catch (Exception badResponse) { // do something with bad_response... Console.WriteLine(badResponse.Message); // set status to HALFOPEN because our initial request failed Status = Status.HALFOPEN; Retries++; return(await Start().ConfigureAwait(false)); // retry with our Status being HALFOPEN } } // if Start() is called with the CircuitBreaker status being HALFOPEN if (Status == Status.HALFOPEN) { Console.WriteLine("TIMEOUT..."); Thread.Sleep(TimeOut); try { // try a call again return(await Call().ConfigureAwait(false)); } catch { if (Retries < RetryCount) // did we retry too many times already? { Retries++; return(await Start().ConfigureAwait(false)); // Start this function again with the same status HALFOPEN } // looks like we retried too many times, time to set status to CLOSED Status = Status.CLOSED; return(await Start().ConfigureAwait(false)); } } // if Start() is called with the CircuitBreaker status being CLOSED if (Status == Status.CLOSED) { // we throw our final error message throw new Exception($"CircuitBreaker failed for { Url} : { Retries} " + $"times: TimeOut { TimeOut}"); } return(await Start().ConfigureAwait(false)); // this should never be reached, but acts as a safety-net }