dart-lang/sdk

HttpClient deadline and retry

mleonhard opened this issue · 0 comments

I am developing an app in Flutter which uses dart:io:HttpClient to make requests to an API. The API occasionally accepts TCP connections slowly, rejects connections, returns HTTP 503 responses, returns other HTTP 5xx responses, or resets active connections. This happens during deployments, load balancer config updates, network outages, server overloads, and intermittent errors. I need my app to work properly in these situations, retrying up to a deadline.

When the API is slow to accept the TCP connection, HttpClient throws TimeoutException after 15 seconds. Some of my app's request deadlines are longer than 15 seconds. The app must calculate the timeout value from the deadline and the current time and set the HttpClient.connectionTimeout field. This code belongs inside HttpClient. Let's add a deadline parameter on HttpClient::openUrl and other methods.

Golang supports deadlines with net/http/Request.WithContext and context.WithDeadline.

Once Dart's HttpClient has a deadline to work with, it can perform retries and tolerate the myriad ways the network and server can fail. This will make Flutter apps more robust. It will provide good user experience for users. This is especially important for phone users who rely on unreliable mobile internet connections.

HttpClient slowly cleans up abandoned network requests. With deadlines, it can do aggressive cleanup. This will reduce app memory usage, data transfer, and battery consumption.

There are levels of retry capability:

  • Retry on any error before sending entire HTTP request
    • Name lookup failure
    • TCP connect timeout
    • TCP connection reset
    • TLS error, including rejected server certificate
    • Proxy error
  • Retry when server responds with 5xx status.
  • Retry GET and HEAD on any error except for correct HTTP response with 4xx status.

Any of these would provide a welcome improvement in Flutter app robustness.

CC: @timsneath