Исключение TimeoutException: Будущее не завершено

#dart

Вопрос:

Я получаю ошибку и не могу понять, что может быть не так. Ошибка:

 This query is already running
TimeoutException: Future not completed
 

код:

  Future<void> addResultToCache(sqlQuery) async {
  try {
      if(pendingFutures.containsKey(sqlQuery.hashCode)) {
        print('This query is already running');
        await pendingFutures[sqlQuery.hashCode];
        print("This Line is already do not prints"); 
      }
      else {
        pendingFutures.addAll({sqlQuery.hashCode: connection.query(sqlQuery, timeoutInSeconds: 3600)});
        var queryResult = await pendingFutures[sqlQuery.hashCode]; // run pending Future 
        await pendingFutures.remove(sqlQuery.hashCode); // remove pending future from list
        var queryObj = RequestCacheStruct(sqlQuery.hashCode, DateTime.now(), queryResult! );
        requestsCacheList.add(queryObj);
        
        print('Query was added to сache');
      }
   }
      on TimeoutException catch(e) {
        print('TimeoutException: ${e.message}' );
        }
}
 

Ошибка возникает не каждый раз, а обычно после n запусков (после 2-3 минут работы). Кажется, что-то не так с:

 await pendingFutures[sqlQuery.hashCode];
 

Не могли бы вы дать какие-либо идеи о том, что может быть не так с моим кодом?

Есть ли у фьючерсов тайм-ауты по умолчанию, и это мой случай?

Комментарии:

1. TimeoutException

2. Проверьте, как вы создаете connection . По умолчанию, похоже, используется тайм-аут в 30 секунд. (Найдите queryTimeoutInSeconds параметр.)

Ответ №1:

Я не думаю, что в конкретной строке, о которой вы спрашиваете, есть что-то неправильное. Ваш код кажется разумным, хотя и чрезмерно сложным.

Вы, кажется, предполагаете, что hashCode ан sqlQuery уникален. Это не. Вполне возможно , что у вас будут два разных запроса с одним и тем же hashCode , и в этом случае вы pendingFutures можете отказаться от второго запроса. Скорее всего, это не ваша проблема, но этого следует опасаться.

Похоже, вы действительно получаете два одинаковых запроса hashCode (либо действительно один и тот же запрос, либо конфликт хэш-кода), и по крайней мере один запрос, который завершается a TimeoutException . В await pendingFutures[sqlQuery.hashCode]; ожидании повторного запроса в будущем. Затем какое-то будущее завершается, возможно, тем, возможно, другим, с TimeoutException А. Это приводит к тому , что либо тот, кто ожидает, либо тот, кто входит var queryResult = await pendingFutures[sqlQuery.hashCode]; , бросает TimeoutException , что поймано и напечатано вашим catch предложением.

Поскольку тайм-аут вашего запроса установлен на один час, вполне разумно, что это произойдет только по истечении этого времени. Или раньше, если что-то еще в системе также имеет тайм-аут, который срабатывает, но это зависит от того, какой другой код вы запускаете. У фьючерсов, как правило, нет тайм-аутов, если вы об этом не попросите.

Комментарии:

1. Странно, что я получаю исключение намного раньше, чем через 1 час. Для получения исключения требуется около 2-3 минут. Значит, ошибка может быть из другой части кода?

2. Кто-то должен бросить TimeoutException то, что вы поймаете. Единственная часть вашего кода, которая выглядит так, как будто она может быть источником (потому что это единственная часть, которая выглядит так, как будто она запускает асинхронную операцию), — это connection.query(sqlQuery, timeoutInSeconds: 3600) . Может быть, это ограничивает время ожидания на 2-3 минуты, может быть, он вызывает какой-то другой код, который затем истекает, но посмотрите на трассировку стека и попытайтесь выяснить, кто для начала создает исключение.

3. @Irn, я не уверен, но, похоже, мой код выше будет заблокирован, если я получу два одинаковых запроса один за другим.

Ответ №2:

Ваши будущие броски TimeoutException и ваше предложение о try-catch блокировке срабатывают.

Что касается того, почему это происходит, это может быть дюжина вещей. Поскольку это работает для вас много раз, а затем останавливается, я бы сказал, что ваш SQL server отключает запросы из-за, например, отсутствия рабочих потоков. Возможно, вы одновременно выполняете больше запросов, для обработки которых настроена база данных, возможно, вы не освобождаете соединения, что приводит к сливу пула соединений. Это всего лишь слепые догадки.