Search code examples
c#restsharppollyretry-logic

What is a decent method for re-trying after failed connection of GET, and POST HTTP Methods via RestSharp?


This C# Console application connects to a server using REST with RestSharp this pc where is hosted doesn't have a stable internet connection so sometimes connections go down and want to implement a loop of retry x times.

And they're called from another class Example Program.cs

Login()
{
    // Restsharp code
    // Restsharp receives response

    // based on RestSharp documentation StatusCode 0 means a failed connection usually on this internet is down or server is down.
    if(response.StatusCode == 0)
    {
        Logger.Error("Failed Connection")
        return null;
    }
}
Items GetItemsInventory()
{
    // Restsharp code
    // Restsharp receives response

    // based on RestSharp documentation StatusCode 0 means a failed connection usually on this internet is down or server is down.
    if(response.StatusCode == 0)
    {
        Logger.Error("Failed Connection")
        return null;
    }
    if(response.StatusCode == HttpStatusCode.BadRequest)
    {
        Logger.Error("Data is incorrect")
        return null;
    }
    if(response.StatusCode == HttpStatusCode.Created)
    {
        Logger.Info("Received Data Successfully")
        return Items;
    }
}
void PostItemsInventory()
{
    // Restsharp code
    // Restsharp receives response

    // based on RestSharp documentation StatusCode 0 means a failed connection usually because internet is down, firewall issue or server is down.
    if(response.StatusCode == 0)
    {
        Logger.Error("Failed Connection")
    }
    if(response.StatusCode == HttpStatusCode.BadRequest)
    {
        Logger.Error("Data is incorrect")
    }
    if(response.StatusCode == HttpStatusCode.Created)
    {
        Logger.Info("Data Sent Successfully")
        // does other stuff
    }
}

Program.cs call this methods

static void Main(string[] args)
{
    //gets login details
    Login();
    GetItemsInventory(Items);
    //does stuff
    PostItemsInventory(ItemsSold);
}

Where will be a good place or method to implement a retry of 'x' times only when RestSharp returns a StatusCode 0. I was thinking of a for loop inside each method or there is another way without a loop.


Solution

  • Retry in general

    First of all I want to emphasize that retry should not be applied blindly for everything. There are some operations, which by their nature, are not repeatable without side-effect(s). So, I suggest to review that are these requirements met for a given operation:

    • The potentially introduced observable impact is acceptable
    • The operation can be redone without any irreversible side effect
    • The introduced complexity is negligible compared to the promised reliability

    You should also be aware that if you don't receive a response it does not mean that the downstream system did not receive your request. The connection can be interrupted at any time of the request-response model. So, it might happen that the request is received, processed and even the response is sent out by the service but the requester did not receive any response.

    If the operation is idempotent because there is a de-duplication logic in place or the operation is by nature side-effect-free then you can try to re-issue the request to overcome transient network failure.

    Polly's Retry

    Polly is a dotNET resiliency library which allows you to define policies such as retry and then decorate with them any arbitrary method. In your particular example, you can define a retry policy which triggers whenever the received Status code is 0 and retries at most x times.

    var retryPolicy = Policy
                    .HandleResult<IRestResponse>(r => r.StatusCode == 0)
                    .WaitAndRetry(x, _ => TimeSpan.FromSeconds(1));
    

    Then you can decorate your RestClient's Execute method like this

    var response = retryPolicy.Execute(() => restClient.Execute(restRequest));