Stop a Fetch Call timing out causing automatic CC retries

Hi All

I have a problem where sometimes the 3rd party API I am accessing via FETCH times out, but only after 300 seconds.

Because this is the same time as the CC time limit, what happens is my CC tasks errors because it runs out of time and then automatically retries itself, which takes another 5 minutes only to error again. And as such it goes into a horrible 5 min error retry spiral.

Is there a way that I can force the fetch call to finish when I see that it is taking way longer than usual to complete?

1 Like

Hi Fred

Yes, you can solve this using an AbortController, and passing in an abort signal into the fetch call as an additional parameter.

Something like this

import { TaskContext } from '@journeyapps/cloudcode';

export async function run(this: TaskContext) {
    // Your code here
    const AbortController = globalThis.AbortController
    const controller = new AbortController();
    let abortSource: string;
    
    // have the beforeTimeout warning trigger the AbortController
    this.on('beforeTimeout', (params) => {
        console.log(`in beforeTimeout: Triggering abort controller: Params`, params)
        abortSource = 'beforeTimeout';
        // this line sends the abort signal
        controller.abort();
        console.log('After calling abort');
    });

    // manually trigger the AbortController after a specific period of time, e.g. 3 mins
    const timeout = setTimeout(() => {
        console.log('Triggering the abort controller');
        abortSource = 'manualTimeout';
        // this line sends the abort signal
        controller.abort();
    }, 3*60*1000);
    
    const url = 'http://example.com';
    // here we are passing in the additional fetch param 'signal' to handle our abort signal
    const config = {
        method: 'GET',
        signal: controller.signal
    }
    
    console.log(`About to fetch`);
    try {
        let result = await fetch(url, config);
        if (result.ok) {
            console.log(`Result ok`);
            let response = await result.text();
            console.log(`Response: ${response}`);
        } else {
            console.log(`Result not ok`);
            console.log(`Result status: ${result.status}`)
            console.log(`Result statusText: ${result.statusText}`)
        }
    } catch (er) {
        console.log(`Error: ${er.name}`);
        if (er.name === 'AbortError') {
		    console.log(`Fetch request was aborted by: ${abortSource}`);
	    }
    }
    console.log('All done ')
    clearTimeout(timeout);
    return true;
}

3 Likes