Skip to content

Commit

Permalink
3.2.4-SNAPSHOT
Browse files Browse the repository at this point in the history
Signed-off-by: Sinri Edogawa <[email protected]>
  • Loading branch information
sinri committed Apr 10, 2024
1 parent 02e2d04 commit f482735
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 62 deletions.
20 changes: 10 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,10 @@
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>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<vertxVersion>4.5.4</vertxVersion>
<commonmarkVersion>0.21.0</commonmarkVersion>
<jacksonVersion>2.15.3</jacksonVersion>
<poiVersion>5.2.5</poiVersion>
</properties>

<groupId>io.github.sinri</groupId>
<artifactId>Keel</artifactId>
<!-- <version>3.2.3-SNAPSHOT</version>-->
<version>3.2.3</version>
<version>3.2.4-SNAPSHOT</version>
<!-- <version>3.2.3</version>-->

<name>Keel</name>
<description>
Expand Down Expand Up @@ -44,6 +36,14 @@
</developer>
</developers>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<vertxVersion>4.5.4</vertxVersion>
<commonmarkVersion>0.21.0</commonmarkVersion>
<jacksonVersion>2.15.3</jacksonVersion>
<poiVersion>5.2.5</poiVersion>
</properties>

<dependencies>
<dependency>
<groupId>io.vertx</groupId>
Expand Down
57 changes: 40 additions & 17 deletions src/main/java/io/github/sinri/keel/core/KeelCronExpression.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.sinri.keel.core;


