springspring-bootscheduled-tasksshedlock

Shedlock: What happens when scheduled tasks share the same shedlock ID?


An application in our domain has 2 specific scheduled tasks; one that is required to run every minute, and one heavy bulk operation to be performed in the middle of the night. As performing both operations at the same time would overload the external server, ShedLock has been implemented to prevent the operations being run simultaneously.

The following ShedLock configuration is used (notice the same IDs):

@Scheduled("0 * * * * *")
@SchedulerLock(name = "sameShedLockId", lockAtLeastFor = "PT59S", lockAtMostFor = "PT59S")
public void runEveryMinute() {
  // ...
}

@Scheduled(cron = "0 0 1 * * *")
@SchedulerLock(name = "sameShedLockId", lockAtLeastFor = "PT10M", lockAtMostFor = "PT15M")
public void runOnceEveryNight() {
  // ...
}

What would happen around 01:00:00 in the morning, when both methods attempt to obtain the same lock and runEveryMinute is able to obtain the lock? Would runOnceEveryNight be put in some sort of ShedLock waiting queue until the lock has been released, or would the task simply not be executed? And if this indeed the case, what would be a better setup to prevent the tasks from being simultaneously around 01:00 in the night?

I wouldn't mind runEveryMinute being skipped once every night, however if runOnceEveryNight is skipped it would take 24 hours until the task is reattempted.


Solution

  • The one that doesn't get the lock is skipped in ShedLock.

    Those 2 being at the same time, I guess it is impossible to know which one will get the lock.

    I guess the easy "fix" is to change runEveryMinute to @Scheduled("10 * * * * *") (or something else that is not 0 for sec) assuming it doesn't take more than 49 seconds to run in my example. In these situations, It is probably best to have as much margin as possible so you avoid some racing condition. i.e. if the runEveryMinutes takes only 1-2 sec, set the cron to around 30 for seconds so it has time both ways.

    Note that all runEveryMinute will be skipped until runOnceEveryNight is complete.