abuzuhri / Amazon-SP-API-CSharp

.Net C# library for the new Amazon Selling Partner API
MIT License
215 stars 191 forks source link

Multiple error at GetOrders & GetOrderItems #646

Open babuscam opened 1 year ago

babuscam commented 1 year ago

Hello, I have the following situation with the 1.7.1 version:

builder.Services.AddSingleton<IAmazonConnectionManager, AmazonConnectionManager>();
 public interface IAmazonConnectionManager
    {
        AmazonConnection GetOrCreateConnection(string apiKey, AmaCredential.AmazonCredential amazonCredential);
    }

    public class AmazonConnectionManager : IAmazonConnectionManager
    {
        private readonly ConcurrentDictionary<string, (AmazonConnection connection, int credentialHash)> _connections = new();

        public AmazonConnection GetOrCreateConnection(string apiKey, AmaCredential.AmazonCredential amazonCredential)
        {
            int credentialHash = amazonCredential.GetHashCode();

            var credential = new AmazonCredential
            {
                AccessKey = amazonCredential.AccessKey,
                SecretKey = amazonCredential.SecretKey,
                RoleArn = amazonCredential.RoleArn,
                ClientId = amazonCredential.ClientId,
                ClientSecret = amazonCredential.ClientSecret,
                RefreshToken = amazonCredential.RefreshToken,
                MarketPlace = MarketPlace.GetMarketPlaceByID(amazonCredential.MarketPlace),
                SellerID = amazonCredential.SellerId
            };

            var connectionInfo = _connections.AddOrUpdate(apiKey,
                // If key does not exist, create new connection info
                key => new()
                {
                    connection = new AmazonConnection(credential),
                    credentialHash = credentialHash
                },
                //Check if the hash already saved in dictionary is the same with the credential received. If not, overwrite the connection in dictionary.
                //The credentials will change every 6 months due to Amazon policy of LWA token rotation
                (key, existingInfo) => existingInfo.credentialHash != credentialHash ? new()
                {
                    connection = new AmazonConnection(credential),
                    credentialHash = credentialHash
                } : existingInfo
            );
            return connectionInfo.connection;
        }
    }

During the job run, from time to time, I get the following errors just for one store(the lines with orange are the same store) image

Errors: Index was outside the bounds of the array. An item with the same key has already been added. Key: LastUpdatedAfter An item with the same key has already been added. Key: LastUpdatedAfter

Error getting LWA Access Token
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Net.Http.Headers.HttpHeaders.ReadStoreValues[T](Span`1 values, Object storeValue, HttpHeaderParser parser, Int32& currentIndex)
   at System.Net.Http.Headers.HttpHeaders.GetStoreValuesAsStringOrStringArray(HeaderDescriptor descriptor, Object sourceValues, String& singleValue, String[]& multiValue)
   at System.Net.Http.Headers.HttpHeaders.GetHeaderString(HeaderDescriptor descriptor)
   at RestSharp.RestResponse.<>c__DisplayClass0_0.<<FromHttpResponse>g__GetDefaultResponse|0>d.MoveNext()
--- End of stack trace from previous location ---
   at RestSharp.RestResponse.<>c__DisplayClass0_0.<<FromHttpResponse>g__GetDefaultResponse|0>d.MoveNext()
--- End of stack trace from previous location ---
   at RestSharp.RestResponse.FromHttpResponse(HttpResponseMessage httpResponse, RestRequest request, Encoding encoding, CookieCollection cookieCollection, CalculateResponseStatus calculateResponseStatus, CancellationToken cancellationToken)
   at RestSharp.RestClient.ExecuteAsync(RestRequest request, CancellationToken cancellationToken)
   at FikaAmazonAPI.AmazonSpApiSDK.Runtime.LWAClient.GetAccessTokenAsync(CancellationToken cancellationToken)
Error getting LWA Access Token
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Net.Http.Headers.HttpHeaders.ReadStoreValues[T](Span`1 values, Object storeValue, HttpHeaderParser parser, Int32& currentIndex)
   at System.Net.Http.Headers.HttpHeaders.GetStoreValuesAsStringOrStringArray(HeaderDescriptor descriptor, Object sourceValues, String& singleValue, String[]& multiValue)
   at System.Net.Http.Headers.HttpHeaders.GetHeaderString(HeaderDescriptor descriptor)
   at RestSharp.RestResponse.<>c__DisplayClass0_0.<<FromHttpResponse>g__GetDefaultResponse|0>d.MoveNext()
--- End of stack trace from previous location ---
   at RestSharp.RestResponse.<>c__DisplayClass0_0.<<FromHttpResponse>g__GetDefaultResponse|0>d.MoveNext()
--- End of stack trace from previous location ---
   at RestSharp.RestResponse.FromHttpResponse(HttpResponseMessage httpResponse, RestRequest request, Encoding encoding, CookieCollection cookieCollection, CalculateResponseStatus calculateResponseStatus, CancellationToken cancellationToken)
   at RestSharp.RestClient.ExecuteAsync(RestRequest request, CancellationToken cancellationToken)
   at FikaAmazonAPI.AmazonSpApiSDK.Runtime.LWAClient.GetAccessTokenAsync(CancellationToken cancellationToken)

Is this because I am making in the same time 2 requests for the same endpoint? And why is not failing for all the stores in this case?

TechyChap commented 1 year ago

Yes, it's not possible to make two concurrent connections to Amazon from the same Connection.

We've resolved this using a shared semaphore.

e.g.

if (await _semaphoreSlim.WaitAsync(30000, cancellationToken))
{
    // Some call the the connection
}

The answer to why does this only happen some times is "timing".