I'm maintaining a system providing a typical synchronous web service REST API. It routes each request to one of several possible backend services. Now there is a new backend I want to use, but there is a problem - it has an asynchronous API - I will need to do a request, and then wait for a callback request.
I'm thinking that it's possible to hide this asynchronicity behind a syncronizing facade. This facade will call the async API and then put the incoming web requests "on hold". When the callback endpoint is called a few seconds later it will resume the correct web request and respond to the original caller. If the callback does not arrive within let's say 10 seconds I will stop waiting, and respond with an error.
A complicating factor is that I have several web nodes behind a load balancer, but I'm thinking I can use a distributed storage solution like Redis to publish incoming callbacks, so that the correct web node can pick it up.
The question is: Is this feasible? Or do you believe it will be really difficult to get it to work properly? Any experience you can share or links to relevant resources would be much appreciated. Any other aproach to using an asynchronous web service in another service which needs to be syncronous?
Some pseudo code of what I'm thinking:
define rest-endpoint "/foobar" {
call async backend
until 10 seconds has passed {
sleep 1 second
result = redis.get(some_correlation_id)
if (result)
return new Response(result)
}
return new Response("failed")
}
define rest-endpoint "/callback" {
redis.push(some_correlation_id)
}
Note that if I time out and respond "failed" I don't (in my particular case) have to create any kind of compensating transaction towards the backend, and the client is also free to retry the same request later.
For the record: The system is implemented on the .NET stack, but I'm interested in any technology which would make implementing something like this simpler.
Also note that I would probably not actually use sleep
in a loop, but some kind of Task
/ future abstraction.