Added basic components.
This commit is contained in:
parent
576146d9e1
commit
10dbec8226
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>nl.andrewlalis</groupId>
|
||||||
|
<artifactId>simply-scheduled</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<java.version>11</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit</groupId>
|
||||||
|
<artifactId>junit-bom</artifactId>
|
||||||
|
<version>5.7.1</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter</artifactId>
|
||||||
|
<version>5.7.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,5 @@
|
||||||
|
module simply_scheduled {
|
||||||
|
exports nl.andrewlalis.simply_scheduled;
|
||||||
|
exports nl.andrewlalis.simply_scheduled.schedule;
|
||||||
|
opens nl.andrewlalis.simply_scheduled;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled;
|
||||||
|
|
||||||
|
import nl.andrewlalis.simply_scheduled.schedule.Schedule;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class BasicScheduler implements Scheduler {
|
||||||
|
private ScheduledExecutorService executorService;
|
||||||
|
private final Clock clock;
|
||||||
|
|
||||||
|
public BasicScheduler(Clock clock) {
|
||||||
|
this.clock = clock;
|
||||||
|
this.executorService = new ScheduledThreadPoolExecutor(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasicScheduler() {
|
||||||
|
this(Clock.systemDefaultZone());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTask(Runnable task, Schedule schedule) {
|
||||||
|
Instant nextExecution = schedule.getNextExecutionTime(this.clock.instant());
|
||||||
|
long diff = nextExecution.toEpochMilli() - System.currentTimeMillis();
|
||||||
|
if (diff < 1) return; // Exit immediately, if the next scheduled execution is in the past.
|
||||||
|
this.executorService.schedule(task, diff, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(boolean force) {
|
||||||
|
if (this.executorService != null) {
|
||||||
|
if (force) {
|
||||||
|
this.executorService.shutdownNow();
|
||||||
|
} else {
|
||||||
|
this.executorService.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled;
|
||||||
|
|
||||||
|
import nl.andrewlalis.simply_scheduled.schedule.Schedule;
|
||||||
|
|
||||||
|
public interface Scheduler {
|
||||||
|
void addTask(Runnable task, Schedule schedule);
|
||||||
|
void start();
|
||||||
|
void stop(boolean force);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled.schedule;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
|
||||||
|
public class DailySchedule implements Schedule {
|
||||||
|
private final ZoneId zoneId;
|
||||||
|
private final LocalTime time;
|
||||||
|
|
||||||
|
public DailySchedule(LocalTime time) {
|
||||||
|
this(time, ZoneId.systemDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DailySchedule(LocalTime time, ZoneId zoneId) {
|
||||||
|
this.time = time;
|
||||||
|
this.zoneId = zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
|
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
||||||
|
LocalDate currentDay = LocalDate.from(referenceInstant);
|
||||||
|
ZonedDateTime sameDayExecution = currentDay.atTime(this.time).atZone(this.zoneId);
|
||||||
|
if (sameDayExecution.isBefore(currentTime)) {
|
||||||
|
return sameDayExecution.toInstant();
|
||||||
|
}
|
||||||
|
return sameDayExecution.plusDays(1).toInstant();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled.schedule;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
public class HourlySchedule implements Schedule {
|
||||||
|
private final ZoneId zoneId;
|
||||||
|
private final int minute;
|
||||||
|
|
||||||
|
public HourlySchedule(int minute) {
|
||||||
|
this(minute, ZoneId.systemDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HourlySchedule(int minute, ZoneId zoneId) {
|
||||||
|
if (minute < 0 || minute > 59) {
|
||||||
|
throw new IllegalArgumentException("Minute must be in the range [0, 59].");
|
||||||
|
}
|
||||||
|
this.zoneId = zoneId;
|
||||||
|
this.minute = minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Instant getNextExecutionTime(Instant referenceInstant) {
|
||||||
|
ZonedDateTime currentTime = referenceInstant.atZone(this.zoneId);
|
||||||
|
int currentMinute = currentTime.getMinute();
|
||||||
|
if (currentMinute < this.minute) {
|
||||||
|
return currentTime.truncatedTo(ChronoUnit.MINUTES).plusMinutes(this.minute - currentMinute).toInstant();
|
||||||
|
}
|
||||||
|
return currentTime.plusHours(1).plusMinutes(this.minute).truncatedTo(ChronoUnit.MINUTES).toInstant();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled.schedule;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public interface Schedule {
|
||||||
|
Instant getNextExecutionTime(Instant referenceInstant);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package nl.andrewlalis.simply_scheduled;
|
||||||
|
|
||||||
|
import nl.andrewlalis.simply_scheduled.schedule.HourlySchedule;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class SchedulerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSchedule() {
|
||||||
|
Clock clock = Clock.fixed(Instant.now(), ZoneOffset.UTC);
|
||||||
|
Scheduler scheduler = new BasicScheduler(clock);
|
||||||
|
LocalTime time = LocalTime.now();
|
||||||
|
int secondsLeft = 60 - time.getSecond() + 1;
|
||||||
|
AtomicBoolean flag = new AtomicBoolean(false);
|
||||||
|
scheduler.addTask(() -> flag.set(true), new HourlySchedule(time.getMinute() + 1));
|
||||||
|
scheduler.start();
|
||||||
|
System.out.printf("Waiting %d seconds for task to run...", secondsLeft);
|
||||||
|
try {
|
||||||
|
Thread.sleep(secondsLeft * 1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
assertTrue(flag.get());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue