How can I cancel/abort a zone in Dart?

Issue

I have an http web server that I’m trying to detect long-running requests and abort them. The following code successfully returns to the client upon timeout, but the async zone still continues to run to completion. How can I actually kill the request handler?

var zone = runZoned(() {
  var timer = new Timer(new Duration(seconds: Config.longRequestTimeoutSeconds), () {
    if (!completer.isCompleted) { // -- not already completed
      log.severe('request timed out');
      // TODO: This successfully responds to the client early, but it does nothing to abort the zone/handler that is already running.
      //       Even though the client will never see the result (and won't have to wait for it), the zone/handler will continue to run to completion as normal.
      // TODO: Find a way to kill/abort/cancel the zone
      completer.complete(new shelf.Response(HttpStatus.SERVICE_UNAVAILABLE, body: 'The server timed out while processing the request'));
    }
  });

  return innerHandler(request) // -- handle request as normal (this may consist of several async futures within)
    .then((shelf.Response response) {
      timer.cancel(); // -- prevent the timeout intercept
      if (!completer.isCompleted) { // -- not already completed (not timed out)
        completer.complete(response);
      }
    })
    .catchError(completer.completeError);
});

Solution

Nothing can kill running code except itself. If you want code to be interruptible, you need some way to tell it, and the code itself needs to terminate (likely by throwing an error). In this case, the innerHandler needs to be able to interrupt itself when requested. If it’s not your code, that might not be possible.

You can write a zone that stops execution of asynchronous events when a flag is set (by modifying Zone.run etc.), but you must be very careful about that – it might never get to an asynchronous finally block and release resources if you start throwing away asynchronous events. So, that’s not recommended as a general solution, only for very careful people willing to do manual resource management.

Answered By – lrn

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.