internal async Task SendAndReceiveAsync()

in code/OBAClient/Client/ClientHelper.cs [128:174]


        internal async Task<XDocument> SendAndReceiveAsync()
        {
            XDocument doc = null;

            // multiple retry attempts
            for (int i = 0; i < Constants.RequestRetryCount; i++)
            {
                try
                {
                    this.uriBuilder.Query = this.CreateQueryString();
                    doc = await this.SendAsync(this.uriBuilder.ToString());

                    // Verify that OBA sent us a valid document and that it's status code is 200:
                    int returnCode = doc.Root.GetFirstElementValue<int>("code");
                    if (returnCode != Convert.ToInt32(HttpStatusCode.OK))
                    {
                        string text = doc.Root.GetFirstElementValue<string>("text");
                        throw new ObaException(returnCode, text);
                    }

                    return doc;
                }
                catch (Exception e)
                {
                    // HTTP 401 or HTTP 429 from OBA servers means we were throttled due to requests not being spaced apart enough.
                    // HTTP 408 means server timeout.
                    // In both cases, retry after waiting.
                    if (e is ObaException &&
                        ((((ObaException)e).ErrorCode == Convert.ToInt32(HttpStatusCode.Unauthorized)) || (((ObaException)e).ErrorCode == 429) || (((ObaException)e).ErrorCode == Convert.ToInt32(HttpStatusCode.RequestTimeout))) &&
                        i < Constants.RequestRetryCount - 1)
                    {
                        // wait before trying again
                        int delay = Constants.MinimumThrottlingDelay * (i + 1);
                        delay = (delay < Constants.MinimumThrottlingDelay) ? Constants.MinimumThrottlingDelay : delay;
                        delay = (delay > Constants.MaximumThrottlingDelay) ? Constants.MaximumThrottlingDelay : delay;
                        await Task.Delay(delay);
                    }
                    else
                    {
                        throw new Exception("Failure on URI: " + this.uriBuilder.ToString(), e);
                    }
                }
            }

            // execution should never reach here
            throw new Exception("unreachable code has been reached");
        }