HttpClient Fetch Retry

So my app is using the aurelia-fetch-client, and I have an issue popping up on my live app that I am trying to resolve, and think it can be done by adjusting / using the retry configuration.

I cannot find any examples that uses the new .withRetry way of doing that.

What I am trying to do is to setup to retry 3 times, with a 5 second wait for response.
My application is hosted on the free Azure servers, and I need to be able to wait for the service to spin up if its been a while since it was last accessed and its gotten unloaded. That can be 5 to 10 seconds or so.

I have tried this in the code below, but it ignores the retry settings, and I suspect its because I am not passing a retry function. Is that the case?

I am not sure how I would do that with how I have things setup now. Maybe someone can point me in the right direction.

Here is what I have for configuration:

        this.http.configure(config =>
        {
            let retryConfig = { maxRetries: 3, interval: 5000, strategy: 0};
            config
                //.useStandardConfiguration()
                .withDefaults({
                    headers:
                    {
                        'Authorization': 'Bearer ' + localStorage.getItem('access_token')
                    }
                })
                .withBaseUrl(API_SETTINGS.urlManage)
                .withRetry(retryConfig);
        });

and I have a utility function that wraps my api calls:

 requestJSON(url: string, opts: any = null)
    {
        return this.http.fetch(url, opts)
            .then(response =>
            {
                let clone = response.clone();
                this.clones.set(url, clone);

                return Promise.all([response, response.json()]);
            })
            .then(([response, json]) =>
            {
                if (!response.ok)
                {
                    throw new Error(json.message);
                }

                this.clones.delete(url);

                return json;
            })
            .catch(async exception =>
            {
                let tmp = await this.clones.get(url);
                let txt = tmp ? tmp.text() : undefined;
                let msg = new Map([
                    [TypeError, "There was a problem fetching the response."],
                    [SyntaxError, "There was a problem parsing the response."],
                    [Error, exception.message]]).get(exception.constructor);


                logger.error(`${msg} [${url}] [${txt}]`);

                if(tmp)
                {
                    this.clones.delete(url);
                }

                toastr.error("Unable to retrieve data. Please check that your login has not timed out. Returning to Home page.", "Error", { timeOut: 5000 });
                this.router.navigateToRoute("home");
                //return undefined;
            });
    }
2 Likes

So being the hack I am, I was still not able to figure out how to use the aurelia-fetch-client HttpClient to do retries. Someone will probably show me the one liner to do that as is the case with most things I can’t wrap my head around in Aurelia.

Right now I am just using fetch directly, and its working. I got main code here:

Here is my slightly modified code:

    fetchRetry(url: string, fetchOptions: object = {}, delay: number, limit: number) : any
    {
        return new Promise((resolve, reject) =>
        {
            function success(response)
            {
                resolve(response);
            }

            function failure(error)
            {
                limit--;
                if (limit)
                {
                    setTimeout(fetchUrl, delay)
                }
                else
                {
                    // this time it failed for real
                    reject(error);
                }
            }

            function finalHandler(finalError)
            {
                throw finalError;
            }

            function fetchUrl()
            {
                //console.log(url, fetchOptions);
                return fetch(url, fetchOptions)
                    .then(success)
                    .catch(failure)
                    .catch(finalHandler);
            }

            fetchUrl();
        });
    }

Here is how I use it:

        let opts = {
            headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
        };

        return this.fetchRetry(url, opts, 5000, 3)
            .then(response =>
            {
                 ...
            }
            .catch(async exception =>
            {
                ...
            }
1 Like

I’m trying to use it too, but didn’t found any sample anywhere and the document is close to non-existent on this.

1 Like

I haven’t had a reason to use this yet so I can’t confirm it works but you could reference the unit tests for sample implementation: https://github.com/aurelia/fetch-client/blob/master/test/http-client.spec.ts#L712

4 Likes

Awesome. Thx Bunny.

4 Likes