import javax.annotation.Nonnull;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -13,9 +15,9 @@ public class KeelCronExpression {
final Set<Integer> dayOptions = new HashSet<>();
final Set<Integer> monthOptions = new HashSet<>();
final Set<Integer> weekdayOptions = new HashSet<>();
private final String rawCronExpression;
private final @Nonnull String rawCronExpression;

public KeelCronExpression(String rawCronExpression) {
public KeelCronExpression(@Nonnull String rawCronExpression) {
this.rawCronExpression = rawCronExpression;

String[] parts = rawCronExpression.trim().split("\\s+");
Expand All @@ -36,24 +38,20 @@ public KeelCronExpression(String rawCronExpression) {
parseField(weekdayExpression, weekdayOptions, 0, 6);
}

public boolean match(Calendar currentCalendar) {
// currentCalendar := Calendar.getInstance();
int minute = currentCalendar.get(Calendar.MINUTE);
int hour = currentCalendar.get(Calendar.HOUR_OF_DAY);
int day = currentCalendar.get(Calendar.DAY_OF_MONTH);
int month = 1 + currentCalendar.get(Calendar.MONTH);// make JAN 1, ...
int weekday = currentCalendar.get(Calendar.DAY_OF_WEEK) - 1; // make sunday 0, ...

return minuteOptions.contains(minute)
&& hourOptions.contains(hour)
&& dayOptions.contains(day)
&& monthOptions.contains(month)
&& weekdayOptions.contains(weekday);
public boolean match(@Nonnull Calendar currentCalendar) {
ParsedCalenderElements parsedCalenderElements = new ParsedCalenderElements(currentCalendar);
return match(parsedCalenderElements);
}

private void parseField(String rawComponent, Set<Integer> optionSet, int min, int max) {
// System.out.println("parseField: " + rawComponent);
public boolean match(@Nonnull ParsedCalenderElements parsedCalenderElements) {
return minuteOptions.contains(parsedCalenderElements.minute)
&& hourOptions.contains(parsedCalenderElements.hour)
&& dayOptions.contains(parsedCalenderElements.day)
&& monthOptions.contains(parsedCalenderElements.month)
&& weekdayOptions.contains(parsedCalenderElements.weekday);
}

private void parseField(@Nonnull String rawComponent, @Nonnull Set<Integer> optionSet, int min, int max) {
if (rawComponent.equals("*")) {
for (int i = min; i <= max; i++) {
optionSet.add(i);
Expand Down Expand Up @@ -106,10 +104,35 @@ private void parseField(String rawComponent, Set<Integer> optionSet, int min, in
}
}

@Nonnull
public String getRawCronExpression() {
return rawCronExpression;
}

/**
* @since 3.2.4
*/
public static class ParsedCalenderElements {
public final int minute;
public final int hour;
public final int day;
public final int month;
public final int weekday;

public ParsedCalenderElements(@Nonnull Calendar currentCalendar) {
minute = currentCalendar.get(Calendar.MINUTE);
hour = currentCalendar.get(Calendar.HOUR_OF_DAY);
day = currentCalendar.get(Calendar.DAY_OF_MONTH);
month = 1 + currentCalendar.get(Calendar.MONTH);// make JAN 1, ...
weekday = currentCalendar.get(Calendar.DAY_OF_WEEK) - 1; // make sunday 0, ...
}

@Override
public String toString() {
return minute + " " + hour + " " + day + " " + month + " " + weekday;
}
}

@Override
public String toString() {
return getRawCronExpression();
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/io/github/sinri/keel/facade/KeelInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import io.github.sinri.keel.logger.KeelLogLevel;
import io.github.sinri.keel.logger.event.KeelEventLogger;
import io.github.sinri.keel.logger.issue.center.KeelIssueRecordCenter;
import io.vertx.core.*;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.spi.cluster.ClusterManager;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -130,7 +133,7 @@ public KeelInstance setLogger(@Nonnull KeelEventLogger eventLogger) {
return this;
}

public Future<Void> gracefullyClose(@Nonnull Handler<Promise<Void>> promiseHandler) {
public Future<Void> gracefullyClose(@Nonnull io.vertx.core.Handler<Promise<Void>> promiseHandler) {
Promise<Void> promise = Promise.promise();
promiseHandler.handle(promise);
return promise.future().compose(v -> getVertx().close());
Expand Down
75 changes: 43 additions & 32 deletions src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package io.github.sinri.keel.servant.sundial;

import io.github.sinri.keel.core.KeelCronExpression;
import io.github.sinri.keel.facade.async.KeelAsyncKit;
import io.github.sinri.keel.logger.event.KeelEventLogger;
import io.github.sinri.keel.logger.issue.center.KeelIssueRecordCenter;
import io.github.sinri.keel.verticles.KeelVerticleImplWithEventLogger;
import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

import static io.github.sinri.keel.facade.KeelInstance.Keel;

/**
* @since 3.0.0
* @since 3.2.4 use verticle to handle the sundial plan executing.
*/
public abstract class KeelSundial extends KeelVerticleImplWithEventLogger {
private final Map<String, KeelSundialPlan> planMap = new ConcurrentHashMap<>();
Expand All @@ -33,47 +36,55 @@ public void start() throws Exception {
this.timerID = Keel.getVertx().setPeriodic(delaySeconds, 60_000L, timerID -> {
Calendar calendar = Calendar.getInstance();
handleEveryMinute(calendar);
refreshPlans();
});
}

private void handleEveryMinute(Calendar now) {
KeelCronExpression.ParsedCalenderElements parsedCalenderElements = new KeelCronExpression.ParsedCalenderElements(now);
planMap.forEach((key, plan) -> {
if (plan.cronExpression().match(now)) {
if (plan.cronExpression().match(parsedCalenderElements)) {
getLogger().debug("Sundial Plan Matched", new JsonObject()
.put("plan_key", plan.key())
.put("plan_cron", plan.cronExpression())
.put("now", parsedCalenderElements.toString())
);
plan.execute(now);
} else {
getLogger().debug("Sundial Plan Not Match", new JsonObject()
.put("plan_key", plan.key())
.put("plan_cron", plan.cronExpression())
.put("now", parsedCalenderElements.toString())
);
}
});

// refresh plan, pfs {0: not-fetching, more: fetching}
if (planFetchingSemaphore.get() == 0) {
planFetchingSemaphore.incrementAndGet();
fetchPlans()
.compose(plans -> {
if (plans == null) {
// treat null as NOT MODIFIED
return Future.succeededFuture();
}
Set<String> toDelete = new HashSet<>(planMap.keySet());
plans.forEach(plan -> {
toDelete.remove(plan.key());
planMap.put(plan.key(), plan);
});
if (!toDelete.isEmpty()) {
toDelete.forEach(planMap::remove);
}
return Future.succeededFuture();
})
.eventually(() -> {
planFetchingSemaphore.decrementAndGet();
return Future.succeededFuture();
});

}

}

@Deprecated(since = "3.0.1", forRemoval = true)
protected Supplier<Collection<KeelSundialPlan>> plansSupplier() {
return null;
/**
* @since 3.2.4
*/
private void refreshPlans() {
KeelAsyncKit.exclusivelyCall(
"io.github.sinri.keel.servant.sundial.KeelSundial.refreshPlans",
1000L,
() -> {
return fetchPlans()
.compose(plans -> {
// treat null as NOT MODIFIED
if (plans != null) {
Set<String> toDelete = new HashSet<>(planMap.keySet());
plans.forEach(plan -> {
toDelete.remove(plan.key());
planMap.put(plan.key(), plan);
});
if (!toDelete.isEmpty()) {
toDelete.forEach(planMap::remove);
}
}
return Future.succeededFuture();
});
}
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package io.github.sinri.keel.servant.sundial;

import io.github.sinri.keel.core.KeelCronExpression;
import io.vertx.core.Future;

import java.util.Calendar;

/**
* @since 3.0.0
* @since 3.2.4 change sync method `execute` to be async.
*/
public interface KeelSundialPlan {
String key();

KeelCronExpression cronExpression();

void execute(Calendar now);
Future<Void> execute(Calendar now);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.sinri.keel.servant.sundial;

import io.github.sinri.keel.verticles.KeelVerticleImplPure;
import io.vertx.core.Future;

import javax.annotation.Nonnull;
import java.util.Calendar;

/**
* @since 3.2.4
*/
public class KeelSundialVerticle extends KeelVerticleImplPure {
private final KeelSundialPlan sundialPlan;
private final Calendar now;

public KeelSundialVerticle(@Nonnull KeelSundialPlan sundialPlan, Calendar now) {
this.sundialPlan = sundialPlan;
this.now = now;
}

@Override
public void start() throws Exception {
Future.succeededFuture()
.compose(v -> {
return sundialPlan.execute(now);
})
.onComplete(ar -> {
undeployMe();
});
}
}

0 comments on commit f482735

Please sign in to comment.