====================
== alfr3dosv blog ==
====================

Replacing quartz with db-scheduler

I was recently tasked with replacing quartz with a simpler solution, db-scheduler was the library I chose because was a good fit, it was simple, the task are easy to configure and only 1 table is needed in the database.

The first thing I did was add the dependency to my spring boot project

<dependency>
    <groupId>com.github.kagkarlsson</groupId>
    <artifactId>db-scheduler</artifactId>
    <version>10.3</version>
</dependency>

In the repository there is a spring boot starter project

Example image

I copied the configuration classes to my own project and made some changes to suit my needs for example i didn’t want tasks to start by default so I changed Scheduler scheduler

@ConditionalOnBean(DataSource.class)
@ConditionalOnMissingBean
@Bean(destroyMethod = "stop")
public Scheduler scheduler(DbSchedulerCustomizer customizer, StatsRegistry registry) {
    ...
    final SchedulerBuilder builder = Scheduler.create(transactionalDataSource, nonStartupTasks(configuredTasks));
    // to 
    final SchedulerBuilder builder = Scheduler.create(transactionalDataSource, configuredTasks);
    ...
}
@ConditionalOnBean(DataSource.class)
@ConditionalOnMissingBean
@Bean(destroyMethod = "stop")
public Scheduler scheduler(DbSchedulerCustomizer customizer, StatsRegistry registry) {
    ...
    builder.startTasks(startupTasks(configuredTasks)); // removed
    ...
}

And then I added the default settings to my application.properties

# Db-scheduler configuration
db-scheduler.threads=5
db-scheduler.polling-interval=5s

db-scheduler.polling-strategy=fetch
db-scheduler.polling-strategy-lower-limit-fraction-of-threads=0.5
db-scheduler.polling-strategy-upper-limit-fraction-of-threads=3.0

I configured all tasks and then made another service in wich I inject the scheduler and the List<Task> tasks to schedule, pause and cancel tasks;

package com.exampletasks.demo.configuration;

import com.github.kagkarlsson.scheduler.task.Task;
import com.github.kagkarlsson.scheduler.task.helper.Tasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

import static com.github.kagkarlsson.scheduler.task.schedule.Schedules.fixedDelay;

@Configuration
public class TaskConfiguration {
    private static final Logger log = LoggerFactory.getLogger(TaskConfiguration.class);

    @Bean
    Task<Void> recurringSampleTask() {
        Task task = Tasks
                .recurring("recurring-sample-task", fixedDelay(Duration.ofMinutes(1)))
                .execute((instance, ctx) -> {
                    log.info("Running recurring-simple-task. Instance: {}, ctx: {}", instance, ctx);
                });
        return task;
    }
}

I needed to implement my own schedule to schedule recurring tasks each month

package com.bitfarm.ibox.model.task;

import com.github.kagkarlsson.scheduler.task.ExecutionComplete;
import com.github.kagkarlsson.scheduler.task.schedule.Schedule;

import java.time.*;

public class MonthlySchedule implements Schedule {
    @Override
    public Instant getNextExecutionTime(ExecutionComplete executionComplete) {
        ZoneId systemZone = ZoneId.systemDefault();
        LocalDateTime date = executionComplete.getTimeDone().atZone(systemZone).toLocalDateTime().plusMonths(1);
        Instant instant = date.atZone(systemZone).toInstant();
        return instant;
    }

    @Override
    public boolean isDeterministic() {
        return false;
    }
}