loading...

Is RabbitMQ a fit solution for request timeout problem ?

haamida profile image Hamida ・1 min read

The system am working on relies on the response received from an external API, frequently now, the requests we are sending finish with a timeout and we end up losing the transaction in progress.

We need our requests to be resent over and over until the API responds so we could continue the transaction.

I got advised to use RabbitMQ so that it queues the requests until the API responds, so this way my application should be a producer that pushes to the queue, what I still can't undrestand is how I am going to receive a callback from the queue once my message (request is excuted sucessfully) ?
Does RabbitMQ guarantee that my request reached its destination sucessfully? will it keep trying to send the request until the api responds (the api is available for exchanges) ?
How will my application resume the execution related to the request ? my intial idea now is to isolate that code that relies on the immediate response of the external API.

Is it even RabbitMQ the best choice here ?

I have zero experience with RabbitMQ that's why I am still skeptical if it's appropriate in this use case so am sorry in advance if some of these questions are completly dumb.

PS: we are keeping track of the timeout data.
The API we are connecting to is part of an external system, we have no control
over it.

Posted on by:

Discussion

pic
Editor guide
 

(I'm gonna assume that this is a web app, and that the front end asks the back end to make the API request. And the back end either renders HTML or just gives the front end some data and the front end builds some DOM. Also assuming websockets aren't part of this.)

I unfortunately can't speak to the particulars of using RabbitMQ, but in general, for the above situation you do probably want some kind of queue. It could also be one like Sidekiq or RQ, which is what I'm more familiar with.

The reason is that, as you've seen, you can't control how long the API takes to respond, or whether it even does, and you need to respond with something in the meantime. You also want someone separate to hang back and actually do the job, and not tie up your web server. A queue is one pattern for having the web server talk to that "worker."

How will my application resume the execution related to the request?

So you can't do it such that everything happens in a single request/response, but what you can do instead is something like:

  • your web app process puts a message on the queue saying that the job needs to be run.
  • your web app process responds immediately with a "processing" status, and the user is shown a spinner, progress bar, etc.
  • your front end is designed to, after it sees the "processsing" status, ask the back end every few seconds for the (hopefully updated) status.
  • at some point, a separate "worker" process sees the job on the queue, takes it off, and runs it. the job makes the API call and then puts the result in your db (or whatever you use for storage for this purpose).
  • the next time your front end polls, it gets the finished result, and you can finally show it.

Some of the details might differ for you, but the point is that you have to make it so that the API call happens asynchronously. That typically means a queue and a separate process for watching it. It could mean that RabbitMQ calls a special private endpoint of your back end. It could even just be threads, if your back end language has those. But it's asynchronous. And the front end keeps asking if the result is in yet.

And one of the nice things about a queue is that you can have a universal policy for what to do on failure. For instance, you might retry any failed job 2 more times, and the third time you give up and store somewhere that it failed. Then your front end polls, sees the failure, and notifies the user. Not great but it's better than a 500.

They also usually have some kind of prioritization -- for instance, you can say that all of your jobs for emailing users get run after the API call jobs.

I hope that helps to at least conceptualize it. Sorry it's not particular to RabbitMQ.

 

Thank you very much, even if it's not particular to RabbitMQ you gave some solid insight. The queue is a big part of the solution but indeed its interaction with the rest of the system is important too, I am going to base off some of the first interventions in solving the problem on your answer.

 

It depends on what expectations the callers expect. Do they want to see it succeed or does it not matter. If it does not matter a consumer can issue a callback when processing of the request is finished. Is it ideal to know if it is completed? If your app is waiting for that to complete before moving on to another step maybe there will need to be a different option.

 

Yes as a caller we need to know that the request is completed.
My app is actually waiting for a response to move to another step of the transaction.
With the current timeout problem, we are losing complete transactions since we have no sucessfull response from the API.

 

In this case, you might want to look into the Saga pattern?

 

Is this a public end user making the call or is it an internal business person?

It's a public user, and through our service he reach the external API to make the transaction, and by its end we need yo present him with a response

 

Here's a great read about this from the RabbitMQ docs

Basically, if you are using an official RabbitMQ client, then reliable message delivery should be handled for you πŸ‘Œ