Как я могу отменить / отменить зону в Dart?

У меня есть веб-сервер http, который я пытаюсь обнаружить продолжительные запросы и прервать их. Следующий код успешно возвращается клиенту по истечении времени ожидания, но асинхронная зона все еще продолжает работать до завершения. Как я могу на самом деле убить обработчик запросов?

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);
});

1 ответ

Решение

Ничто не может убить работающий код, кроме самого себя. Если вы хотите, чтобы код был прерываемым, вам нужен какой-то способ сообщить об этом, а сам код должен завершиться (вероятно, из-за ошибки). В этом случае innerHandler должен иметь возможность прерывать себя по запросу. Если это не ваш код, это может быть невозможно.

Вы можете написать зону, которая останавливает выполнение асинхронных событий, когда установлен флаг (путем изменения Zone.run и т.д.), но вы должны быть очень осторожны с этим - он может никогда не попасть в асинхронный блок finally и освободить ресурсы, если вы начнете выбрасывать асинхронные события. Так что это не рекомендуется в качестве общего решения, только для очень осторожных людей, желающих заниматься ручным управлением ресурсами.

Другие вопросы по тегам