Play Framework - Parallel promises with partial acceptable failure - java

I currently try to call a bunch of webservices in parallel. In the end I want to evaluate all the responses. Therefore I use Promise.sequence. Unfortunately the whole method fails if one of the web calls failed. I would be satisfied if I just get the response of the succeeded calls.
Is there some way to perform the Promise.sequence and just retrieve the succeeded calls? After that it would be nice to handle the failed calls in any separate way.

I found a solution for now. For each Promise i create via ws.url("http://...").get() i define a recover method, e.g.
ws.url(theUrl).get().recover((t) -> null)
So when these Promises are processed via Promise.sequence no error is thrown (because it was already catched by the recover of the particular WS call promise).
Later on I just have to check if a result is null and then drop it from further processing.

Related

spring-boot multi threading aggregation and vice versa

We are building spring-boot application. At present Rest controller is calling multiple webservices in sequential manner. Now we need to perform these calls in parallel and return response as per below condition
Aggregate - Wait for all parallel webservices call to complete and then aggregate response and return the same.
No Aggregation - Return response whichever webservice call is completed first and abandon/cancel/interrupt rest of in progress call.
I have done some research and found ExecutorService but not sure if this will fit into both type of scenarios as I am very new to Spring-Boot.
Please let me know if there is way to achieve the same.
In my opinion, ExecutorService is a good idea and you should submit a Callable to ExecutoService so that you get back a Future.
To handle situation # 1 , you should logically AND return value of isDone() method call for all Futures and to handle situation # 2, you should do logical OR and something like that.
Here are references - Callable & Future.
I am not suggesting specific to Spring Boot but coming from Core Java back ground. This will get you started then you can refine approaches and switch APIs.
Hope it helps !!

Why is there no asyncContext.cancel()

While the Servlet 3.0 spec has request.startAsync() and asyncContext.start(),
why has it not provided a asyncContext.stop() or asyncContext.cancel() to initiate necessary clean-up on the server-side ?
Pls view this in the context of this other question to understand where I am coming from.
One HTTP request starts the Async processing and returns a
.../outstandingRequests/requestId link to the client.
Another HTTP request calls DELETE on that link to cancel the request
In this case, if I had a way to clean-up the server-side (servlet container stuff like AsyncListeners), instead of having to call asyncContext.complete() which will probably try and send a response back to the client, it will make sense. Doesnt it ?
In this scenario, call 1 is still hanging there, waiting for its response when call 2 comes in and wants to kill it. In this scenario, why would you not want to call complete() on call 1, thus finishing that call so that client stops waiting? You would probably want to set the status code to something other than 200 in this type of situation, but complete seems too be the best option given any scenario because it returns control back to the original caller and performs any request related cleanup work.
When a timeout happens, which is an error, the container calls complete (with a non-200 response code I imagine). The scenario you describe is similar to a timeout (albeit a forced timeout), so why not do the same thing the container does. Just call something like this before calling complete:
ac.getResponse().setStatus(500);
Any maybe write something to the output stream describing what caused this error.

Handling asynchronous saving with the possibility of time-critical errors?

So, to explain this, I'll start out by going through the application stack.
The system is running JSP with jQuery on top, talking through a controller layer with a service layer, which in turn utilizes a persistence layer implemented in Hibernate.
Now, traditionally, errors like having overlapping contracts has been handled through throwing exceptions up through the layers until they're translated into an error message for the user.
Now I have an object that at any given time can only be tied to one contract. At the moment, when I save a contract, I look at all of these objects and check if they're already covered by an existing contract. However, since multiple clients can be saving at any given time, this introduces the risk of getting past the check on two separate contracts, leading to one object being tied to two contracts at the same time.
To combat this, the idea was to use a queue, put objects into the queue from the main thread, and then have a separate thread take them out one by one, saving them.
However, here's the problem. For one, I would like the user to know that the saving is currently happening, for another, if by accident the scenario before happens, and two contracts with the same object covering the same time is in the queue, the second one will fail, and this needs to be sent back to the user.
My initial attempt was to keep data fields on the object put into the queue, and then check against those in a blocking wait, and then throw an exception or report success based on what happens. That deadlocked the system completely.
Anyone able to point me in the right direction with regards to techniques and patterns I should be using for this?
I can't really tell why you have a deadlock without seeing your code. I can think of some other options though:
Poll the thread to see its state (not as good).
Use some kind of eventing system. You would have an event listener (OverlappingContractEventListener perhaps) and then you would trigger the event from the thread when the scenario happens. The event handler would need to persist this information somehow.
If you are going for this approach, then on the client side you will need to poll.
You can poll a specific controller (using setInterval and AJAX) that looks up the corresponding information for the object to see what state its in. This information should have been persisted by your event listener.
You can use web workers (this is supported in Chrome, Firefox, Safari, and Opera. IE will support it in 10) and perform the polling in the background.
There is one other way that doesn't involve eventing. It depends on you figuring out the source of your deadlock though. Once you fix the source of your deadlock you can do one of two things:
Perform an AJAX call to the controller. The controller will wait for the service to return information. The code to issue feedback to the user will be inside the success handler of your controller.
Use a web worker to perform the call in the background. The web worker would also perform an AJAX call and wait for the response.
Shouldn't you be doing the check for duplicate contracts in the database? Depending on the case, you can do this with a constraint, trigger, o stored procedure. If it fails, send an exception up the stack. That's normally the way to handle things like this. You can then catch the exception in jQuery and display an error:
jQuery Ajax error handling, show custom exception messages
Hope this helps.

