Reputation: 11346
I am trying to implement a feature in a Spring MVC app that kicks off a long running job. The task will be kicked off by a Spring Controller. Since it could take a long time to finish (few mins to over an hour), @Async seems to be a perfect candidate for what I am trying to do.
One requirement is that, I want to limit async task per id. To explain the problem statement. Lets say we need to build a student report for a given student id. Controller will kick off a reporting job for given id. At any given time only one report can be run for a given student id.
If a new request comes in, if there is a report running for that id, we want to cancel that and start a new job (Assuming new request will provide the most up to date info and old request is no longer relevant). Reporting task can run for different ids (eg. job for student id 100 and 200 can run but only one task per id should run at a time.. ie. there should not be two jobs for id 100).
Here is how the controller would look like:
@RequestMapping("/report/{id}")
.. ...
Future<Void> reportFuture = reportService.generate(id)
.....
Service would looks similar to:
@Async
public Future<Void> generate(int id) {
... Do some Long Calculations generate a report
}
So, how can we keep track of the async task such that we know if there is a job running for given id, if so cancel that?
Upvotes: 1
Views: 472
Reputation: 11346
I ended up solving this by creating a singleton scoped component that would track the report. When the service call is being made, it would first check the component to see if there is a Future
for the given id. If not, it would add the Future
in that component and start the process. If the component returned a Future
, it would call cancel on that Future
and start a new service call.
Upvotes: 1