Scheduling
A module for creating declarative-style planners using annotations.
When applying aspects, class must not be final
When applying aspects, class must be open
Native¶
Creating a scheduler using the standard ScheduledExecutorService that comes with the JVM.
In order to create a scheduler via aspects, special annotations are used that essentially duplicate the ScheduledExecutorService
method signatures.
The parameters of the annotations correspond to the parameters of the methods scheduleAtFixedRate
, schedule
, scheduleWithFixedDelay
respectively.
Also all annotations have the config
argument, if it is present, the parameter values will be taken from the configuration on the specified path.
Dependency¶
Dependency build.gradle
:
Module:
Dependency build.gradle.kts
:
Module:
Configuration¶
Example of the complete configuration described in the ScheduledExecutorServiceConfig
class (default values are specified):
scheduling {
threads = 20 //(1)!
shutdownWait = "30s" //(2)!
telemetry {
logging {
enabled = false //(3)!
}
metrics {
enabled = true //(4)!
slo = [ 1, 10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000, 90000 ] //(5)!
}
tracing {
enabled = true //(6)!
}
}
}
- Maximum number of threads in ScheduledExecutorService
- Time to wait for jobs to complete before shutting down the scheduler in case of graceful shutdown
- Enables module logging (default
false
) - Enables module metrics (default
true
) - Configuring SLO for DistributionSummary metrics
- Enables module tracing (default
true
)
scheduling:
threads: 20 #(1)!
shutdownWait: "30s" #(2)!
telemetry:
logging:
enabled: false #(3)!
metrics:
enabled: true #(4)!
slo: [ 1, 10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000, 90000 ] #(5)!
telemetry:
enabled: true #(6)!
- Maximum number of threads in ScheduledExecutorService
- Time to wait for jobs to complete before shutting down the scheduler in case of graceful shutdown
- Enables module logging (default
false
) - Enables module metrics (default
true
) - Configuring SLO for DistributionSummary metrics
- Enables module tracing (default
true
)
Fixed rate¶
Scheduling with startup at fixed intervals.
For example, if the period is set to 10 seconds and each task execution takes 5 seconds to complete, then the task will run every 10 seconds.
But if a task execution takes longer to complete than the defined period, the next execution will start only after the current one finishes. The task executions will not happen concurrently.
Configuration¶
It is possible to transfer parameters via configuration, it has priority over the parameters specified in the annotation:
SomeService of configuration via a config file:
Fixed delay¶
Awaits fixed delay from the end of the previous task execution before starting the next execution.
It does not matter how long the current execution takes, the next execution is started exactly after the previous task is finished and the specified waiting interval between tasks.
Configuration¶
It is possible to transfer parameters via configuration, it has priority over the parameters specified in the annotation:
SomeService of configuration via a config file:
Once¶
Runs a single task at a certain fixed time interval.
Configuration¶
It is possible to transfer parameters via configuration, it has priority over the parameters specified in the annotation:
SomeService of configuration via a config file:
Graceful Shutdown¶
If you want to pre-terminate processing on a scheduled service termination without waiting for the service to end, you need to check Thread.currentThread().isInterrupted() status and terminate the service yourself.
Quartz¶
A library-based implementation of Quartz as a scheduler for creating aspects.
Dependency¶
Dependency build.gradle
:
Module:
Dependency build.gradle.kts
:
Module:
Configuration¶
Configuration is specified as Properties values in key and value format:
quartz { //(1)!
"org.quartz.threadPool.threadCount" = "10"
}
scheduling {
waitForJobComplete = true //(2)!
telemetry {
logging {
enabled = false //(3)!
}
metrics {
enabled = true //(4)!
slo = [ 1, 10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000, 90000 ] //(5)!
}
tracing {
enabled = true //(6)!
}
}
}
- Quartz scheduler configuration parameters
- Whether to wait for jobs to complete before shutting down scheduler in case of graceful shutdown
- Enables module logging (default
false
) - Enables module metrics (default
true
) - Configuring SLO for DistributionSummary metrics
- Enables module tracing (default
true
)
quartz: #(1)!
org.quartz.threadPool.threadCount: "10"
scheduling:
waitForJobComplete: true #(2)!
telemetry:
logging:
enabled: false #(3)!
metrics:
enabled: true #(4)!
slo: [ 3, 10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 30000, 60000, 90000 ] #(5)!
telemetry:
enabled: true #(6)!
- Quartz scheduler configuration parameters
- Whether to wait for jobs to complete before shutting down scheduler in case of graceful shutdown
- Enables module logging (default
false
) - Enables module metrics (default
true
) - Configuring SLO for DistributionSummary metrics
- Enables module tracing (default
true
)
Default settings are used from:
quartz.properties
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
Cron¶
Usage Cron expressions to run scheduled tasks.
Starts a single task at a certain fixed time interval.
Configuration¶
It is possible to transfer parameters via configuration, it has priority over the parameters specified in the annotation:
Configuration example:
Trigger¶
This involves creating your custom trigger
based on the Quartz library and registering it in the application dependency container with a specific tag and then using it via annotation.
@KoraApp
public interface Application extends QuartzModule {
@Tag(SomeService.class) //(1)!
default Trigger myTrigger() {
return TriggerBuilder.newTrigger()
.withIdentity("myTrigger")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(50)
.repeatForever())
.build();
}
}
@Component
public class SomeService {
@ScheduleWithTrigger(@Tag(SomeService.class)) //(2)!
void schedule() {
// do something
}
}
- Trigger tag
- Trigger tag
@KoraApp
interface Application : QuartzModule {
@Tag(SomeService::class) //(1)!
fun myTrigger(): Trigger {
return TriggerBuilder.newTrigger()
.withIdentity("myTrigger")
.startNow()
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(50)
.repeatForever()
)
.build()
}
}
@Component
class SomeService {
@ScheduleWithTrigger(@Tag(SomeService.class)) //(2)!
fun schedule() {
// do something
}
}
- Trigger tag
- Trigger tag