简体   繁体   中英

How to space out (rate-limiting) outgoing axios requests originating from an express app handling requests received from a webhook?

here is my issue:

I built a Node express app that handles incoming requests from a webhook that sometimes sends dozens of packages in one second. Once the request has been processed I need to make an API POST request using Axios with the transformed data.

Unfort.netely this API has a rate limit of 2 request per second.

I am looking for a way to build some kind of queuing system that accepts every incoming requests, and send the outgoing request at a limited rate of 2 request per seconds.

I tried adding a delay with SetTimeout, but it only delayed the load => when hundreds of requests were receieved, the handling of each of them was delayed by 10 seconds, but they were still being sent out at nearly the same time, just 10 seconds later.

I was thinking of trying to log the time of each outgoing request, and only send a new outgoing request if (time - timeOfLastRequest > 500ms) but I'm pretty sure this is not the right way to handle this.

Here is a very basic version of the code to illustrate my issue:

// API1 SOMETIMES RECEIVES DOZENS OF API CALLS PER SECOND
app.post("/api1", async (req, res) => { 

    const data = req.body.object;

    const transformedData = await transformData(data);

    // API2 ONLY ACCEPTS 2 REQUEST PER SECOND
    const resp = await sendToApi2WithAxios(transformedData); 

})

Save this code with data.js file you can replace the get call with your post call.

import axios from 'axios'

const delay = time => new Promise(res=>setTimeout(res,time));

const delayCall = async () => {
    try {
        let [seconds, nanoseconds] = process.hrtime()
        console.log('Time is: ' + (seconds + nanoseconds/1000000000) + ' secs')
        let resp = await axios.get(
            'https://worldtimeapi.org/api/timezone/Europe/Paris'
        );
        console.log(JSON.stringify(resp.data.datetime, null, 4));

        await delay(501);
        [seconds, nanoseconds] = process.hrtime()
        console.log('Time is: ' + (seconds + nanoseconds/1000000000) + ' secs')

        resp = await axios.get(
            'https://worldtimeapi.org/api/timezone/Europe/Paris'
        );
        console.log(JSON.stringify(resp.data.datetime, null, 4))
    } catch (err) {
        console.error(err)
    }
};

delayCall()

In packages.json

{
  "dependencies": {
    "axios": "^1.2.1"
  },
  "type": "module"
}

Install and run it from terminal

npm install axios
node data.js

Result - it will guaranty more than 501 msec API call

$ node data.js
Time is: 3074.690104402 secs
"2022-12-07T18:21:41.093291+01:00"
Time is: 3077.166384501 secs
"2022-12-07T18:21:43.411450+01:00"

So your code

const delay = time => new Promise(res=>setTimeout(res,time));
// API1 SOMETIMES RECEIVES DOZENS OF API CALLS PER SECOND
app.post("/api1", async (req, res) => { 

    const data = req.body.object;

    const transformedData = await transformData(data);

    await delay(501);

    // API2 ONLY ACCEPTS 2 REQUEST PER SECOND
    const resp = await sendToApi2WithAxios(transformedData); 

})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM