javascriptnode.jsaxioslong-polling

Once in a while, axios http long polling not returning at all


I have a function that looks like

async function longPoll() {
    let timeout = 0
    try {
        // perform longPoll tasks
        let response = await axios.get(config.url)
        const data = response.data && response.data.data
        if (!Array.isArray(data)) {
            return
        }
        await Promise.all(data.map(async(item) => {
            try {
                // send message via WhatsApp using 'whatsapp-web.js'
                let chatId = getChatId(item)
                let text = getText(item)
                await client.sendMessage(chatId, text)
            } catch (e) {
                // some logging
                return
            }
            try {
                // report sending is ok
                let response = await axios.get(config.confirmationUrl)
            } catch (e) {
                // some logging
            }
        }))
    } catch (e) {
        if (e.response) {
            let status = e.response.status
            let statusText = e.response.statusText
            console.error(`Server response ${status} ${statusText}`)
        } else if (e.request) {
            console.error('No response from server.')
        } else {
            console.error('Failed to create request.')
        }
        timeout = 5000
    } finally {
        setTimeout(longPoll, timeout)
    }
}

longPoll() // kick off

In the beginning, it runs fine. After a while, longPoll() is no longer called. Why is it so?

I'm using NodeJS v16.14.0 with axios v0.19


Notes:

  1. I have found the cause. See my own answer.
  2. Repro steps available in my comment
  3. I undeleted this question for informational & sharing purpose

Solution

  • The problem was caused by occasional network issues.

    I solved it by

    1. Adding a timeout to axios calls; for example: axios.get(url, {timeout: 18000}) for 18 seconds timeout. This is the main solution.
    2. Keeping a timestamp of when the last http request was started and check it regularly with setInterval(). If it was not tolerable, I starts a new "loop". And also add handling if the number of long polling "loop" is too many and terminate the extra. I did this when I haven't found the culprit.

    Based on my observation, the actual time spent before exception is thrown might be several seconds (up to 5 seconds) longer than timeout duration given to axios.