Write to GAE datastore asynchronously

In my Java app, sometimes my users do some work that requires a datastore write, but I don't want to keep the user waiting while the datastore is writing. I want to immediately return a response to the user while the data is stored in the background.
It seems fairly clear that I could do this by using GAE task queues, enqueueing a task to store the data. But I also see that there's an Async datastore API, which seems like it would be much easier than dealing with task queues.
Can I just call AsyncDatastoreService.put() and then return from my servlet? Will that API store my data without keeping my users waiting?
I think you are right that the Async calls seem easier. However, the docs for AsyncDatastore mention one caveat that you should consider:
Note: Exceptions are not thrown until you call the get() method. Calling this method allows you to verify that the asynchronous operation succeeded.
The "get" in that note is being called on the Future object returned by the async call. If you just return from your servlet without ever calling get on the Future object, you might not know for sure whether your put() worked.
With a queued task, you can handle the error cases more explicitly, or just rely on the automatic retries. If all you want to queue is datastore puts, you should be able to create (or find) a utility class that does most of the work for you.
Unfortunately, there aren't any really good solutions here. You can enqueue a task, but there's several big problems with that:
Task payloads are limited in size, and that size is smaller than the entity size limit.
Writing a record to the datastore is actually pretty fast, in wall-clock time. A significant part of the cost, too, is serializing the data, which you have to do to add it to the task queue anyway.
By using the task queue, you're creating more eventual consistency - the user may come back and not see their changes applied, because the task has not yet executed. You may also be introducing transaction issues - how do you handle concurrent updates?
If something fails, it could take an arbitrarily long time to apply the user's updates. In such situations, it probably would have been better to simply return an error to the user.
My recommendation would be to use the async API where possible, but to always write to the datastore directly. Note that you need to wait on all your outstanding API calls, as Peter points out, or you won't know if they failed - and if you don't wait on them, the app server will, before returning a response to the user.
If all you need is for the user to have a responsive interface while stuff churns in the back on the db, all you have to do is make an asynchronous call at the client level, aka do some ajax that sends the db write request, changes imemdiatelly the users display, and then upon an ajax request callback update the view with whatever is it you wish.
You can easily add GWT support to you GAE project (either via eclipse plugin or maven gae plugin) and have the time of your life doing asynchronous stuff.

If a REST web service call fails, should a message or event queue be used to retry later?

I'm building a web service with a RESTful interface (lets call it MY_API). This service relies on another RESTful webservice to handle certain aspects (calling it OTHER_API). I'd like to determine what types of best practices I should consider using to handle failures of OTHER_API.
Scenario
My UI is a single page javascript application. There are some fairly complex actions a user can take, which can easily take the user a minute or two to complete. When they are done, they click the SAVE button and MY_API is called to save the data.
MY_API has everything it needs to persist the information submitted by the user. However, there is an action that must take place that is handled by OTHER_API. For instance, OTHER_API might handle sending out an emails. Or perhaps it handles adding line items to my user's billing statement. In both cases, these are critical things than must be completed, but they don't have to happen right now, they just need to happen eventually.
If OTHER_API fails, I don't want to simply tell the user their action has failed, as they spent a lot of time doing it and this will make the experience less than optimal.
Questions
So should I create some sort of Message or Event Queue that can save these failed REST requests to OTHER_API and process them later?
Any advice or suggestions on techniques to go about saving REST requests for delayed processing?
Is there a recommended open source message queue solution that would work for this type of scenario with JSON-based REST web services? Java is preferred as my backend is written in it.
Are there other techniques I should consider?
Rather than approach this by focusing on the failure state, it'd be faster and more robust to recognize that these actions should be performed asynchronously and out-of-band from the request by the UI. You should indeed use a message/event/job queue, and just pop those jobs right onto that queue as quickly as possible, and respond to the original request as quickly as possible. Once you've done that, the asynchronous job can be performed independently of the original request, and at its own pace — including with retries as needed.
If you want your API to indicate that there are aspects of the request which have not completed, you can use the HTTP response Status Code 202 (Accepted).

Categories

Resources