I have a problem to solve in a project that I'm not sure how to proceed. I have an endpoint that receives a file to be processed. This file is large so I want to include it in a list, return a response with something like "Element added to the processing list" and then using a scheduler process all the data.
I implemented an scheduler who check every second if new elements were include in the list, and if they are, I start to process the information, just like this:
@Service
@Transactional("generation-transaction_manager")
@Slf4j
@EnableScheduling
public class SchedulerService
{
@Scheduled(fixedRate = 1000)
public void checkList()
{
if (!OwnConfiguration.fileList.isEmpty())
{
// Do something
}
}
}
But I think is not an efficient approach, I want to only execute that method when an element was include in the list, something like a trigger.
Do you know what classes or libraries I need to use? I'm a little bit desperate
Edit: Just run a method asynchronously doesn't work on this case because I need to load the files one per one, validating that the previous one was successly loaded. I need to be sure that the previous file was loaded before to start with the next one
CodePudding user response:
The "best" way to do this would be with queues. https://docs.spring.io/spring-amqp/reference/html/ It has many added advantages, but it's more complex.
The other way is asynchronous methods. You say that you have a problem with the order of execution. You can use threadpool singleThreadExecutor to achieve that (instead of async/await), it should respect the order in which the tasks are started. (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor())
Relevant javadoc quote:
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
But the very best solution is going to be using a queue, you get much more resilience, the ability to run multiple pods (all other solutions are going to break if you scale up your service) and so on.
CodePudding user response:
You can create your own class who extends ArrayList and override the add method where you can add a call for a fireAction method "the trigger"
class MyArrayList<X> extends ArrayList<X>{
//...
//...
// override the add method here
public boolean add (X x) {
fireAction();
super.add(x);
}
public static void fireAction(){
// .... put your code here
}
}