Skip to content

Commit

Permalink
Merge pull request #43563 from mkouba/issue-issue-22824-docs
Browse files Browse the repository at this point in the history
Scheduler: document `@Scheduled#executionMaxDelay()`
  • Loading branch information
mkouba authored Sep 27, 2024
2 parents 03e46f6 + d71c9f9 commit ceb7e30
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 11 deletions.
27 changes: 23 additions & 4 deletions docs/src/main/asciidoc/scheduler-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ Property Expressions. (Note that `"{property.path}"` style expressions are still
void myMethod() { }
----

=== Delayed Execution
[[delayed_start]]
=== Delayed Start of a Trigger

`@Scheduled` provides two ways to delay the time a trigger should start firing at.

Expand Down Expand Up @@ -249,9 +250,8 @@ void everyTwoSeconds() { }
NOTE: If `@Scheduled#delay()` is set to a value greater than zero the value of `@Scheduled#delayed()` is ignored.

The main advantage over `@Scheduled#delay()` is that the value is configurable.
The `delay` attribute supports <<config-reference#property-expressions,Property Expressions>> including default values and nested
Property Expressions. (Note that `"{property.path}"` style expressions are still supported but don't offer the full functionality of Property Expressions.)

The `delay` attribute supports <<config-reference#property-expressions,Property Expressions>> including default values and nested Property Expressions.
(Note that `"{property.path}"` style expressions are still supported but don't offer the full functionality of Property Expressions.)

[source,java]
----
Expand All @@ -260,6 +260,25 @@ void everyTwoSeconds() { }
----
<1> The config property `myMethod.delay.expr` is used to set the delay.

[[delayed_execution]]
=== Delayed Execution

`@Scheduled#executionMaxDelay()` can be set to delay each execution of a scheduled method.
The value represents the maximum delay between the activation of the trigger and the execution of the scheduled method.
The actual delay is a randomized number between 0 and the maximum specified delay.

The value is parsed with `DurationConverter#parseDuration(String)`.
It can be a property expression, in which case, the scheduler attempts to use the configured value instead: `@Scheduled(executionMaxDelay = "${myJob.maxDelay}")`.
Additionally, the property expression can specify a default value:
`@Scheduled(executionMaxDelay = "${myJob.maxDelay}:500ms}")`.

[source,java]
----
@Scheduled(every = "2s", executionMaxDelay = "500ms") <1>
void everyTwoSeconds() { }
----
<1> The delay will be a value between 0 and 500 milliseconds. As a result, the period between to `everyTwoSeconds()` executions will be roughly between one and a half and two and a half seconds.

[[concurrent_execution]]
=== Concurrent Execution

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.scheduler.test.delayedexecution;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.CountDownLatch;
Expand All @@ -11,8 +10,10 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.runtime.StartupEvent;
import io.quarkus.scheduler.DelayedExecution;
import io.quarkus.scheduler.Scheduled;
import io.quarkus.scheduler.Scheduler;
import io.quarkus.test.QuarkusUnitTest;

public class DelayedExecutionTest {
Expand All @@ -24,23 +25,38 @@ public class DelayedExecutionTest {
@Test
public void testSimpleScheduledJobs() throws InterruptedException {
assertTrue(Jobs.EVENT_LATCH.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH1.await(5, TimeUnit.SECONDS));
assertTrue(Jobs.LATCH2.await(5, TimeUnit.SECONDS));
}

static class Jobs {

static final CountDownLatch LATCH = new CountDownLatch(1);
static final CountDownLatch EVENT_LATCH = new CountDownLatch(1);
static final CountDownLatch LATCH1 = new CountDownLatch(1);
static final CountDownLatch LATCH2 = new CountDownLatch(1);
static final CountDownLatch EVENT_LATCH = new CountDownLatch(2);

@Scheduled(identity = "foo", every = "1s", executionMaxDelay = "500ms")
static void everySecond() {
LATCH.countDown();
LATCH1.countDown();
}

void start(@Observes StartupEvent event, Scheduler scheduler) {
scheduler.newJob("bar")
.setInterval("1s")
.setExecutionMaxDelay("500ms")
.setTask(se -> {
LATCH2.countDown();
}).schedule();
}

void onDelay(@Observes DelayedExecution delayedExecution) {
assertTrue(delayedExecution.getDelay() < 500);
assertEquals("foo", delayedExecution.getExecution().getTrigger().getId());
EVENT_LATCH.countDown();
String id = delayedExecution.getExecution().getTrigger().getId();
if ("foo".equals(id) || "bar".equals(id)) {
EVENT_LATCH.countDown();
} else {
throw new IllegalStateException("Invalid job identity: " + id);
}
}

}
Expand Down

0 comments on commit ceb7e30

Please sign in to comment.