Can't extend query timeout in C# SDK


#1

I have a long running query which is returning with this exception after 75 seconds:
"System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request. ---> System.Net.Sockets.SocketException: The I/O operation has been aborted because of either a thread exit or an application request"

I’m using couchbase dependency injection in an ASP.NET solution. The query works in the workbench on the server.

I’ve tried extending the timeout of the query request:

var req = new QueryRequest(query);
req.Timeout(new TimeSpan(0, 10, 0));
var result = await _bucket.QueryAsync<T>(req);

and changing the bucket configuration:

"CouchbaseOptions": {
    "QueryRequestTimeout": "1000000",
    "SearchRequestTimeout": "1000000"
}

I’ve confirmed via inspecting the _bucket object that the configurations are being applied, but it’s still returning the same exception after 75 seconds. What can I do here?


#2

Hi @lukeb

This is odd behaviour, setting the timeout on the QueryRequest should be enough combined with the QueryRequestTimeout configuration property. My guess is the timeout property is not being applied correctly to the N1QL query JSON.

Please can you confirm what Couchbase server & SDK versions you’re using?

Thanks


#3

Using
Server 5.0.1 build 5003
Couchbase.Extensions.DependencyInjection 2.0.2
Tested in CouchbaseNetClient 2.5.9 and 2.6.0

I’ve just tested forcing a timeout by setting the timeout duration to 1ms, and the resulting exception is different:

A task was canceled.
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Couchbase.N1QL.QueryClient.ExecuteQueryAsync[T](IQueryRequest queryRequest, CancellationToken cancellationToken)}

So something else is causing the socket read to abort, but it’s not the QueryRequestTimeout
Here’s the stacktrace from the exception:

   at System.Net.Http.HttpConnection.ChunkedEncodingReadStream.CopyToAsyncCore(Stream destination, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.HttpConnectionResponseContent.SerializeToStreamAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
   at System.Net.Http.HttpContent.LoadIntoBufferAsyncCore(Task serializeToStreamTask, MemoryStream tempBuffer)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Couchbase.N1QL.QueryClient.ExecuteQueryAsync[T](IQueryRequest queryRequest, CancellationToken cancellationToken)

And the relevant log from the console:

The operation has timed out. {"s":"n1ql","i":"1::2","b":"sync_gateway","r":"couchbase-******","t":75000000}


#4

Further testing results:
I can get the query to complete using the synchronous API and ensuring that the query timeout is set in BOTH the cluster configuration and the query request. Failing to do either will result in two different timeout errors.

This is the only combination that works:

var cluster = new Cluster(new ClientConfiguration
{
	Servers = new List<Uri> { new Uri("http://*********") },
	QueryRequestTimeout = 10000000
});
...
var req = new QueryRequest(query);
req.Timeout(new TimeSpan(0, 10, 0));
var result = bucket.Query<TempEvent>(req);

#5

@MikeGoldsmith
Is this a bug or am I implementing incorrectly? I’d prefer to be using the async API.


#6

Hi @lukeb

Sorry for the delay in getting back to you. There does indeed seem to be a bug in QueryAsync<T> where timeouts are not being honoured correctly beyond 75 seconds (shorter ones are handled correctly). The code you have above should work with both sync and async code paths.

I’ve created the following ticket to investigate - NCBC-1746.

Thanks


#7

@lukeb -

I am trying to replicate your issue, but haven’t been able to just yet. Would you mind posting:

  1. The entire stacktrace of the error you are encountering in the initial post
  2. An example project with the same configuration you are using (including dependency injection)

You can attach it to the Jira ticket: https://issues.couchbase.com/browse/NCBC-1746

Thanks!

Jeff


#8

@lukeb I closed the ticket because I cannot reproduce. Queries always time out just after the Timeout and QueryRequestTimeout settings from what I can see (see the ticket).