1.8. Scheduling#
Zamanlanmış görevler tanımlanmasını sağlayan bileşendir. Uygulama cluster özelliklerini sağlar (distributable). Quartz library'si kulanılmaktadır.
Konfigurasyon#
Gradle Bağımlılıkları
Cluster Konfigürasyonları
Veritabanında cluster olan bir uygulamadır. Quartz tabloları manuel ya da liquibase ile initialize edilebilir.
spring:
quartz:
scheduler-name: ${spring.application.name}
auto-startup: true
startup-delay: 2s
overwrite-existing-jobs: true
job-store-type: jdbc
liquibase:
parameters:
quartz-jdbc-job-store-schema: ${hvl.scheduling.quartz.jdbc-job-store.schema-name}
quartz-jdbc-job-store-table-prefix: ${hvl.scheduling.quartz.jdbc-job-store.table-prefix}
Liquibase
Liquibase konfigürasyonu için; changelog-root.yaml dosyasına; aşağıdaki gibi quartz changelog dosya tanımı eklenmelidir.
Çevre Değişkenleri
Cloud profili olarak "hvl-scheduling" verilerek, ya da bootstrap.yml dosyasına yapılan aşağıdaki tanımlamalarla çevre değişkenleri yönetilebilir.
-
QUARTZ_JDBC_JOB_STORE_SCHEMA (schema-name): Scheduler'ın kullandığı şema adıdır (default değerini hibernate'den alınır).
-
"table-prefix": Quartz tablolarına koyulacak ön ektir (default değeri "qrz_"dır).
ÖNEMLİ NOT: Varsayılan olarak her uygulamanın default şemasında quartz tabloları oluşmaktadır. Bazı durumlarda quartz tablolarının tek şemada olması ya da ortak scheduler kullanımları gibi durumlar için bu property'ler yararlıdır. Örneğin; "oauth", "report" ve "bpmn" şemalarımız olsun. Bu şemalarda quartz tabloları olması istenmeyebilir. Bu durumda "schedule" şema ismi tanımlanır. "oauth", "report" ve "bpmn" uygulamalarının quartz scheduler'ların olduğunu varsayalım. Bu uygulamalar için ortak şema kullanmak istediğimizde yukarıdaki "schema-name" property'si değeri kullanılır.
ÖNEMLİ NOT: Varsayılan olarak her uygulamanın içerisine quartz dahil edildiğinde otokonfigurasyon tarafından uygulamanın adı ile tanımlanmış bir scheduler oluşmaktadır. Yani uygulama adı; "scheduler name"'dir. Sebebi; ortak bir arayüzden uygulamadaki planlanmış görevler yönetilmek istendiğinde, uygulama bazlı ayrı yapılmasının sağlanmasıdır.
Kullanım#
Bileşen iki farklı şekilde kullanılabilir.
-
@HvlDistributableScheduled anotasyonu metodun üzerine yazılır ve bu anotasyonun property'leri örnekte görüldüğü gibi doldururulur.
jobName: Quartz job adıdır.
jobGroupName: Quartz job grup adıdır.
jobTriggers: Quartz job trigger tanımıdır.
triggerType: Quartz job'ın trigger tipidir.
triggerExp: Quartz job'ın belirlenen trigger tipine uygun expression değeridir.
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Service;
import tr.com.havelsan.javarch.scheduling.annotation.HvlDistributableScheduled;
import tr.com.havelsan.javarch.scheduling.annotation.HvlJobTrigger;
import tr.com.havelsan.javarch.scheduling.annotation.HvlJobTriggerType;
import java.time.OffsetDateTime;
@Service
public class AnnotatedJobService {
AnnotatedJobService() {
super();
}
@HvlDistributableScheduled(
jobGroupName = "sample-job-group",
jobTriggers = @HvlJobTrigger(
triggerType = HvlJobTriggerType.CRON,
triggerExp = "0/59 * * * * ?"
)
)
public void scheduledWithCron(JobExecutionContext jobExecutionContext) {
System.err.println("scheduledWithCron triggered." + "(" + OffsetDateTime.now() + ")");
}
@HvlDistributableScheduled(
jobName = "scheduled-with-second",
jobGroupName = "sample-job-group",
jobTriggers = @HvlJobTrigger(
triggerType = HvlJobTriggerType.FIXED_RATE,
triggerExp = "PT15S"
)
)
public void scheduledWithSecond(JobExecutionContext jobExecutionContext) {
System.err.println("scheduledWithSecond triggered. (" + OffsetDateTime.now() + ")");
}
}
- Bir diğer kullanım ise; HvlQuartzExecutableJob sınıfını extend eden bir class oluşturmaktır.
import org.quartz.JobExecutionContext;
import tr.com.havelsan.javarch.scheduling.quartz.job.HvlQuartzExecutableJob;
import java.time.OffsetDateTime;
import java.util.Set;
public class SampleJob extends HvlQuartzExecutableJob {
@Override
protected Integer jobExecutionMaxRetryCount() {
return 3;
}
@Override
protected Set<Class<? extends Throwable>> whenJobExecutionRetry() {
return Set.of();
}
@Override
protected void executeJobInstance(JobExecutionContext jobExecutionContext) {
System.err.println("job executed. (" + OffsetDateTime.now() + ")");
}
}
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import tr.com.havelsan.javarch.configuration.HvlBaseConfiguration;
import tr.com.havelsan.javarch.samples.scheduling.configuration.constant.HvlSchedulingConfigurationConstant;
import tr.com.havelsan.javarch.samples.scheduling.job.SampleJob;
/**
* @author javarch
*/
@Configuration
@ComponentScan(basePackages = {HvlSchedulingConfigurationConstant.BASE_PACKAGE})
public class HvlSchedulingConfiguration extends HvlBaseConfiguration {
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.storeDurably()
.build();
}
@Bean
public Trigger sampleTrigger() {
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("triggerName", "group1")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(30)
.repeatForever())
.build();
}
}