Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQS Timeouts not firing when using async ReceiveMessageAsync #609

Closed
jakejscott opened this issue Apr 2, 2017 · 5 comments
Closed

SQS Timeouts not firing when using async ReceiveMessageAsync #609

jakejscott opened this issue Apr 2, 2017 · 5 comments
Labels
feature-request A feature should be added or improved. guidance Question that needs advice or information.

Comments

@jakejscott
Copy link

Timeout exceptions are not being thrown when I configure the SQS client with a 10 second timeout, and a long polling time of 20 seconds. Here is the sample code:

using System;
using System.Net;
using System.Threading.Tasks;
using Amazon;
using Amazon.Runtime;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace ConsoleApp1
{
    public class Program
    {
        static void Main(string[] args)
        {
            TaskScheduler.UnobservedTaskException += (sender, eventArgs) =>
            {
                Console.Error.WriteLine("UnobservedTaskException event");
            };

            try
            {
                Task.Run(async () =>
                {
                    var accessKey = Environment.GetEnvironmentVariable("MY_AWS_ACCESSKEY");
                    var secretKey = Environment.GetEnvironmentVariable("MY_AWS_SECRETKEY");
                    var queueUrl = Environment.GetEnvironmentVariable("MY_QUEUEURL");

                    var credentials = new BasicAWSCredentials(accessKey, secretKey);

                    AWSConfigs.LoggingConfig.LogMetrics = true;
                    AWSConfigs.LoggingConfig.LogResponses = ResponseLoggingOption.Always;
                    AWSConfigs.LoggingConfig.LogTo = LoggingOptions.Console;
                    AWSConfigs.LoggingConfig.LogMetricsFormat = LogMetricsFormatOption.Standard;

                    var clientConfig = new AmazonSQSConfig
                    {
                        RegionEndpoint = RegionEndpoint.APSoutheast2,
                        Timeout = TimeSpan.FromSeconds(10),                 // Default value is 100 seconds
                        ReadWriteTimeout = TimeSpan.FromSeconds(30),        // Default value is 300 seconds
                        MaxErrorRetry = 0,                                  // Default value is 4 retries
                        ThrottleRetries = false                             // Default value is true
                    };

                    IAmazonSQS sqs = new AmazonSQSClient(credentials, clientConfig);

                    var request = new ReceiveMessageRequest
                    {
                        QueueUrl = queueUrl,
                        MaxNumberOfMessages = 1,
                        WaitTimeSeconds = 20,
                    };

                    Console.WriteLine("Polling SQS...");
                    ReceiveMessageResponse response = await sqs.ReceiveMessageAsync(request);

                    if (response.HttpStatusCode == HttpStatusCode.OK)
                    {
                        Console.WriteLine("Response OK");
                    }
                    else
                    {
                        Console.WriteLine("Response Failed");
                    }
                })
                .GetAwaiter().GetResult();

                
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.WriteLine("Done");
            Console.ReadLine();
        }
    }
}
@jakejscott
Copy link
Author

How this came about: I was testing long polling and disconnecting myself from the internet... and something bad happened.....no timeouts. I would have expected the code to throw after some amount of time but it doesn't. It just sits there forever if I don't reconnect to the internet. When I use the normal sync APIs timeouts are thrown as you would expect.

@jakejscott
Copy link
Author

I'm using the following version of the librarys

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AWSSDK.Core" version="3.3.10.3" targetFramework="net452" />
  <package id="AWSSDK.SQS" version="3.3.1.11" targetFramework="net452" />
</packages>
```
I'm also using .NET Framework 4.5.2

@sstevenkang sstevenkang added the bug This issue is a bug. label Apr 3, 2017
@PavelSafronov PavelSafronov added Question and removed bug This issue is a bug. labels Apr 3, 2017
@gokarnm
Copy link
Contributor

gokarnm commented Apr 3, 2017

You would have to pass a CancellationToken with an appropriate timeout value to the ReceiveMessageAsync method explicitly. On .NET 4.5 we use HttpWebRequest as the underlying HTTP Client, and its Timeout property is only used for synchronous calls. We'll consider having the SDK create a cancellation token instead in future.

    var cts = new CancellationTokenSource();
    cts.CancelAfter(TimeSpan.FromSeconds(10));
    var token = cts.Token;
    ReceiveMessageResponse response = await sqs.ReceiveMessageAsync(request, token);

@jakejscott
Copy link
Author

Yeah I came to the same conclusion, and added some code to catch the OperationCanceledException and then compare the exceptions CancellationToken to the source so that you know if was a timeout:

var recieveTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));

ReceiveMessageResponse response;
try
{
    var request = new ReceiveMessageRequest
    {
        QueueUrl = queueUrl,
        MaxNumberOfMessages = 1,
        WaitTimeSeconds = 20,
    };
    response = await sqs.ReceiveMessageAsync(request, recieveTimeout.Token);
}
catch (OperationCanceledException opEx)
{
    if (opEx.CancellationToken == recieveTimeout.Token)
    {
        log.Warning("Timeout receiving messages.");
    }
    else
    {
        throw;
    }
}

I think there needs to be some documentation added about using CancellationTokenSource for all async code.

@PavelSafronov PavelSafronov added the feature-request A feature should be added or improved. label Apr 3, 2017
@PavelSafronov
Copy link

We've updated the ClientConfig documentation to clarify the applicability of the timeout fields. Thanks for bringing this up. Closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A feature should be added or improved. guidance Question that needs advice or information.
Projects
None yet
Development

No branches or pull requests

5 participants