Skip to content

Switching on retries on timeout causes unexpected behavior #5284

Description

@avinash0161

I am trying to use the retry mechanism of Orleans. I have the following code:

Start Silo, Client and Send Requests from client to a grain:

            var siloBuilder = new SiloHostBuilder()
                .UseLocalhostClustering()
                .UseDashboard(options => { })
                .Configure<ClusterOptions>(options =>
                {
                    options.ClusterId = "dev";
                    options.ServiceId = "Orleans2StatelessWorkers";
                })
                .Configure<EndpointOptions>(options =>
                    options.AdvertisedIPAddress = IPAddress.Loopback)
                .ConfigureLogging(logging => logging.AddConsole())
                .Configure<SiloMessagingOptions>(options => {options.ResponseTimeout = new TimeSpan(0,0,32); options.ResendOnTimeout = true; options.MaxResendCount = 60; });

            var host = siloBuilder.Build();
            await host.StartAsync();

            var clientBuilder = new ClientBuilder()
                .UseLocalhostClustering()
                .Configure<ClusterOptions>(options =>
                {
                    options.ClusterId = "dev";
                    options.ServiceId = "Orleans2StatelessWorkers";
                })
                .ConfigureLogging(logging => logging.AddConsole())
                .Configure<ClientMessagingOptions>(options => {options.ResponseTimeout = new TimeSpan(0,0,32); options.ResendOnTimeout = true; options.MaxResendCount = 60;});

            var client = clientBuilder.Build();
            await client.Connect();

            var hashGenerator = client.GetGrain<IHashGeneratorGrain>(0);

            while (true)
            {
                try{
                    Console.WriteLine("Client making a call");
                    await hashGenerator.TempCall();
                }
                catch (Exception ex) // to catch timeout exceptions
                {
                    Console.WriteLine("EXCEPTION: " + ex.Message);
                }      
            }

Grain class

    public class HashGeneratorGrain : Grain, IHashGeneratorGrain
    {
        public async Task TempCall()
        {
            await Task.Delay(33000);
            return;
        }
    }

What's expected:
Client has its timeout set to 32s. It makes a call to the grain and the call takes >33s to process. So, after 32s a timeout happens and TempCall() should again be invoked.

What happens:
The timeouts happen almost immediately (after 1-2s) and logs showing retries start to appear in quick succession (1-2 s gap between them). This behavior is observed if the ResendOnTimeout option is set to true and there is some Task.Delay statement in TempCall(). To confirm this, I even increased the options.ResponseTimeout for the client to more than 2 min and decreased the Task.Delay in TempCall() to 10s. Therefore, no timeout should ideally have occurred after this change. However, the same observation (immediate timeouts and retries) ensued.
This behavior is no more seen if I remove the options.ResendOnTimeout = true; options.MaxResendCount = 60; from the Client builder messaging options in the code above. The timeout happens after the set time, but of course there is no resending.
The above described behavior (client to grain communication) is also seen in grain to grain communication.

The entire project is uploaded here.


Credits Note: The code used above is a modified version of the code available here. I have removed the [Stateless Grain] tag from the grains to turn them into normal grains.

Metadata

Metadata

Assignees

Labels

staleIssues with no activity for the past 6 months

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions