Ability to retry failed http requests

540
3
04-14-2021 11:48 AM
RoyJackson2
New Contributor III
 

Greetings.   In our angular app, sometimes we see requests made by the JS API which do not succeed.  These include basemap tiles, or requests to various GIS services, other content endpoints.  504 Gateway timeout is the main culprit.  

With angular we can implement HttpInterceptor, and retry failed requests.  

In the JS API, we have interceptors in esri config request, which can affect requests before they are sent, change responses as they are received, or see failed responses.  

When we get failed error responses, is it possible to implement retry logic, so we can try to recover from intermittent API failures?

Thank you

Tags (2)
0 Kudos
3 Replies
AndyGup
Esri Regular Contributor

Hi @RoyJackson2 , can you share a vanillaJS codepen app that reproduces a 504 timeout? It's very unlikely that Angular is causing the problem, more likely something to do with the network or cloud. A vanillaJS app will help with isolating and troubleshooting the HTTP request issue. 

RoyJackson2
New Contributor III

Hi Andy!  Thanks for the reply.   

The thing about these errors, is that we don't exactly know when they happen or why they happen.  It could be 1 in a thousand requests, only at certain times.  Perhaps gremlins in the wires?  It has been noticed for 504, and to a lesser degree 401 responses, for a very small fraction of requests.   This is against our AWS APIs and hosted services, or even an occasional AGOL basemap tile times out.  Usually we are working on something else, and notice that oh weird here is an unexplained http error being logged to console.    I think it is something in the network outside the app and angular.   But, we need to be able to handle these fluke situations in our 911 call taking app, so that the user experience will not be interrupted, and we show their map data accordingly.   

For our Angular Http client, we are looking at the http interceptor, and likely the retryWhen operator to re-submit requests depending on the status code.   Because the esri JS api handles http by itself outside of angular, I am looking for a comparable generic approach of error handling and retry logic so that these intermittent api failures dont cause a map to not load.  I am unable to find any kind of configuration setting that would affect retrying requests, or a sample of using the error interceptor  

 esriErrorRequestInterceptor(error: esri.Error) {
        if (error.message === 'Request canceled') {
            // This message shows up when the map requests a tile, but it is moved before the request is done.
            // We want to ignore "Request canceled" messages so they don't show up in the console every time
            // we zoom/pan.
        } else {
            this.logger.error({
                message: 'esri request failed: ' + error.message,
                context: this.context,
                error: error.details,
                logToCloudWatch: true
            });
            // How do we retry the request so that the object making the request can still process the result?
        }
    }

These intermittent API issues can prevent a layer from loading, content in the layer from being displayed... so we need to come up with an approach to recover from these scenarios across basically all traffic for the app, including retrying, logging, notifying user etc. 

Thank you

0 Kudos
AndyGup
Esri Regular Contributor

We don't have this concept in the API, but there is functionality that you can try. The best approach would be to check for layer.loadError and inspect the error that caused the failure, then run layer.refresh():

https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#loadErro...

And, like your snippet above you could also try adding a request interceptor with the "before" callback. Make the request yourself and then retry. We don't have a way to delay or retry a request automatically:

https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#BeforeInterceptorCall...

You might also experiment with watching layer.loadStatus for "failed", here's a sample demonstrating the concept:

https://codepen.io/andygup/pen/xxgjQZE?editors=1000 

0 Kudos