google-api-dotnet-client
google-api-dotnet-client copied to clipboard
Simplify customizing the HttpClient timeout
Hi,
I am experiencing this problem now. My google script is invoked by my app though Google.Apis.Script.v1 nuget package v1.57.0.2638. The script processes a google worksheet. From the google log it is seen that the script runs about 2 minutes (108-130 secs) and completes successfully meaning it returns a value which is logged. Also, it has status Completed in the log. Also, that the script is completed is also seen from the worksheet data. Nevertheless, on the client side the following exception is arisen:
A task was canceled. [System.Threading.Tasks.TaskCanceledException]
Module: CommonLanguageRuntimeLibrary
Stack: at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Google.Apis.Requests.ClientServiceRequest`1.Execute() in C:\Apiary\2022-03-28.08-00-01\Src\Support\Google.Apis\Requests\ClientServiceRequest.cs:line 179
The client code is as follows:
public object Run(string function, params object[] parameters)
{
ExecutionRequest request = new ExecutionRequest
{
Function = function,
Parameters = parameters,
#if DEBUG
DevMode = true,
#else
DevMode = false,
#endif
};
ScriptsResource.RunRequest runRequest = service.Scripts.Run(request, ScriptId);
Operation operation = null;
for (int i = 0; ; i++)
try
{
operation = runRequest.Execute();
break;
}
catch (Google.GoogleApiException e)
{
if (i >= RetryMaxCount)
throw;
if (e.Error?.Code != 500)
throw;
Log.Warning2("Retrying...", e);
System.Threading.Thread.Sleep(RetryDelayMss);
}
if (operation.Error != null)
{
string message = "Server error: " + operation.Error.ToStringByJson();
throw new Exception(message);
}
return operation.Response["result"];
}
The exception is thrown from here: runRequest.Execute();
Notice, it is not a GoogleApiException because otherwise it would be caught within the method.
I'm in Europe. A man in the USA using the same app experiences the same error. So, reasoning from the above facts, the error neither depends on the network nor is caused by timeout on the server. On the other hand, it arises only when the target worksheet has much data to process that takes more than 100 secs. When the same script runs less than 100 secs, no exception is thrown. Notice, 100 secs is a guessed number - I have no formal evidence that it is the timeout within Google.Apis.Script lib.
Please share your thoughts on the nature of this issue. Thank you!
I strongly suspect that you're just seeing the default HttpClient timeout of 100s. You haven't shown us how you've initialized service
, but that's where I'd expect you to set the timeout for the client. Unfortunately it doesn't look like this is trivial to do out of the box (and we may look at making this easier) but you could do something like this:
public sealed class TimeoutHttpClientInitializer : IConfigurableHttpClientInitializer
{
private readonly IConfigurableHttpClientInitializer _other;
private readonly TimeSpan _timeout;
public TimeoutHttpClientInitializer(IConfigurableHttpClientInitializer other, TimeSpan timeout)
{
_other = other;
_timeout = timeout;
}
public void Initialize(ConfigurableHttpClient httpClient)
{
_other?.Initialize(httpClient);
httpClient.Timeout = _timeout;
}
}
(For more general purpose use it would make sense to have a composite client initializer, and that's probably the route we'll take internally, but a single class will be simpler to get you up and running.)
Exactly! What I did is just set
service.HttpClient.Timeout = new TimeSpan(0, 0, 0, 300);
where service
is:
ScriptService service = new ScriptService(new BaseClientService.Initializer
{
HttpClientInitializer = Credential,
ApplicationName = applicationName,
});
Thank you for the clue!
(It would be nice to have Timeout exposed on the surface where it could be easily spotted. At least it would be a requirement to an 'easy-to-do' API around Google.Apis lib.)
Marking as a feature request, we will look into srufacing a Timeout.