Я создаю приложение nodejs (10.16.0) и angular (8.0.3).
Один из модулей этого приложения предназначен для извлечения данных из базы данных путем выполнения довольно большой запрос (только для чтения, 80 строк с некоторыми внутренними объединениями и несколькими условиями), в конце, в зависимости от отправляемых параметров, этот процесс может извлечь от 0 до более 600 000 строк (или даже больше), поэтому запрос выполнение может занять от 1 секунды до даже 4 минут.
Процесс следующий:
- Пользователь вставляет (из внешнего интерфейса) несколько параметров.
- Пользователь нажимает на кнопка «Генерировать».
- Angular создает JSON с данными, необходимыми для формирования запроса, и отправляет его на сервер Nodejs.
- Nodejs получает JSON и формирует его запрос (здесь время начинает отсчитываться, весь процесс может занять от 0 до 240 секунд).
- Nodejs запрашивает у сервера DB2 результат запроса (этот подпроцесс занимает больше времени, даже несколько минут)
- Nodejs получает результат.
- * 1 059 * очищает результат (0 - 5 секунд в зависимости от длины массива).
- Nodejs возвращает очищенный список в angular.
- Angular создает файл с очищенным списком (еще 0 - 5 секунд).
- Загрузка файла.
Мой angular запрос (функция вызывается после нажатия на кнопку отправки):
// User input is the JSON that contains parameters
getReportData(userInput: JSON): Observable<MyInterface> {
return this.httpClient.post<MyInterface>(`${this.MyURL}/generateReport`, { userInput })
.pipe(
catchError(e => throwError(new Error("No Cost Types found" + e.message))));
}
Мой nodejs ответ конечной точки:
router.post('/generateReport', async (req, res, next) => {
try {
// ** Here it is when the time starts to count**
const result = await dataRetriever.getData(req.body.userInput);
if (result instanceof Error) next(createError(result, 400));
else res.send(result);
} catch (error) {
next(createError(error, 400));
}
});
Функция извлечения данных:
async function getData(userInput) {
const query = queryGenerator.getCQRDataRetrieveQuery(userInput);
// This await is the process that can take several minutes
const data = await queryExecutor.executeStatement(query);
if (data.length >= 1) {
const result = sanitizeDBResults(data);
return result;
} else {
// In case no rows were found
return [];
}
}
Проблема заключается в том, что когда angular ожидает ответа после нажатия кнопки «Создать», он выключается обрыв соединения через 60 секунд ожидания (что меньше времени, чем в уже рассмотренных примерах).
Это сообщение, отображаемое на консоли chrome после 60 секунд ожидания:
zone.js:3372 POST https://*myURL*/generateReport 504 (Gateway Time-out)
Я слышал о заголовке с именем «keep alive» или о реализации веб-сокетов для «heartbeat» от nodejs до angular, чтобы клиентская часть знала, что соединение все еще живо, но это правильный подход ? Какое еще решение может быть простым и эффективным?
Так что мне нужно реализовать способ удержания Angular ответа на запрос более 60 секунд, результаты запроса могут занять 4 минуты или даже больше, если это необходимо.
Есть идеи по этому поводу?