recurly / recurly-client-dotnet

A .NET API wrapper for Recurly.
https://developers.recurly.com
MIT License
86 stars 80 forks source link

SSL connection in async execution #832

Open kaiserbergin opened 6 months ago

kaiserbergin commented 6 months ago

Description

When executing multiple client calls via Task.WhenAll with the message The SSL connection could not be established, see inner exception., but the inner exception is null. Retry policies are a workaround at this point, but I'd like to understand the issue better, and understand what the inner exception should / could be.

Error Message: The SSL connection could not be established, see inner exception. Inner Exception: null Stack Trace:

   at Recurly.BaseClient.HandleResponse(IRestResponse resp)
   at Recurly.BaseClient.<>c__DisplayClass18_0`1.<MakeRequestAsync>b__0(Task`1 t)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Recurly.BaseClient.MakeRequestAsync[T](Method method, String url, Request body, Dictionary`2 queryParams, RequestOptions options, CancellationToken cancellationToken)

To Reproduce

Roughly what I'm doing, sans the resiliency policies, exception handling, and application logic:

var client = new Client(apiKey);
var @params = new ListInvoiceCouponRedemptionsParams
        {
            Sort = TimestampSort.UpdatedAt,
            BeginTime =  DateTimeOffset.Now.AddDays(-1),
            EndTime =  DateTimeOffset.Now,
        };

// Doing fifty invoice id's at a time from a larger batch
foreach (var taskChunk in idChunk.Chunk(50))
{
    var tasks = taskChunk.Select(async id =>
    {
        // Tried with newing up client or reusing, same issue applies...
        Pager<CouponRedemption> pager = client.ListInvoiceCouponRedemptions(id, @params);

        while (pager.HasMore)
        {
           // error happens here
           await pager.FetchNextPageAsync(cancellationToken).ConfigureAwait(false);
        }    
    });

    await Task.WhenAll(tasks);
}

Expected behavior

Your Environment