I am using Shedlock
to run my scheduler
task only once if multiple instances of the service are running.
I followed the documentation and this is what I did.
This is the function that needs to run periodically
@Scheduled(fixedDelayString = "300000")
@SchedulerLock(name = "onlineIngestionTask", lockAtMostFor = 240000, lockAtLeastFor = 240000)
public void pullTasksFromRemote() {
//Code
}
In my config class I have the following beans
@Bean
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
@Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
The pom includes
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>0.14.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>0.14.0</version>
</dependency>
I added a table to my db, the one to which jdbc connects.
CREATE TABLE shedlock(
name VARCHAR(64),
lock_until TIMESTAMP(3) NULL,
locked_at TIMESTAMP(3) NULL,
locked_by VARCHAR(255),
PRIMARY KEY (name)
)
After this I tried to test the functionality by running tha pp first on port 8080. Then I use server.port=9000
to run it again on port 9000. But both these instances start running the task. Am I missing something. Is something wrong in the implementation? Can someone give any ideas. Thanks !!
ShedLock makes sure that your scheduled tasks are executed at most once at the same time. If a task is being executed on one node, it acquires a lock which prevents execution of the same task from another node (or thread).
ShedLock is a distributed lock for scheduled tasks. It ensures a task is only executed once at the same time. Once the first Spring Boot instance acquires the lock for a scheduled task, all other instances will skip the task execution.
We can choose to delay the first execution of the method by specifying the interval using the initialDelay attribute. We can deploy multiple Scheduler Instances using the ShedLock library which ensures only one instance to run at a time by using a locking mechanism in a shared database.
dlock guarantees to have one lock at any time by using database indexes and constraints. You can simply do something like below.
@Scheduled(cron = "30 30 3 * * *")
@TryLock(name = "onlineIngestionTask", owner = SERVER_NAME, lockFor = 240000)
public void pullTasksFromRemote() {
}
See the article about using it.
we recently had this issue in prod where we could see multiple runs of shedlock schedulers. if you are using spring boot 2.2.1.RELEASE onwards then use below deps for shedlock
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-redis-spring</artifactId>
<version>4.8.0</version>
</dependency>
Please try with cron expression inside @scheduled
instead of fixedDelayString
, below scheduler run every hour.
@Scheduled(cron = "0 */1 * * *")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With