3

What I want to do:

I want to implement a retry mechanism for function dailyComputeValue. dailyComputeValue will call computeValue. There is one part within function ComputeValue where we will call externalService.getRecord, which could return an empty list.

If this is the case, I want to rerun the function every 10 min until it does not return an empty list (Once externalService.getRecord does not return an empty list when we run checkExpiryForADate, we would not run it anymore within the scheduled timeframe (from 7AM to 9AM)

The complication is that I cannot use a boolean flag in this case because computeValue needs to return a double. So I am thinking of throwing an exception if externalService.getRecord returns an empty list. I have changed dailyComputeValue to be like the code below to implement the retry mechanism

What I have tried:

@Scheduled(cron = "${scheduler: */10 7-8 * * MON-FRI}")
public void dailyComputeValue() {
  double value = 0;
  try {
      value = computeValue(String product);
  } 
  catch {
     log.warn("Record not available yet", ex.getMessage();)
  }
  //to only save to database if there is good value (not from the empty list)
  valueRepository.save(value);
}

public Double computeValue(String product)
{
    List<Pair<ZonedDateTime, Double>> valueRecords = new ArrayList<>(externalService.getRecord());
    if (valueRecords.isEmpty()){
    throw new Exception("Record not available yet");
    }
    //perform some operation to return a double
}

The problem with my code:

The current code will retry computeValue every 10 minutes, but will not stop once computeValue returns a double. I am not sure how to implement the code to "rerun the function every 10 min until it does not return an empty list (Once externalService.getRecord does not return an empty list when we run dailyComputeValue, we would not run it anymore within the scheduled timeframe (from 7AM to 9AM)".

Any help would be greatly appreciated, thanks in advance.

w97802
  • 109
  • 6
exponents
  • 33
  • 4

2 Answers2

0

One way you can use while loop inside try block with 10 minutes sleep time when externalService.getRecord() return empty list. And make computeValue method to return null if empty list is returned by externalService.getRecord()

In this case you can keep the scheduler to run between 7AM to 9AM

 double value = null;

 try {

     while(value == null) {

        value = computeValue(String product);

        if(value == null){
           Thread.sleep(10) //minutes
        }
     }
  } 
    catch {
      log.warn("Record not available yet", ex.getMessage();)
  }

You can also check Spring Retry but you have to specify the max number of retries and you can keep it Integer.MAX.

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
0

I tried to replicate your question, here is one possible solution.

private double value = null;
private long lastSuccess;

@Scheduled(cron = "${scheduler: */10 7-8 * * MON-FRI}")
public void dailyComputeValue() {

  if(value != null && 
     lastSuccess != null && 
     !sameDate(lastSuccess, System.currentTimeMillis()){
     // resetting value in new day
     value = null;
  }
  
  if(value != null) return; // skipping scheduled job if value is present

  try {
     value = computeValue(String product);
  } catch (Exception ex) {
     log.warn("Record not available yet", ex.getMessage();)
     return;
  }

  lastSuccess = System.currentTimeMillis();
  valueRepository.save(value);
}

Checking same date:

private Boolean sameDate(long d1, long d2){
  Calendar cal1 = Calendar.getInstance();
  Calendar cal2 = Calendar.getInstance();
  cal1.setTimeInMillis(d1);
  cal2.setTimeInMillis(d2);
  return cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
                        cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
}

Hope it is of some help.

Phil Ku
  • 191
  • 1
  • 6