Establecer correctamente un tiempo de espera para una solicitud HTTTP en Angular con un Service Worker
Como parte de una nueva funcionalidad que está agregando mi equipo, se me pidió que, cuando una solicitud HTTP Post específica falle (cuando haya poca o ninguna conexión a Internet disponible), vuelva a intentar la solicitud cada X segundos durante un período total de Y segundos. Por ejemplo, cada 1 segundo en un período de 8 segundos.
Este es el código que desarrollé:
“`javascript
return this.carService.saveCar(car)
.pipe(this.isRetryable() ? retryWhen(errors => {
return errors.pipe(mergeMap(response => {
if (response.status === TIMEOUT<em>EXCEPTION</em>CODE || response.status === UNKNOWN<em>EXCEPTION</em>CODE) {
return of(response).pipe(delay(this.saveCarRetryTimeout)) // X segundos
}
<pre><code> return throwError(response);
}));
}) : tap(),
this.isRetryable() ? timeout(this.saveCarProccessTime) : tap(), // Y segundos
tap((carId: number) => {
this.logger.info(saveCarBaseLog.setStatus(LogStatus.COMPLETE));
}),
catchError((err) => {
this.logger.error(saveCarBaseLog).setStatus(LogStatus.FAILED));
return throwError(err);
}));
</code></pre>
“`
La función isRetryable() verifica si tenemos configuradas las variables X e Y, para que no afecte al proceso.
Después de hacerlo y ver que funciona bien tanto en el entorno local como en el de desarrollo, subimos la versión. Al día siguiente nos encontramos con un problema: en los entornos de preproducción y producción, algunos autos se guardan dos veces.
Después de una investigación que hice, parece que este problema proviene del worker del servicio que tenemos. Cuando ocurre un tiempo de espera completo, la solicitud en sí misma se agota, aunque la solicitud FETCH asociada nunca se cancela, lo que provoca un problema cuando la conexión a Internet es lenta (la solicitud FETCH eventualmente tiene éxito y no obtenemos ninguna indicación al respecto).
Realmente estoy perdido en cuanto a qué hacer aquí, así que cualquier ayuda es bienvenida.
No puedo subir una captura de pantalla de la red ya que es una red privada,
Pero en la sección de red en Chrome se ve así:
Solicitud POST – saveCar – XHR – 504 Tiempo de espera
Solicitud POST – (ServiceWorker) saveCar – FETCH – 504 Tiempo de espera
Solicitud POST – saveCar – XHR – 504 Tiempo de espera
Solicitud POST – (ServiceWorker) saveCar – FETCH – 504 Tiempo de espera
Solicitud POST – saveCar – XHR – 504 Tiempo de espera
Solicitud POST – (ServiceWorker) saveCar – FETCH – 200 Éxito (El problemático)
davy.ai
Solución para reintentar solicitudes HTTP POST en Angular con Service Worker
El código proporcionado parece estar reintentando la solicitud HTTP POST cuando hay una conexión lenta o inexistente a Internet durante un período total de Y segundos. Sin embargo, en el entorno de producción, algunos coches se guardan dos veces debido al Service Worker.
Para resolver este problema, necesitamos modificar el Service Worker para manejar los reintentos de una manera más inteligente.
Una forma de hacerlo es interceptar la solicitud saliente de HTTP POST dentro del Service Worker, y si agota el tiempo de espera, podríamos almacenarla en IndexedDB con una marca de tiempo. Luego, cuando la red esté disponible nuevamente, podríamos verificar periódicamente IndexedDB para solicitudes agotadas en el tiempo y reintentarlas.
Aquí tienes un ejemplo básico de cómo se podría hacer esto:
Este código intercepta todas las solicitudes de HTTP POST salientes dentro del Service Worker, y si una agota el tiempo de espera, la almacena en IndexedDB con una marca de tiempo. Luego, verifica periódicamente IndexedDB para solicitudes agotadas en el tiempo y las vuelve a intentar. Si una solicitud tiene éxito, se elimina de IndexedDB.
Ten en cuenta que este código asume que estás utilizando la biblioteca
idb
(https://github.com/jakearchibald/idb) para interactuar con IndexedDB.Usando este enfoque, deberías poder volver a intentar las solicitudes HTTP POST de una manera más inteligente evitando el problema de guardar los coches dos veces.