ShedLock: Running multiple instances runs scheduler tasks multiple times

20,200

Solution 1

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.

Solution 2

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>

Solution 3

Please try with cron expression inside @scheduled instead of fixedDelayString, below scheduler run every hour.

@Scheduled(cron = "0 */1 * * *")
Share:
20,200
varunkr
Author by

varunkr

Maverick !

Updated on August 27, 2020

Comments

  • varunkr
    varunkr over 3 years

    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 !!