1

inside a Spring web application I have a scheduled task that is called every five minutes.

 @Scheduled(fixedDelay = 300000)
     public void importDataTask()
{
    importData(); //db calls, file manipulations, etc..
}

Usually the task runs smoothly for days, but sometimes happens that the example method importaData()will not terminate, so importDataTask()will not be called again and everything will be blocked until I restart the application.

The question is: is there a feasibile method to be sure that a method will not be indefinitely blocked (waybe waiting for a resource, or something else)?

davidxxx
  • 125,838
  • 23
  • 214
  • 215
frankieta
  • 962
  • 1
  • 9
  • 31
  • finding the deadlock will be a better approach, we dont know where is it getting struck. so i doubt we can provide ideas for a fix. – Srinath Ganesh Oct 29 '16 at 15:00

2 Answers2

1

The question is: is there a feasibile method to be sure that a method will not be indefinitely blocked (waybe waiting for a resource, or something else)?

If the scheduling cannot be planned at a precise regular interval, you should maybe not use a fixed delay but use two conditions : delay + last execution done.
You could schedule a task which checks if the two conditions are met and if it the case, you run the important processing. Otherwise, it waits for the next schedule.
In this way, you should not be blocked. You could wait for some time if the task exceeds the fixed delay. If it is a problem because the fixed delay is often exceeded, you should probably not use a fixed delay or so you should increase sensitively it in order that it is less common.

Here an example (writing without editor. Sorry if any mistake) :

private boolean isLastImportDataTaskFinished;

@Scheduled(fixedDelay = 300000)
 public void importDataTaskManager(){
    if (isLastImportDataTaskFinished()){
        new Thread(new ImportantDataProcessing())).start();           
    }
    else{
        // log the problem if you want
    }
}

 private isLastImportDataTaskFinished(){
   // to retrieve this information, you can do as you want : use a variable 
   //  in this class or a data in database,file...
   // here a simple implementation 
   return isLastImportDataTaskFinished;
 }

Runnable class :

 public class ImportantDataProcessing implements Runnable{
   public void run(){       
      importData(); //db calls, file manipulations, etc..    
  }
}

Comment:

But if I run it as a thread how can I kill it if I find it's exceeding the time limit since I don't have any reference to it (in the idea of using a second task to determine the stuck state)?

You can use an ExecutorService (you have a question about it here : How to timeout a thread).

Here a very simple example :

ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(new ImportantDataProcessing());
try {
    future.get(100, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
    e.printStackTrace();
}
catch (ExecutionException e) {
    e.printStackTrace();
}
catch (TimeoutException e) {
    // the timeout to handle but other exceptions should be handled :)  
    e.printStackTrace();
}
executor.shutdown();

If interesting information may be returned by ImportantDataProcessing processing , you can use a task instead of a runnable instance to type the future.

Community
  • 1
  • 1
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Thanks @davidxxx, I have a doubt though. If the method importData() is blocked for whatever reason the next iteration of importDataTask() will not be called since the fixedDelay will wait for the termination of the previous batch since it's not concurrent. The idea to log the last import date is good since in this way I could have a SECOND task only for checking this value (from db) and see if too much time passed so I can interpret it as stuck. But then? Maybe I should look into Threads functionalities. – frankieta Oct 29 '16 at 15:09
  • 1
    Indeed. To avoid that, you could run importData() in a new Thread. In this way importDataTaskManager() will not be blocking. I update my answer :) However, if importData() is never terminated, the problem is much more serious. Using a second task is also a idea. – davidxxx Oct 29 '16 at 15:14
  • I will definitely try it. Since the data to import can be huge the first time I think I will divide it in chunks and import them a chunk at a time every time the scheduled task runs. But if I run it as a thread how can I kill it if I find it's exceeding the time limit since I don't have any reference to it (in the idea of using a second task to determine the stuck state)? Sorry if maybe I'm steering away for the original question. – frankieta Oct 29 '16 at 15:33
  • 1
    JDK provides mechanisms to do it. I will edit my answer to add that information. No problem. Sometimes, problems are a little complicated :) – davidxxx Oct 29 '16 at 15:38
0

Firstly, sure. There are many feasibile methods to remind you if the process is blocked, such as log/message/email which embed in you code.

Secondly, it is decided by if you want it block or not. If block is not you intention, new thread or timeout may be you choice.

younghz
  • 66
  • 3
  • Yes, block is not my intention. The limited time interval (5 mins) is because the users wants to see the result of the import in semi-real time. – frankieta Oct 29 '16 at 15:15