From f5307edb731e8b5e680d25bee1d3d8a358a93e95 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Thu, 21 Mar 2024 13:42:10 +0800 Subject: [PATCH 01/13] 3.2.3-SNAPSHOT Signed-off-by: Sinri Edogawa --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8da945..33519bb 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A Java framework with VERT.X eco, for projects for web, job and more. io.github.sinri Keel - 3.1.9 + 3.2.2 ``` From f30cafd2ac57f94b8da62db6ec841f6de943be42 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Fri, 29 Mar 2024 11:44:30 +0800 Subject: [PATCH 02/13] 3.2.3-SNAPSHOT Replace KeelConfiguration with KeelConfigElement Signed-off-by: Sinri Edogawa --- .../elasticsearch/ElasticSearchConfig.java | 23 +- .../sinri/keel/email/smtp/KeelSmtpKit.java | 14 +- .../sinri/keel/facade/KeelConfiguration.java | 1 + .../sinri/keel/facade/KeelInstance.java | 17 +- .../facade/async/FutureForEachBreakable.java | 39 +++ .../sinri/keel/facade/async/KeelAsyncKit.java | 8 + .../configuration/KeelConfigElement.java | 329 ++++++++++++++++++ .../facade/configuration/package-info.java | 1 + .../keel/mysql/KeelMySQLConfiguration.java | 72 ++-- .../mysql/KeelMySQLDataSourceProvider.java | 8 +- .../io/github/sinri/keel/redis/RedisKit.java | 3 +- .../keel/test/lab/blocking/AsyncTest.java | 75 ++++ .../keel/test/lab/unit/KeelConfigTest.java | 26 ++ 13 files changed, 550 insertions(+), 66 deletions(-) create mode 100644 src/main/java/io/github/sinri/keel/facade/async/FutureForEachBreakable.java create mode 100644 src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java create mode 100644 src/main/java/io/github/sinri/keel/facade/configuration/package-info.java create mode 100644 src/test/java/io/github/sinri/keel/test/lab/blocking/AsyncTest.java create mode 100644 src/test/java/io/github/sinri/keel/test/lab/unit/KeelConfigTest.java diff --git a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java index bbab325..056f2e7 100644 --- a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java +++ b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java @@ -1,9 +1,10 @@ package io.github.sinri.keel.elasticsearch; -import io.github.sinri.keel.facade.KeelConfiguration; +import io.github.sinri.keel.facade.configuration.KeelConfigElement; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import java.util.Objects; import static io.github.sinri.keel.facade.KeelInstance.Keel; @@ -11,14 +12,14 @@ /** * @since 3.0.7 */ -public class ElasticSearchConfig extends KeelConfiguration { +public class ElasticSearchConfig extends KeelConfigElement { - public ElasticSearchConfig(KeelConfiguration configuration) { + public ElasticSearchConfig(KeelConfigElement configuration) { super(configuration); } public ElasticSearchConfig(String esKey) { - this(Keel.getConfiguration().extract("es", esKey)); + this(Keel.getConfiguration().extractConfigElement("es", esKey)); } /* @@ -34,25 +35,23 @@ public ElasticSearchConfig(String esKey) { */ public String username() { - return readString("username"); + return getValueAsString("username", null); } public String password() { - return readString("password"); + return getValueAsString("password", null); } public @Nonnull String clusterHost() { - return Objects.requireNonNull(readString("cluster", "host")); + return Objects.requireNonNull(getValueAsString(List.of("cluster", "host"), null)); } public int clusterPort() { - String s = readString("cluster", "port"); - return Integer.parseInt(Objects.requireNonNullElse(s, "9200")); + return getValueAsInteger(List.of("cluster", "port"), 9200); } public @Nonnull String clusterScheme() { - String s = readString("cluster", "scheme"); - return Objects.requireNonNullElse(s, "http"); + return Objects.requireNonNull(getValueAsString(List.of("cluster", "scheme"), "http")); } public @Nonnull String clusterApiUrl(@Nonnull String endpoint) { @@ -60,6 +59,6 @@ public int clusterPort() { } public @Nullable String opaqueId() { - return readString("opaqueId"); + return getValueAsString("opaqueId", null); } } diff --git a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java index 48f5b5f..87a5329 100644 --- a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java +++ b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java @@ -1,6 +1,5 @@ package io.github.sinri.keel.email.smtp; -import io.github.sinri.keel.facade.KeelConfiguration; import io.vertx.core.Future; import io.vertx.ext.mail.MailClient; import io.vertx.ext.mail.MailConfig; @@ -55,14 +54,15 @@ public KeelSmtpKit() { * As of 3.0.6, only five property keys supported. */ private static MailConfig buildMailConfig(@Nonnull String smtpName) { - KeelConfiguration smtpConfiguration = Keel.getConfiguration().extract("email", "smtp", smtpName); + var smtpConfiguration = Keel.getConfiguration().extractConfigElement("email", "smtp", smtpName); + Objects.requireNonNull(smtpConfiguration); var mailConfig = new MailConfig(); - mailConfig.setHostname(smtpConfiguration.readString("hostname")); - mailConfig.setPort(Objects.requireNonNull(smtpConfiguration.readAsInteger("port"))); - mailConfig.setUsername(smtpConfiguration.readString("username")); - mailConfig.setPassword(smtpConfiguration.readString("password")); - mailConfig.setSsl("ON".equals(smtpConfiguration.readString("ssl"))); + mailConfig.setHostname(smtpConfiguration.getValueAsString("hostname", null)); + mailConfig.setPort(smtpConfiguration.getValueAsInteger("port", 25)); + mailConfig.setUsername(smtpConfiguration.getValueAsString("username", null)); + mailConfig.setPassword(smtpConfiguration.getValueAsString("password", null)); + mailConfig.setSsl(smtpConfiguration.getValueAsBoolean("ssl", false)); return mailConfig; } diff --git a/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java b/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java index 8e12e15..c020160 100644 --- a/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java +++ b/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java @@ -19,6 +19,7 @@ /** * @since 3.0.0 */ +@Deprecated(since = "3.2.3", forRemoval = true) public class KeelConfiguration implements JsonifiableEntity { private @Nonnull JsonObject data = new JsonObject(); diff --git a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java index 630638c..d40cfd6 100644 --- a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java +++ b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java @@ -1,12 +1,12 @@ package io.github.sinri.keel.facade; import io.github.sinri.keel.facade.cluster.KeelClusterKit; +import io.github.sinri.keel.facade.configuration.KeelConfigElement; import io.github.sinri.keel.helper.KeelHelpersInterface; 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.json.JsonObject; import io.vertx.core.spi.cluster.ClusterManager; import javax.annotation.Nonnull; @@ -19,7 +19,10 @@ public class KeelInstance implements KeelHelpersInterface, KeelClusterKit { public static KeelInstance Keel = new KeelInstance(); - private final @Nonnull KeelConfiguration configuration; + /** + * @since 3.2.3 + */ + private final @Nonnull KeelConfigElement configuration; private @Nullable Vertx vertx; private @Nullable ClusterManager clusterManager; /** @@ -29,19 +32,23 @@ public class KeelInstance implements KeelHelpersInterface, KeelClusterKit { private KeelEventLogger eventLogger; private KeelInstance() { - this.configuration = KeelConfiguration.createFromJsonObject(new JsonObject()); + this.configuration = new KeelConfigElement(""); this.eventLogger = KeelIssueRecordCenter.outputCenter().generateEventLogger("Keel"); this.eventLogger.setVisibleLevel(KeelLogLevel.WARNING); } @Nonnull - public KeelConfiguration getConfiguration() { + public KeelConfigElement getConfiguration() { return configuration; } public @Nullable String config(@Nonnull String dotJoinedKeyChain) { String[] split = dotJoinedKeyChain.split("\\."); - return getConfiguration().readString(split); + KeelConfigElement keelConfigElement = this.configuration.extractConfigElement(split); + if (keelConfigElement == null) { + return null; + } + return keelConfigElement.getValueAsString(); } public @Nonnull Vertx getVertx() { diff --git a/src/main/java/io/github/sinri/keel/facade/async/FutureForEachBreakable.java b/src/main/java/io/github/sinri/keel/facade/async/FutureForEachBreakable.java new file mode 100644 index 0000000..96a8264 --- /dev/null +++ b/src/main/java/io/github/sinri/keel/facade/async/FutureForEachBreakable.java @@ -0,0 +1,39 @@ +package io.github.sinri.keel.facade.async; + +import io.vertx.core.Future; + +import javax.annotation.Nonnull; +import java.util.Iterator; +import java.util.function.BiFunction; + +/** + * @since 3.2.3 + */ +public class FutureForEachBreakable { + + @Nonnull + private final Iterable iterable; + @Nonnull + private final BiFunction> itemProcessor; + private FutureForEachBreakable(@Nonnull Iterable iterable, @Nonnull BiFunction> itemProcessor) { + this.iterable = iterable; + this.itemProcessor = itemProcessor; + } + + public static Future call(@Nonnull Iterable iterable, @Nonnull BiFunction> itemProcessor) { + return new FutureForEachBreakable<>(iterable, itemProcessor).start(); + } + + private Future start() { + Iterator iterator = iterable.iterator(); + return KeelAsyncKit.repeatedlyCall(routineResult -> { + if (iterator.hasNext()) { + T next = iterator.next(); + return this.itemProcessor.apply(next, routineResult); + } else { + routineResult.stop(); + return Future.succeededFuture(); + } + }); + } +} diff --git a/src/main/java/io/github/sinri/keel/facade/async/KeelAsyncKit.java b/src/main/java/io/github/sinri/keel/facade/async/KeelAsyncKit.java index c3d4c15..e060f04 100644 --- a/src/main/java/io/github/sinri/keel/facade/async/KeelAsyncKit.java +++ b/src/main/java/io/github/sinri/keel/facade/async/KeelAsyncKit.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -81,6 +82,13 @@ static Future iterativelyBatchCall(@Nonnull Iterator iterator, @Non }); } + /** + * @since 3.2.3 + */ + static Future iterativelyCall(@Nonnull Iterable iterable, @Nonnull BiFunction> itemProcessor) { + return FutureForEachBreakable.call(iterable, itemProcessor); + } + /** * @since 2.9 callFutureForRange * @since 3.0.0 stepwiseCall diff --git a/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java new file mode 100644 index 0000000..60698d2 --- /dev/null +++ b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java @@ -0,0 +1,329 @@ +package io.github.sinri.keel.facade.configuration; + +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.FileReader; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + + +public class KeelConfigElement { + @Nonnull + private final String name; + @Nonnull + private final Map children; + @Nullable + private String value; + + public KeelConfigElement(@Nonnull String name) { + this.name = name; + this.value = null; + this.children = new ConcurrentHashMap<>(); + } + + public KeelConfigElement(@Nonnull KeelConfigElement another) { + this.name = another.getName(); + this.children = another.getChildren(); + this.value = another.getValueAsString(); + } + + public static KeelConfigElement fromJsonObject(@Nonnull JsonObject jsonObject) { + String name = jsonObject.getString("name"); + KeelConfigElement keelConfigElement = new KeelConfigElement(name); + if (jsonObject.containsKey("value")) { + keelConfigElement.value = jsonObject.getString("value"); + } + JsonArray children = jsonObject.getJsonArray("children"); + children.forEach(child -> { + if (child instanceof JsonObject) { + keelConfigElement.addChild(fromJsonObject((JsonObject) child)); + } else { + throw new IllegalArgumentException(); + } + }); + return keelConfigElement; + } + + @Nonnull + public String getName() { + return name; + } + + @Nullable + public String getValueAsString() { + return value; + } + + @Nullable + public String getValueAsString(@Nullable String def) { + return Objects.requireNonNullElse(value, def); + } + + @Nullable + public String getValueAsString(@Nonnull List keychain, @Nullable String def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsString(def); + } + + @Nullable + public String getValueAsString(@Nonnull String keychain, @Nullable String def) { + return getValueAsString(List.of(keychain), def); + } + + @Nullable + public Integer getValueAsInteger() { + if (value == null) return null; + return Integer.parseInt(value); + } + + public int getValueAsInteger(int def) { + if (value == null) return def; + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return def; + } + } + + public int getValueAsInteger(@Nonnull List keychain, int def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsInteger(def); + } + + public int getValueAsInteger(@Nonnull String keychain, int def) { + return getValueAsInteger(List.of(keychain), def); + } + + @Nullable + public Long getValueAsLong() { + if (value == null) return null; + return Long.parseLong(value); + } + + public long getValueAsLong(long def) { + if (value == null) return def; + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return def; + } + } + + public long getValueAsLong(@Nonnull List keychain, long def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsLong(def); + } + + public long getValueAsLong(@Nonnull String keychain, long def) { + return getValueAsLong(List.of(keychain), def); + } + + @Nullable + public Float getValueAsFloat() { + if (value == null) return null; + return Float.parseFloat(value); + } + + public float getValueAsFloat(float def) { + if (value == null) return def; + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + return def; + } + } + + public float getValueAsFloat(@Nonnull List keychain, float def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsFloat(def); + } + + public float getValueAsFloat(@Nonnull String keychain, float def) { + return getValueAsFloat(List.of(keychain), def); + } + + @Nullable + public Double getValueAsDouble() { + if (value == null) return null; + return Double.parseDouble(value); + } + + public double getValueAsDouble(double def) { + if (value == null) return def; + try { + return Double.parseDouble(value); + } catch (NumberFormatException e) { + return def; + } + } + + public double getValueAsDouble(@Nonnull List keychain, double def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsDouble(def); + } + + public double getValueAsDouble(@Nonnull String keychain, double def) { + return getValueAsDouble(List.of(keychain), def); + } + + @Nullable + public Boolean getValueAsBoolean() { + if (value == null) return null; + return "YES".equalsIgnoreCase(value) || "TRUE".equalsIgnoreCase(value); + } + + public boolean getValueAsBoolean(boolean def) { + if (value == null) return def; + return "YES".equalsIgnoreCase(value) + || "TRUE".equalsIgnoreCase(value) + || "ON".equalsIgnoreCase(value) + || "1".equalsIgnoreCase(value) + ; + } + + public boolean getValueAsBoolean(@Nonnull List keychain, boolean def) { + KeelConfigElement extracted = this.extractConfigElement(keychain); + if (extracted == null) return def; + return extracted.getValueAsBoolean(def); + } + + public boolean getValueAsBoolean(@Nonnull String keychain, boolean def) { + return getValueAsBoolean(List.of(keychain), def); + } + + public KeelConfigElement ensureChild(@Nonnull String childName) { + return this.children.computeIfAbsent(childName, x -> new KeelConfigElement(childName)); + } + + public KeelConfigElement addChild(@Nonnull KeelConfigElement child) { + this.children.put(child.getName(), child); + return this; + } + + public KeelConfigElement removeChild(@Nonnull KeelConfigElement child) { + this.children.remove(child.getName()); + return this; + } + + public KeelConfigElement removeChild(@Nonnull String childName) { + this.children.remove(childName); + return this; + } + + public KeelConfigElement setValue(@Nonnull String value) { + this.value = value; + return this; + } + + @Nonnull + public Map getChildren() { + return children; + } + + @Nullable + public KeelConfigElement getChild(@Nonnull String childName) { + return children.get(childName); + } + + public JsonObject toJsonObject() { + JsonArray childArray = new JsonArray(); + children.forEach((cName, c) -> childArray.add(c.toJsonObject())); + var x = new JsonObject() + .put("name", name) + .put("children", childArray); + if (value != null) { + x.put("value", value); + } + return x; + } + + public @Nullable KeelConfigElement extractConfigElement(@Nonnull List split) { + if (split.isEmpty()) return null; + if (split.size() == 1) return this.children.get(split.get(0)); + KeelConfigElement keelConfigElement = this.children.get(split.get(0)); + if (keelConfigElement == null) { + return null; + } + for (int i = 1; i < split.size(); i++) { + keelConfigElement = keelConfigElement.getChild(split.get(i)); + if (keelConfigElement == null) { + return null; + } + } + return keelConfigElement; + } + + public @Nullable KeelConfigElement extractConfigElement(@Nonnull String... split) { + List list = Arrays.asList(split); + return this.extractConfigElement(list); + } + + public KeelConfigElement loadProperties(@Nonnull Properties properties) { + properties.forEach((k, v) -> { + String fullKey = k.toString(); + String[] keyArray = fullKey.split("\\."); + KeelConfigElement keelConfigElement = null; + for (int i = 0; i < keyArray.length; i++) { + String key = keyArray[i]; + if (i == 0) { + keelConfigElement = children.computeIfAbsent(key, x -> new KeelConfigElement(key)); + } else { + keelConfigElement = keelConfigElement.ensureChild(key); + } + if (i == keyArray.length - 1) { + keelConfigElement.setValue(properties.getProperty(fullKey)); + } + } + }); + return this; + } + + /** + * @since 3.0.1 + */ + public @Nonnull KeelConfigElement loadPropertiesFile(@Nonnull String propertiesFileName) { + return loadPropertiesFile(propertiesFileName, StandardCharsets.UTF_8); + } + + public @Nonnull KeelConfigElement loadPropertiesFile(@Nonnull String propertiesFileName, @Nonnull Charset charset) { + Properties properties = new Properties(); + try { + // here, the file named as `propertiesFileName` should be put along with JAR + properties.load(new FileReader(propertiesFileName, charset)); + } catch (IOException e) { + System.err.println("Cannot find the file config.properties. Use the embedded one."); + try { + properties.load(getClass().getClassLoader().getResourceAsStream(propertiesFileName)); + } catch (IOException ex) { + throw new RuntimeException("Cannot find the embedded file config.properties.", ex); + } + } + + return loadProperties(properties); + } + + /** + * @since 3.0.6 + */ + public @Nonnull KeelConfigElement loadPropertiesFileContent(@Nonnull String content) { + Properties properties = new Properties(); + try { + properties.load(new StringReader(content)); + } catch (IOException e) { + throw new RuntimeException("Cannot load given properties content.", e); + } + return loadProperties(properties); + } +} diff --git a/src/main/java/io/github/sinri/keel/facade/configuration/package-info.java b/src/main/java/io/github/sinri/keel/facade/configuration/package-info.java new file mode 100644 index 0000000..788bae3 --- /dev/null +++ b/src/main/java/io/github/sinri/keel/facade/configuration/package-info.java @@ -0,0 +1 @@ +package io.github.sinri.keel.facade.configuration; \ No newline at end of file diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java index cb304b8..f9d0238 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java @@ -1,7 +1,7 @@ package io.github.sinri.keel.mysql; import io.github.sinri.keel.core.TechnicalPreview; -import io.github.sinri.keel.facade.KeelConfiguration; +import io.github.sinri.keel.facade.configuration.KeelConfigElement; import io.github.sinri.keel.mysql.matrix.ResultMatrix; import io.vertx.core.Future; import io.vertx.mysqlclient.MySQLBuilder; @@ -9,6 +9,7 @@ import io.vertx.sqlclient.PoolOptions; import javax.annotation.Nonnull; +import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -24,31 +25,18 @@ * poolShared = false; * tcpKeepAlive=false; */ -public class KeelMySQLConfiguration extends KeelConfiguration { - private final @Nonnull String dataSourceName; - - public KeelMySQLConfiguration(@Nonnull String dataSourceName, @Nonnull KeelConfiguration keelConfiguration) { - this.dataSourceName = dataSourceName; - this.reloadDataFromJsonObject(keelConfiguration.toJsonObject()); - } - -// public String buildJDBCConnectionString() { -// MySQLConnectOptions connectOptions = getConnectOptions(); -// var host = connectOptions.getHost(); -// var port = connectOptions.getPort(); -// var schema = connectOptions.getDatabase(); -// var charset = connectOptions.getCharset(); -// boolean ssl = connectOptions.isSsl(); -// return "jdbc:mysql://" + host + ":" + port + "/" + schema -// + "?useSSL=" + (ssl ? "true" : "false") + "&useUnicode=true" + -// "&characterEncoding=" + charset -// + "&allowPublicKeyRetrieval="+(ssl ? "true" : "false"); -// } +public class KeelMySQLConfiguration extends KeelConfigElement { + //private final @Nonnull String dataSourceName; + + public KeelMySQLConfiguration(@Nonnull KeelConfigElement base) { + super(base); + } + @Nonnull - public static KeelMySQLConfiguration loadConfigurationForDataSource(@Nonnull KeelConfiguration keelConfiguration, @Nonnull String dataSourceName) { - KeelConfiguration configuration = keelConfiguration.extract("mysql", dataSourceName); - return new KeelMySQLConfiguration(dataSourceName, configuration); + public static KeelMySQLConfiguration loadConfigurationForDataSource(@Nonnull KeelConfigElement configCenter, @Nonnull String dataSourceName) { + KeelConfigElement keelConfigElement = configCenter.extractConfigElement("mysql", dataSourceName); + return new KeelMySQLConfiguration(Objects.requireNonNull(keelConfigElement)); } @Nonnull @@ -94,44 +82,46 @@ public PoolOptions getPoolOptions() { } public String getHost() { - return readString("host"); + return getValueAsString(List.of("host"), null); } public Integer getPort() { - return Objects.requireNonNullElse(readAsInteger("port"), 3306); + return getValueAsInteger(List.of("port"), 3306); } public String getPassword() { - return readString("password"); + return getValueAsString(List.of("password"), null); } public String getUsername() { - var u = readString("username"); + var u = getValueAsString("username", null); if (u == null) { - u = readString("user"); + u = getValueAsString("user", null); } return u; } public String getDatabase() { - String schema = readString("schema"); + String schema = getValueAsString("schema", null); if (schema == null) { - schema = readString("database"); + schema = getValueAsString("database", null); } return Objects.requireNonNullElse(schema, ""); } public String getCharset() { - return readString("charset"); + return getValueAsString("charset", null); } public Integer getPoolMaxSize() { - return readAsInteger("poolMaxSize"); + var x = getChild("poolMaxSize"); + if (x == null) return null; + return x.getValueAsInteger(); } @Nonnull public String getDataSourceName() { - return dataSourceName; + return getName(); } /** @@ -141,7 +131,11 @@ public String getDataSourceName() { * @since 3.0.1 let it be its original setting! */ private Integer getConnectionTimeout() { - return readAsInteger("connectionTimeout"); + var x = getChild("connectionTimeout"); + if (x == null) { + return null; + } + return x.getValueAsInteger(); } /** @@ -152,7 +146,11 @@ private Integer getConnectionTimeout() { * @see ... */ public Integer getPoolConnectionTimeout() { - return readAsInteger("poolConnectionTimeout"); + KeelConfigElement keelConfigElement = extractConfigElement("poolConnectionTimeout"); + if (keelConfigElement == null) { + return null; + } + return keelConfigElement.getValueAsInteger(); } /** @@ -162,7 +160,7 @@ public Integer getPoolConnectionTimeout() { * that created it is undeployed. */ public boolean getPoolShared() { - return !("NO".equals(readString("poolShared"))); + return getValueAsBoolean("poolShared", true); } diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java index 74f3847..2ee49f8 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java @@ -1,9 +1,9 @@ package io.github.sinri.keel.mysql; -import io.github.sinri.keel.facade.KeelConfiguration; import io.vertx.sqlclient.SqlConnection; import javax.annotation.Nonnull; +import java.util.List; import java.util.Objects; import java.util.function.Function; @@ -13,7 +13,7 @@ public class KeelMySQLDataSourceProvider { @Nonnull public static String defaultMySQLDataSourceName() { - return Objects.requireNonNullElse(Keel.getConfiguration().readString("mysql", "default_data_source_name"), "default"); + return Objects.requireNonNull(Keel.getConfiguration().getValueAsString(List.of("mysql", "default_data_source_name"), "default")); } /** @@ -24,9 +24,9 @@ public static NamedMySQLDataSource initializ @Nonnull String dataSourceName, Function sqlConnectionWrapper ) { - KeelConfiguration configuration = Keel.getConfiguration().extract("mysql", dataSourceName); + var configuration = Keel.getConfiguration().extractConfigElement("mysql", dataSourceName); Objects.requireNonNull(configuration); - KeelMySQLConfiguration mySQLConfigure = new KeelMySQLConfiguration(dataSourceName, configuration); + KeelMySQLConfiguration mySQLConfigure = new KeelMySQLConfiguration(configuration); return new NamedMySQLDataSource<>(mySQLConfigure, sqlConnectionWrapper); } diff --git a/src/main/java/io/github/sinri/keel/redis/RedisKit.java b/src/main/java/io/github/sinri/keel/redis/RedisKit.java index cd7071f..0272dca 100644 --- a/src/main/java/io/github/sinri/keel/redis/RedisKit.java +++ b/src/main/java/io/github/sinri/keel/redis/RedisKit.java @@ -7,6 +7,7 @@ import io.vertx.redis.client.RedisConnection; import io.vertx.redis.client.RedisOptions; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; @@ -23,7 +24,7 @@ public RedisKit(String redisInstanceKey) { /* * URL should be redis://[:password@]host[:port][/db-number] */ - String url = Keel.getConfiguration().readString("redis", redisInstanceKey, "url"); + String url = Keel.getConfiguration().getValueAsString(List.of("redis", redisInstanceKey, "url"), null); Objects.requireNonNull(url); this.client = Redis.createClient(Keel.getVertx(), new RedisOptions() .setConnectionString(url) diff --git a/src/test/java/io/github/sinri/keel/test/lab/blocking/AsyncTest.java b/src/test/java/io/github/sinri/keel/test/lab/blocking/AsyncTest.java new file mode 100644 index 0000000..8a9ebe7 --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/blocking/AsyncTest.java @@ -0,0 +1,75 @@ +package io.github.sinri.keel.test.lab.blocking; + +import io.github.sinri.keel.facade.async.KeelAsyncKit; +import io.github.sinri.keel.tesuto.KeelTest; +import io.github.sinri.keel.tesuto.TestUnit; +import io.vertx.core.Future; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class AsyncTest extends KeelTest { + + @TestUnit + public Future foreachBreakableTest() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + list.add(i); + } + + var x = new ForeachBreakable(list) { + + @Override + protected Future handleItem(Integer item, AtomicBoolean breakAtomic) { + getLogger().info("handle " + item); + if (item % 5 == 4) { + breakAtomic.set(true); + } + return Future.succeededFuture(); + } + }; + return x.start() + .compose(Future::succeededFuture) + .onSuccess(v -> { + getLogger().notice("FIN"); + }) + .onFailure(e -> { + getLogger().exception(e); + }); + } + + public abstract static class ForeachBreakable { + private final Iterable iterable; + private final AtomicBoolean breakRef = new AtomicBoolean(false); + + public ForeachBreakable(Iterable iterable) { + this.iterable = iterable; + } + + public Future start() { + Iterator iterator = iterable.iterator(); + return KeelAsyncKit.repeatedlyCall(routineResult -> { + if (iterator.hasNext()) { + T next = iterator.next(); + return handleItem(next, breakRef) + .compose(x -> { + if (breakRef.get()) { + routineResult.stop(); + } + return Future.succeededFuture(); + }); + } else { + routineResult.stop(); + return Future.succeededFuture(); + } + }); + } + + abstract protected Future handleItem(T item, AtomicBoolean breakAtomic); + + } + + +} diff --git a/src/test/java/io/github/sinri/keel/test/lab/unit/KeelConfigTest.java b/src/test/java/io/github/sinri/keel/test/lab/unit/KeelConfigTest.java new file mode 100644 index 0000000..1673d50 --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/unit/KeelConfigTest.java @@ -0,0 +1,26 @@ +package io.github.sinri.keel.test.lab.unit; + +import io.github.sinri.keel.tesuto.KeelTest; +import io.github.sinri.keel.tesuto.TestUnit; +import io.vertx.core.Future; + +import javax.annotation.Nonnull; + +import static io.github.sinri.keel.facade.KeelInstance.Keel; + +public class KeelConfigTest extends KeelTest { + + @Nonnull + @Override + protected Future starting() { + Keel.getConfiguration().loadPropertiesFile("config.properties"); + return Future.succeededFuture(); + } + + @TestUnit + public Future readTest() { + getLogger().info("all", Keel.getConfiguration().toJsonObject()); + getLogger().info("email.smtp.default_smtp_name: " + Keel.config("email.smtp.default_smtp_name")); + return Future.succeededFuture(); + } +} From a96b5dce83feff7a0164aef9875834c321e7b848 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Fri, 29 Mar 2024 12:01:18 +0800 Subject: [PATCH 03/13] 3.2.3-SNAPSHOT call back extract Signed-off-by: Sinri Edogawa --- .../elasticsearch/ElasticSearchConfig.java | 2 +- .../sinri/keel/email/smtp/KeelSmtpKit.java | 2 +- .../github/sinri/keel/facade/KeelInstance.java | 2 +- .../configuration/KeelConfigElement.java | 18 +++++++++--------- .../keel/mysql/KeelMySQLConfiguration.java | 4 ++-- .../mysql/KeelMySQLDataSourceProvider.java | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java index 056f2e7..696559f 100644 --- a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java +++ b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java @@ -19,7 +19,7 @@ public ElasticSearchConfig(KeelConfigElement configuration) { } public ElasticSearchConfig(String esKey) { - this(Keel.getConfiguration().extractConfigElement("es", esKey)); + this(Keel.getConfiguration().extract("es", esKey)); } /* diff --git a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java index 87a5329..7ca75fa 100644 --- a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java +++ b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java @@ -54,7 +54,7 @@ public KeelSmtpKit() { * As of 3.0.6, only five property keys supported. */ private static MailConfig buildMailConfig(@Nonnull String smtpName) { - var smtpConfiguration = Keel.getConfiguration().extractConfigElement("email", "smtp", smtpName); + var smtpConfiguration = Keel.getConfiguration().extract("email", "smtp", smtpName); Objects.requireNonNull(smtpConfiguration); var mailConfig = new MailConfig(); diff --git a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java index d40cfd6..6a51217 100644 --- a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java +++ b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java @@ -44,7 +44,7 @@ public KeelConfigElement getConfiguration() { public @Nullable String config(@Nonnull String dotJoinedKeyChain) { String[] split = dotJoinedKeyChain.split("\\."); - KeelConfigElement keelConfigElement = this.configuration.extractConfigElement(split); + KeelConfigElement keelConfigElement = this.configuration.extract(split); if (keelConfigElement == null) { return null; } diff --git a/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java index 60698d2..2706145 100644 --- a/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java +++ b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java @@ -68,7 +68,7 @@ public String getValueAsString(@Nullable String def) { @Nullable public String getValueAsString(@Nonnull List keychain, @Nullable String def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsString(def); } @@ -94,7 +94,7 @@ public int getValueAsInteger(int def) { } public int getValueAsInteger(@Nonnull List keychain, int def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsInteger(def); } @@ -119,7 +119,7 @@ public long getValueAsLong(long def) { } public long getValueAsLong(@Nonnull List keychain, long def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsLong(def); } @@ -144,7 +144,7 @@ public float getValueAsFloat(float def) { } public float getValueAsFloat(@Nonnull List keychain, float def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsFloat(def); } @@ -169,7 +169,7 @@ public double getValueAsDouble(double def) { } public double getValueAsDouble(@Nonnull List keychain, double def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsDouble(def); } @@ -194,7 +194,7 @@ public boolean getValueAsBoolean(boolean def) { } public boolean getValueAsBoolean(@Nonnull List keychain, boolean def) { - KeelConfigElement extracted = this.extractConfigElement(keychain); + KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; return extracted.getValueAsBoolean(def); } @@ -249,7 +249,7 @@ public JsonObject toJsonObject() { return x; } - public @Nullable KeelConfigElement extractConfigElement(@Nonnull List split) { + public @Nullable KeelConfigElement extract(@Nonnull List split) { if (split.isEmpty()) return null; if (split.size() == 1) return this.children.get(split.get(0)); KeelConfigElement keelConfigElement = this.children.get(split.get(0)); @@ -265,9 +265,9 @@ public JsonObject toJsonObject() { return keelConfigElement; } - public @Nullable KeelConfigElement extractConfigElement(@Nonnull String... split) { + public @Nullable KeelConfigElement extract(@Nonnull String... split) { List list = Arrays.asList(split); - return this.extractConfigElement(list); + return this.extract(list); } public KeelConfigElement loadProperties(@Nonnull Properties properties) { diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java index f9d0238..568159e 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java @@ -35,7 +35,7 @@ public KeelMySQLConfiguration(@Nonnull KeelConfigElement base) { @Nonnull public static KeelMySQLConfiguration loadConfigurationForDataSource(@Nonnull KeelConfigElement configCenter, @Nonnull String dataSourceName) { - KeelConfigElement keelConfigElement = configCenter.extractConfigElement("mysql", dataSourceName); + KeelConfigElement keelConfigElement = configCenter.extract("mysql", dataSourceName); return new KeelMySQLConfiguration(Objects.requireNonNull(keelConfigElement)); } @@ -146,7 +146,7 @@ private Integer getConnectionTimeout() { * @see ... */ public Integer getPoolConnectionTimeout() { - KeelConfigElement keelConfigElement = extractConfigElement("poolConnectionTimeout"); + KeelConfigElement keelConfigElement = extract("poolConnectionTimeout"); if (keelConfigElement == null) { return null; } diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java index 2ee49f8..8f3f732 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java @@ -24,7 +24,7 @@ public static NamedMySQLDataSource initializ @Nonnull String dataSourceName, Function sqlConnectionWrapper ) { - var configuration = Keel.getConfiguration().extractConfigElement("mysql", dataSourceName); + var configuration = Keel.getConfiguration().extract("mysql", dataSourceName); Objects.requireNonNull(configuration); KeelMySQLConfiguration mySQLConfigure = new KeelMySQLConfiguration(configuration); return new NamedMySQLDataSource<>(mySQLConfigure, sqlConnectionWrapper); From d930c7979d0b2b7fe0dabd5a9c12a90cf3ea0f84 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Mon, 1 Apr 2024 10:16:13 +0800 Subject: [PATCH 04/13] 3.2.3-SNAPSHOT Pagination Signed-off-by: Sinri Edogawa --- .../sinri/keel/facade/KeelConfiguration.java | 178 ------------------ .../keel/facade/async/FutureForEach.java | 2 +- .../sinri/keel/facade/async/FutureSleep.java | 4 - .../mysql/statement/AbstractStatement.java | 3 - .../keel/mysql/statement/AnyStatement.java | 4 +- .../statement/CatholicQueryCriteria.java | 98 ---------- .../mysql/statement/ConditionsComponent.java | 53 +----- .../keel/mysql/statement/SelectStatement.java | 160 +++++++++++++--- .../mysql/statement/WriteIntoStatement.java | 10 +- 9 files changed, 144 insertions(+), 368 deletions(-) delete mode 100644 src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java delete mode 100644 src/main/java/io/github/sinri/keel/mysql/statement/CatholicQueryCriteria.java diff --git a/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java b/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java deleted file mode 100644 index c020160..0000000 --- a/src/main/java/io/github/sinri/keel/facade/KeelConfiguration.java +++ /dev/null @@ -1,178 +0,0 @@ -package io.github.sinri.keel.facade; - -import io.github.sinri.keel.core.json.JsonifiableEntity; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.json.JsonObject; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.FileReader; -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.*; - -import static io.github.sinri.keel.facade.KeelInstance.Keel; -import static io.github.sinri.keel.helper.KeelHelpersInterface.KeelHelpers; - -/** - * @since 3.0.0 - */ -@Deprecated(since = "3.2.3", forRemoval = true) -public class KeelConfiguration implements JsonifiableEntity { - - private @Nonnull JsonObject data = new JsonObject(); - - public KeelConfiguration() { - } - - /** - * @param another - * @since 3.0.7 - */ - public KeelConfiguration(@Nonnull KeelConfiguration another) { - this(another.toJsonObject()); - } - - public KeelConfiguration(@Nonnull JsonObject jsonObject) { - this.data = jsonObject; - } - - public KeelConfiguration(@Nonnull Properties properties) { - this.data = KeelConfiguration.transformPropertiesToJsonObject(properties); - } - - static @Nonnull JsonObject transformPropertiesToJsonObject(@Nonnull Properties properties) { - JsonObject jsonObject = new JsonObject(); - - Set plainKeySet = new HashSet<>(); - properties.forEach((key, value) -> plainKeySet.add(key.toString())); - - for (var plainKey : plainKeySet) { - String[] components = plainKey.split("\\."); - List keychain = Arrays.asList(components); - try { - KeelHelpers.jsonHelper().writeIntoJsonObject(jsonObject, keychain, properties.getProperty(plainKey)); - } catch (Throwable throwable) { - Keel.getLogger().exception(throwable, "io.github.sinri.keel.facade.KeelConfiguration.transformPropertiesToJsonObject Format Failed" + properties); - } - } - return jsonObject; - } - - static @Nonnull KeelConfiguration createFromPropertiesFile(@Nonnull String propertiesFileName) { - KeelConfiguration p = new KeelConfiguration(); - p.loadPropertiesFile(propertiesFileName); - return p; - } - - static @Nonnull KeelConfiguration createFromProperties(@Nonnull Properties properties) { - KeelConfiguration p = new KeelConfiguration(); - p.putAll(properties); - return p; - } - - static @Nonnull KeelConfiguration createFromJsonObject(@Nonnull JsonObject jsonObject) { - KeelConfiguration p = new KeelConfiguration(); - p.putAll(jsonObject); - return p; - } - - public @Nonnull KeelConfiguration putAll(@Nonnull KeelConfiguration keelConfiguration) { - return putAll(keelConfiguration.toJsonObject()); - } - - public @Nonnull KeelConfiguration putAll(@Nonnull Properties properties) { - return putAll(KeelConfiguration.transformPropertiesToJsonObject(properties)); - } - - public @Nonnull KeelConfiguration putAll(@Nonnull JsonObject jsonObject) { - data.mergeIn(jsonObject); - return this; - } - - /** - * @since 3.0.10 - */ - public @Nonnull KeelConfiguration loadJsonObjectFile(@Nonnull String jsonObjectFileName) { - try { - byte[] bytes = KeelHelpers.fileHelper().readFileAsByteArray(jsonObjectFileName, true); - this.data = new JsonObject(Buffer.buffer(bytes)); - return this; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * @since 3.0.1 - */ - public @Nonnull KeelConfiguration loadPropertiesFile(@Nonnull String propertiesFileName) { - return loadPropertiesFile(propertiesFileName, StandardCharsets.UTF_8); - } - - public @Nonnull KeelConfiguration loadPropertiesFile(@Nonnull String propertiesFileName, @Nonnull Charset charset) { - Properties properties = new Properties(); - try { - // here, the file named as `propertiesFileName` should be put along with JAR - properties.load(new FileReader(propertiesFileName, charset)); - } catch (IOException e) { - System.err.println("Cannot find the file config.properties. Use the embedded one."); - try { - properties.load(KeelConfiguration.class.getClassLoader().getResourceAsStream(propertiesFileName)); - } catch (IOException ex) { - throw new RuntimeException("Cannot find the embedded file config.properties.", ex); - } - } - - return putAll(properties); - } - - /** - * @since 3.0.6 - */ - public @Nonnull KeelConfiguration loadPropertiesFileContent(@Nonnull String content) { - Properties properties = new Properties(); - try { - properties.load(new StringReader(content)); - } catch (IOException e) { - throw new RuntimeException("Cannot load given properties content.", e); - } - return putAll(properties); - } - - public @Nonnull KeelConfiguration extract(String... keychain) { - JsonObject jsonObject = Objects.requireNonNullElse(readJsonObject(keychain), new JsonObject()); - return new KeelConfiguration(jsonObject); - } - - public @Nullable Long readAsLong(String... keychain) { - String s = readString(keychain); - return s == null ? null : Long.valueOf(s); - } - - public @Nullable Integer readAsInteger(String... keychain) { - String s = readString(keychain); - return s == null ? null : Integer.valueOf(s); - } - - /** - * Parse TRUE/FALSE to boolean ignoring case. - */ - public @Nullable Boolean readAsBoolean(String... keychain) { - String s = readString(keychain); - return s == null ? null : Boolean.valueOf(s); - } - - @Override - public @Nonnull JsonObject toJsonObject() { - return this.data; - } - - @Override - public @Nonnull KeelConfiguration reloadDataFromJsonObject(@Nonnull JsonObject data) { - this.data = data; - return this; - } -} diff --git a/src/main/java/io/github/sinri/keel/facade/async/FutureForEach.java b/src/main/java/io/github/sinri/keel/facade/async/FutureForEach.java index 5fd37f5..1f22b95 100644 --- a/src/main/java/io/github/sinri/keel/facade/async/FutureForEach.java +++ b/src/main/java/io/github/sinri/keel/facade/async/FutureForEach.java @@ -20,7 +20,7 @@ private FutureForEach(@Nonnull Function> itemProcessor) { } static Future call(@Nonnull Iterable collection, @Nonnull Function> itemProcessor) { - return new FutureForEach(itemProcessor).process(collection); + return new FutureForEach<>(itemProcessor).process(collection); } private Future process(@Nonnull Iterable collection) { diff --git a/src/main/java/io/github/sinri/keel/facade/async/FutureSleep.java b/src/main/java/io/github/sinri/keel/facade/async/FutureSleep.java index 2aba6d3..8215711 100644 --- a/src/main/java/io/github/sinri/keel/facade/async/FutureSleep.java +++ b/src/main/java/io/github/sinri/keel/facade/async/FutureSleep.java @@ -15,10 +15,6 @@ */ public class FutureSleep { static Future call(long time) { -// Promise promise = Promise.promise(); -// if (time < 1) time = 1; -// Keel.getVertx().setTimer(time, x -> promise.complete()); -// return promise.future(); return call(time, null); } diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/AbstractStatement.java b/src/main/java/io/github/sinri/keel/mysql/statement/AbstractStatement.java index 799addc..cdae2e3 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/AbstractStatement.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/AbstractStatement.java @@ -48,9 +48,6 @@ protected String getRemarkAsComment() { } public AbstractStatement setRemarkAsComment(@Nonnull String remarkAsComment) { -// if (remarkAsComment == null) { -// remarkAsComment = ""; -// } remarkAsComment = remarkAsComment.replaceAll("[\\r\\n]+", "¦"); this.remarkAsComment = remarkAsComment; return this; diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/AnyStatement.java b/src/main/java/io/github/sinri/keel/mysql/statement/AnyStatement.java index f9f99b2..ae736a1 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/AnyStatement.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/AnyStatement.java @@ -66,14 +66,14 @@ static WriteIntoStatement replace(@Nonnull Handler statement return writeIntoStatement; } - static TemplatedReadStatement templatedRead(@Nonnull String path,@Nonnull Handler templatedReadStatementHandler) { + static TemplatedReadStatement templatedRead(@Nonnull String path, @Nonnull Handler templatedReadStatementHandler) { TemplatedReadStatement readStatement = TemplatedStatement.loadTemplateToRead(path); TemplateArgumentMapping arguments = readStatement.getArguments(); templatedReadStatementHandler.handle(arguments); return readStatement; } - static TemplatedModifyStatement templatedModify(@Nonnull String path,@Nonnull Handler templatedModifyStatementHandler) { + static TemplatedModifyStatement templatedModify(@Nonnull String path, @Nonnull Handler templatedModifyStatementHandler) { TemplatedModifyStatement templatedModifyStatement = TemplatedStatement.loadTemplateToModify(path); TemplateArgumentMapping arguments = templatedModifyStatement.getArguments(); templatedModifyStatementHandler.handle(arguments); diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/CatholicQueryCriteria.java b/src/main/java/io/github/sinri/keel/mysql/statement/CatholicQueryCriteria.java deleted file mode 100644 index 32561d3..0000000 --- a/src/main/java/io/github/sinri/keel/mysql/statement/CatholicQueryCriteria.java +++ /dev/null @@ -1,98 +0,0 @@ -package io.github.sinri.keel.mysql.statement; - -import io.github.sinri.keel.mysql.condition.CompareCondition; -import io.vertx.core.json.JsonArray; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * @since 1.13 - */ -@Deprecated(since = "3.1.8", forRemoval = true) -public class CatholicQueryCriteria { - protected final Map inclusiveCriteria = new HashMap<>(); - protected final Map exclusiveCriteria = new HashMap<>(); - - public CatholicQueryCriteria include(@Nonnull String name, @Nullable T value) { - if (value == null) return this; - inclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - inclusiveCriteria.get(name).add(value); - return this; - } - - public CatholicQueryCriteria include(@Nonnull String name, @Nullable Collection values) { - if (values == null) return this; - inclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - JsonArray jsonArray = new JsonArray(); - values.forEach(jsonArray::add); - inclusiveCriteria.get(name).addAll(jsonArray); - return this; - } - - public CatholicQueryCriteria include(@Nonnull String name, @Nullable JsonArray values) { - if (values == null) return this; - inclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - inclusiveCriteria.get(name).addAll(values); - return this; - } - - public CatholicQueryCriteria exclude(@Nonnull String name, @Nullable T value) { - if (value == null) return this; - exclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - exclusiveCriteria.get(name).add(value); - return this; - } - - public CatholicQueryCriteria exclude(@Nonnull String name, @Nullable Collection values) { - if (values == null) return this; - exclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - JsonArray jsonArray = new JsonArray(); - values.forEach(jsonArray::add); - exclusiveCriteria.get(name).addAll(jsonArray); - return this; - } - - public CatholicQueryCriteria exclude(@Nonnull String name, @Nullable JsonArray values) { - if (values == null) return this; - exclusiveCriteria.computeIfAbsent(name, x -> new JsonArray()); - exclusiveCriteria.get(name).addAll(values); - return this; - } - - public final ConditionsComponent mergeIntoConditionsComponent(@Nonnull ConditionsComponent conditionsComponent) { - inclusiveCriteria.forEach((name, objects) -> { - if (objects.isEmpty()) return; - if (objects.size() == 1) { - conditionsComponent.comparison(compareCondition -> compareCondition - .filedEqualsValue(name, objects.getValue(0)) - ); - } else { - conditionsComponent.among(amongstCondition -> amongstCondition - .elementAsExpression(name) - .amongstValueList(objects.getList()) - ); - } - }); - exclusiveCriteria.forEach((name, objects) -> { - if (objects.isEmpty()) return; - if (objects.size() == 1) { - conditionsComponent.comparison(compareCondition -> compareCondition - .compare(name) - .operator(CompareCondition.OP_NEQ) - .againstValue(objects.getValue(0)) - ); - } else { - conditionsComponent.among(amongstCondition -> amongstCondition - .elementAsExpression(name) - .not() - .amongstValueList(objects.getList()) - ); - } - }); - return conditionsComponent; - } -} diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java b/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java index d1713ee..ab7905e 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java @@ -1,8 +1,6 @@ package io.github.sinri.keel.mysql.statement; import io.github.sinri.keel.mysql.condition.*; -import io.vertx.core.json.JsonArray; -import io.vertx.core.json.JsonObject; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -22,6 +20,10 @@ public ConditionsComponent() { conditions = new ArrayList<>(); } + public ConditionsComponent(@Nonnull ConditionsComponent another) { + this.conditions = another.conditions; + } + public boolean isEmpty() { return this.conditions.isEmpty(); } @@ -199,56 +201,9 @@ public ConditionsComponent raw(@Nonnull String raw) { return this; } - /** - * @param catholicQueryCriteria CatholicQueryCriteria Instance - * @return this - * @since 1.13 - */ - @Deprecated(since = "3.1.8", forRemoval = true) - public ConditionsComponent withCatholicQueryCriteria(@Nonnull CatholicQueryCriteria catholicQueryCriteria) { - return catholicQueryCriteria.mergeIntoConditionsComponent(this); - } - @Override public String toString() { if (conditions.isEmpty()) return ""; return KeelHelpers.stringHelper().joinStringArray(conditions, " and "); } - - /** - * @since 2.0 - */ - @Deprecated(since = "3.1.0", forRemoval = true) - public final ConditionsComponent quickMapping(JsonObject mapping) { - mapping.forEach(entry -> quickMapping(entry.getKey(), entry.getValue())); - return this; - } - - /** - * @since 2.0 - */ - @Deprecated(since = "3.1.0", forRemoval = true) - public final ConditionsComponent quickMapping(String key, Object value) { - if (key != null && !key.isEmpty()) { - if (value == null) { - this.comparison(compareCondition -> compareCondition - .compare(key) - .operator(CompareCondition.OP_IS) - .againstExpression("NULL") - ); - } else if (value instanceof JsonArray) { - if (((JsonArray) value).size() > 0) { - this.among(amongstCondition -> amongstCondition - .elementAsExpression(key) - .amongstValueList(((JsonArray) value).getList()) - ); - } - } else { - this.comparison(compareCondition -> compareCondition - .filedEqualsValue(key, value.toString()) - ); - } - } - return this; - } } diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java b/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java index 8f4a4ab..74f5654 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java @@ -1,10 +1,15 @@ package io.github.sinri.keel.mysql.statement; +import io.github.sinri.keel.mysql.NamedMySQLConnection; import io.github.sinri.keel.mysql.condition.CompareCondition; import io.github.sinri.keel.mysql.condition.GroupCondition; import io.github.sinri.keel.mysql.condition.MySQLCondition; import io.github.sinri.keel.mysql.condition.RawCondition; import io.github.sinri.keel.mysql.exception.KeelSQLGenerateError; +import io.github.sinri.keel.mysql.exception.KeelSQLResultRowIndexError; +import io.github.sinri.keel.mysql.matrix.ResultMatrix; +import io.vertx.core.Future; +import io.vertx.sqlclient.SqlConnection; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -16,23 +21,51 @@ import static io.github.sinri.keel.helper.KeelHelpersInterface.KeelHelpers; public class SelectStatement extends AbstractReadStatement { - // private final List whereConditions = new ArrayList<>(); - final ConditionsComponent whereConditionsComponent = new ConditionsComponent(); - // private final List havingConditions = new ArrayList<>(); - final ConditionsComponent havingConditionsComponent = new ConditionsComponent(); - private final List tables = new ArrayList<>(); - private final List columns = new ArrayList<>(); - private final List categories = new ArrayList<>(); - private final List sortRules = new ArrayList<>(); - private long offset = 0; - private long limit = 0; - private @Nonnull String lockMode = ""; + final ConditionsComponent whereConditionsComponent; + final ConditionsComponent havingConditionsComponent; + private final List tables; + private final List columns; + private final List categories; + private final List sortRules; + private long offset; + private long limit; + private @Nonnull String lockMode; /** * For MySQL 5.7 ,8.0 or higher, in Select, to limit the max execution time in millisecond. * * @since 3.1.0 */ - private @Nullable Long maxExecutionTime = null; + private @Nullable Long maxExecutionTime; + + /** + * @param another To swift clone one instance based on without direct reference. + * @since 3.2.3 + */ + public SelectStatement(@Nonnull SelectStatement another) { + this.whereConditionsComponent = new ConditionsComponent(another.whereConditionsComponent); + this.havingConditionsComponent = new ConditionsComponent(another.havingConditionsComponent); + this.tables = new ArrayList<>(another.tables); + this.columns = new ArrayList<>(another.columns); + this.categories = new ArrayList<>(another.categories); + this.sortRules = new ArrayList<>(another.sortRules); + this.offset = another.offset; + this.limit = another.limit; + this.lockMode = another.lockMode; + this.maxExecutionTime = another.maxExecutionTime; + } + + public SelectStatement() { + this.whereConditionsComponent = new ConditionsComponent(); + this.havingConditionsComponent = new ConditionsComponent(); + this.tables = new ArrayList<>(); + this.columns = new ArrayList<>(); + this.categories = new ArrayList<>(); + this.sortRules = new ArrayList<>(); + this.offset = 0; + this.limit = 0; + this.lockMode = ""; + this.maxExecutionTime = null; + } public SelectStatement from(@Nonnull String tableExpression) { return from(tableExpression, null); @@ -57,11 +90,11 @@ public SelectStatement from(@Nonnull String tableExpression, @Nullable String al /** * @since 2.8 */ - public SelectStatement from(@Nonnull AbstractReadStatement subQuery,@Nonnull String alias) { + public SelectStatement from(@Nonnull AbstractReadStatement subQuery, @Nonnull String alias) { if (alias.isBlank()) { throw new KeelSQLGenerateError("Sub Query without alias"); } - return this.from("(" + subQuery.toString() + ")", alias); + return this.from("(" + subQuery + ")", alias); } public SelectStatement leftJoin(@Nonnull Function joinFunction) { @@ -88,13 +121,18 @@ public SelectStatement straightJoin(@Nonnull Function func) { columns.add(func.apply(new ColumnComponent()).toString()); return this; } public SelectStatement columnWithAlias(@Nonnull String columnExpression, @Nonnull String alias) { - if(columnExpression.isBlank() || alias.isBlank()){ + if (columnExpression.isBlank() || alias.isBlank()) { throw new IllegalArgumentException("Column or its alias is empty."); } columns.add(columnExpression + " as `" + alias + "`"); @@ -204,7 +242,7 @@ public String toString() { if (limit > 0) { sql.append(AbstractStatement.SQL_COMPONENT_SEPARATOR).append("LIMIT ").append(limit).append(" OFFSET ").append(offset); } - if (!"".equals(lockMode)) { + if (!lockMode.isEmpty()) { sql.append(AbstractStatement.SQL_COMPONENT_SEPARATOR).append(lockMode); } if (!getRemarkAsComment().isEmpty()) { @@ -213,11 +251,63 @@ public String toString() { return String.valueOf(sql); } + /** + * @since 3.2.3 + */ + Future queryForPagination( + NamedMySQLConnection sqlConnection, + long pageNo, + long pageSize + ) { + return this.queryForPagination(sqlConnection.getSqlConnection(), pageNo, pageSize); + } + + /** + * Call from this instance, as the original query as Select Statement for all rows in certain order. + * + * @param pageNo since 1. + * @param pageSize a number + * @since 3.2.3 + */ + Future queryForPagination( + SqlConnection sqlConnection, + long pageNo, + long pageSize + ) { + if (pageSize <= 0) throw new IllegalArgumentException("page size <= 0"); + if (pageNo < 1) throw new IllegalArgumentException("page no < 1"); + var countStatement = new SelectStatement(this) + .resetColumns() + .columnWithAlias("count(*)", "total") + .limit(pageSize, (pageNo - 1) * pageSize); + + return Future.all( + countStatement.execute(sqlConnection) + .compose(resultMatrix -> { + try { + long total = resultMatrix.getOneColumnOfFirstRowAsLong("total"); + return Future.succeededFuture(total); + } catch (KeelSQLResultRowIndexError e) { + throw new RuntimeException(e); + } + }), + this.execute(sqlConnection) + ) + .compose(compositeFuture -> { + Long total = compositeFuture.resultAt(0); + ResultMatrix resultMatrix = compositeFuture.resultAt(1); + return Future.succeededFuture(new PaginationResult(total, resultMatrix)); + }); + } + public static class JoinComponent { - @Nonnull final String joinType; + @Nonnull + final String joinType; final List onConditions = new ArrayList<>(); - @Nonnull String tableExpression="NOT-SET"; - @Nullable String alias; + @Nonnull + String tableExpression = "NOT-SET"; + @Nullable + String alias; public JoinComponent(@Nonnull String joinType) { this.joinType = joinType; @@ -267,17 +357,21 @@ public String toString() { } public static class ColumnComponent { - @Nullable String schema; - @Nullable String field="NOT-SET"; - @Nullable String expression; - @Nullable String alias; + @Nullable + String schema; + @Nullable + String field = "NOT-SET"; + @Nullable + String expression; + @Nullable + String alias; public ColumnComponent field(@Nonnull String field) { this.field = field; return this; } - public ColumnComponent field(@Nullable String schema,@Nonnull String field) { + public ColumnComponent field(@Nullable String schema, @Nonnull String field) { this.schema = schema; this.field = field; return this; @@ -311,4 +405,22 @@ public String toString() { return String.valueOf(column); } } + + public static class PaginationResult { + private final long total; + private final ResultMatrix resultMatrix; + + public PaginationResult(long total, ResultMatrix resultMatrix) { + this.total = total; + this.resultMatrix = resultMatrix; + } + + public long getTotal() { + return total; + } + + public ResultMatrix getResultMatrix() { + return resultMatrix; + } + } } diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/WriteIntoStatement.java b/src/main/java/io/github/sinri/keel/mysql/statement/WriteIntoStatement.java index a6c08d7..12a9673 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/WriteIntoStatement.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/WriteIntoStatement.java @@ -74,15 +74,7 @@ public WriteIntoStatement columns(@Nonnull List columns) { public WriteIntoStatement addDataMatrix(@Nonnull List> batch) { for (List row : batch) { - List t = new ArrayList<>(); - for (Object item : row) { - if (item == null) { - t.add("NULL"); - } else { - t.add(new Quoter(String.valueOf(item)).toString()); - } - } - this.batchValues.add(t); + this.addDataRow(row); } return this; } From 85cb0bb96cdcd35be87158ccbc6e6a07dabb3e7b Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Tue, 2 Apr 2024 11:45:54 +0800 Subject: [PATCH 05/13] 3.2.3-SNAPSHOT configuration refine Signed-off-by: Sinri Edogawa --- .../elasticsearch/ElasticSearchConfig.java | 12 +- .../sinri/keel/email/smtp/KeelSmtpKit.java | 10 +- .../configuration/KeelConfigElement.java | 140 ++++++++++++++---- .../keel/mysql/KeelMySQLConfiguration.java | 18 +-- .../mysql/KeelMySQLDataSourceProvider.java | 2 +- .../keel/mysql/statement/SelectStatement.java | 3 +- .../io/github/sinri/keel/redis/RedisKit.java | 2 +- 7 files changed, 133 insertions(+), 54 deletions(-) diff --git a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java index 696559f..b9b5a9c 100644 --- a/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java +++ b/src/main/java/io/github/sinri/keel/elasticsearch/ElasticSearchConfig.java @@ -35,23 +35,23 @@ public ElasticSearchConfig(String esKey) { */ public String username() { - return getValueAsString("username", null); + return readString("username", null); } public String password() { - return getValueAsString("password", null); + return readString("password", null); } public @Nonnull String clusterHost() { - return Objects.requireNonNull(getValueAsString(List.of("cluster", "host"), null)); + return Objects.requireNonNull(readString(List.of("cluster", "host"), null)); } public int clusterPort() { - return getValueAsInteger(List.of("cluster", "port"), 9200); + return readInteger(List.of("cluster", "port"), 9200); } public @Nonnull String clusterScheme() { - return Objects.requireNonNull(getValueAsString(List.of("cluster", "scheme"), "http")); + return Objects.requireNonNull(readString(List.of("cluster", "scheme"), "http")); } public @Nonnull String clusterApiUrl(@Nonnull String endpoint) { @@ -59,6 +59,6 @@ public int clusterPort() { } public @Nullable String opaqueId() { - return getValueAsString("opaqueId", null); + return readString("opaqueId", null); } } diff --git a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java index 7ca75fa..0ff98f0 100644 --- a/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java +++ b/src/main/java/io/github/sinri/keel/email/smtp/KeelSmtpKit.java @@ -58,11 +58,11 @@ private static MailConfig buildMailConfig(@Nonnull String smtpName) { Objects.requireNonNull(smtpConfiguration); var mailConfig = new MailConfig(); - mailConfig.setHostname(smtpConfiguration.getValueAsString("hostname", null)); - mailConfig.setPort(smtpConfiguration.getValueAsInteger("port", 25)); - mailConfig.setUsername(smtpConfiguration.getValueAsString("username", null)); - mailConfig.setPassword(smtpConfiguration.getValueAsString("password", null)); - mailConfig.setSsl(smtpConfiguration.getValueAsBoolean("ssl", false)); + mailConfig.setHostname(smtpConfiguration.readString("hostname", null)); + mailConfig.setPort(smtpConfiguration.readInteger("port", 25)); + mailConfig.setUsername(smtpConfiguration.readString("username", null)); + mailConfig.setPassword(smtpConfiguration.readString("password", null)); + mailConfig.setSsl(smtpConfiguration.readBoolean("ssl", false)); return mailConfig; } diff --git a/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java index 2706145..3e456b9 100644 --- a/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java +++ b/src/main/java/io/github/sinri/keel/facade/configuration/KeelConfigElement.java @@ -62,20 +62,32 @@ public String getValueAsString() { } @Nullable - public String getValueAsString(@Nullable String def) { + public String getValueAsStringElse(@Nullable String def) { return Objects.requireNonNullElse(value, def); } @Nullable - public String getValueAsString(@Nonnull List keychain, @Nullable String def) { + public String readString() { + return readString(List.of()); + } + + @Nullable + public String readString(@Nonnull List keychain) { + var x = extract(keychain); + if (x == null) return null; + return x.getValueAsString(); + } + + @Nullable + public String readString(@Nonnull List keychain, @Nullable String def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsString(def); + return extracted.getValueAsStringElse(def); } @Nullable - public String getValueAsString(@Nonnull String keychain, @Nullable String def) { - return getValueAsString(List.of(keychain), def); + public String readString(@Nonnull String keychain, @Nullable String def) { + return readString(List.of(keychain), def); } @Nullable @@ -84,7 +96,7 @@ public Integer getValueAsInteger() { return Integer.parseInt(value); } - public int getValueAsInteger(int def) { + public int getValueAsIntegerElse(int def) { if (value == null) return def; try { return Integer.parseInt(value); @@ -93,14 +105,26 @@ public int getValueAsInteger(int def) { } } - public int getValueAsInteger(@Nonnull List keychain, int def) { + @Nullable + public Integer readInteger() { + return readInteger(List.of()); + } + + @Nullable + public Integer readInteger(@Nonnull List keychain) { + var x = this.extract(keychain); + if (x == null) return null; + return x.getValueAsInteger(); + } + + public int readInteger(@Nonnull List keychain, int def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsInteger(def); + return extracted.getValueAsIntegerElse(def); } - public int getValueAsInteger(@Nonnull String keychain, int def) { - return getValueAsInteger(List.of(keychain), def); + public int readInteger(@Nonnull String keychain, int def) { + return readInteger(List.of(keychain), def); } @Nullable @@ -109,7 +133,7 @@ public Long getValueAsLong() { return Long.parseLong(value); } - public long getValueAsLong(long def) { + public long getValueAsLongElse(long def) { if (value == null) return def; try { return Long.parseLong(value); @@ -118,14 +142,29 @@ public long getValueAsLong(long def) { } } - public long getValueAsLong(@Nonnull List keychain, long def) { + @Nullable + public Long readLong() { + return readLong(List.of()); + } + + @Nullable + public Long readLong(@Nonnull List keychain) { + KeelConfigElement extracted = this.extract(keychain); + if (extracted != null) { + return extracted.getValueAsLong(); + } else { + return null; + } + } + + public long readLong(@Nonnull List keychain, long def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsLong(def); + return extracted.getValueAsLongElse(def); } - public long getValueAsLong(@Nonnull String keychain, long def) { - return getValueAsLong(List.of(keychain), def); + public long readLong(@Nonnull String keychain, long def) { + return readLong(List.of(keychain), def); } @Nullable @@ -134,7 +173,7 @@ public Float getValueAsFloat() { return Float.parseFloat(value); } - public float getValueAsFloat(float def) { + public float getValueAsFloatElse(float def) { if (value == null) return def; try { return Float.parseFloat(value); @@ -143,14 +182,26 @@ public float getValueAsFloat(float def) { } } - public float getValueAsFloat(@Nonnull List keychain, float def) { + @Nullable + public Float readFloat() { + return readFloat(List.of()); + } + + @Nullable + public Float readFloat(@Nonnull List keychain) { + var x = extract(keychain); + if (x == null) return null; + return x.getValueAsFloat(); + } + + public float readFloat(@Nonnull List keychain, float def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsFloat(def); + return extracted.getValueAsFloatElse(def); } - public float getValueAsFloat(@Nonnull String keychain, float def) { - return getValueAsFloat(List.of(keychain), def); + public float readFloat(@Nonnull String keychain, float def) { + return readFloat(List.of(keychain), def); } @Nullable @@ -159,7 +210,7 @@ public Double getValueAsDouble() { return Double.parseDouble(value); } - public double getValueAsDouble(double def) { + public double getValueAsDoubleElse(double def) { if (value == null) return def; try { return Double.parseDouble(value); @@ -168,14 +219,26 @@ public double getValueAsDouble(double def) { } } - public double getValueAsDouble(@Nonnull List keychain, double def) { + @Nullable + public Double readDouble() { + return readDouble(List.of()); + } + + @Nullable + public Double readDouble(@Nonnull List keychain) { + var x = extract(keychain); + if (x == null) return null; + return x.getValueAsDouble(); + } + + public double readDouble(@Nonnull List keychain, double def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsDouble(def); + return extracted.getValueAsDoubleElse(def); } - public double getValueAsDouble(@Nonnull String keychain, double def) { - return getValueAsDouble(List.of(keychain), def); + public double readDouble(@Nonnull String keychain, double def) { + return readDouble(List.of(keychain), def); } @Nullable @@ -184,7 +247,7 @@ public Boolean getValueAsBoolean() { return "YES".equalsIgnoreCase(value) || "TRUE".equalsIgnoreCase(value); } - public boolean getValueAsBoolean(boolean def) { + public boolean getValueAsBooleanElse(boolean def) { if (value == null) return def; return "YES".equalsIgnoreCase(value) || "TRUE".equalsIgnoreCase(value) @@ -193,14 +256,26 @@ public boolean getValueAsBoolean(boolean def) { ; } - public boolean getValueAsBoolean(@Nonnull List keychain, boolean def) { + @Nullable + public Boolean readBoolean() { + return readBoolean(List.of()); + } + + @Nullable + public Boolean readBoolean(@Nonnull List keychain) { + var x = extract(keychain); + if (x == null) return null; + return x.getValueAsBoolean(); + } + + public boolean readBoolean(@Nonnull List keychain, boolean def) { KeelConfigElement extracted = this.extract(keychain); if (extracted == null) return def; - return extracted.getValueAsBoolean(def); + return extracted.getValueAsBooleanElse(def); } - public boolean getValueAsBoolean(@Nonnull String keychain, boolean def) { - return getValueAsBoolean(List.of(keychain), def); + public boolean readBoolean(@Nonnull String keychain, boolean def) { + return readBoolean(List.of(keychain), def); } public KeelConfigElement ensureChild(@Nonnull String childName) { @@ -249,8 +324,11 @@ public JsonObject toJsonObject() { return x; } + /** + * @param split The list of keys. If empty, give this, or dig in. + */ public @Nullable KeelConfigElement extract(@Nonnull List split) { - if (split.isEmpty()) return null; + if (split.isEmpty()) return this; if (split.size() == 1) return this.children.get(split.get(0)); KeelConfigElement keelConfigElement = this.children.get(split.get(0)); if (keelConfigElement == null) { diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java index 568159e..a6a9d70 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLConfiguration.java @@ -82,35 +82,35 @@ public PoolOptions getPoolOptions() { } public String getHost() { - return getValueAsString(List.of("host"), null); + return readString(List.of("host"), null); } public Integer getPort() { - return getValueAsInteger(List.of("port"), 3306); + return readInteger(List.of("port"), 3306); } public String getPassword() { - return getValueAsString(List.of("password"), null); + return readString(List.of("password"), null); } public String getUsername() { - var u = getValueAsString("username", null); + var u = readString("username", null); if (u == null) { - u = getValueAsString("user", null); + u = readString("user", null); } return u; } public String getDatabase() { - String schema = getValueAsString("schema", null); + String schema = readString("schema", null); if (schema == null) { - schema = getValueAsString("database", null); + schema = readString("database", null); } return Objects.requireNonNullElse(schema, ""); } public String getCharset() { - return getValueAsString("charset", null); + return readString("charset", null); } public Integer getPoolMaxSize() { @@ -160,7 +160,7 @@ public Integer getPoolConnectionTimeout() { * that created it is undeployed. */ public boolean getPoolShared() { - return getValueAsBoolean("poolShared", true); + return readBoolean("poolShared", true); } diff --git a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java index 8f3f732..c4805ae 100644 --- a/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java +++ b/src/main/java/io/github/sinri/keel/mysql/KeelMySQLDataSourceProvider.java @@ -13,7 +13,7 @@ public class KeelMySQLDataSourceProvider { @Nonnull public static String defaultMySQLDataSourceName() { - return Objects.requireNonNull(Keel.getConfiguration().getValueAsString(List.of("mysql", "default_data_source_name"), "default")); + return Objects.requireNonNull(Keel.getConfiguration().readString(List.of("mysql", "default_data_source_name"), "default")); } /** diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java b/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java index 74f5654..394cf33 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/SelectStatement.java @@ -279,7 +279,8 @@ Future queryForPagination( var countStatement = new SelectStatement(this) .resetColumns() .columnWithAlias("count(*)", "total") - .limit(pageSize, (pageNo - 1) * pageSize); + .limit(0, 0); + this.limit(pageSize, (pageNo - 1) * pageSize); return Future.all( countStatement.execute(sqlConnection) diff --git a/src/main/java/io/github/sinri/keel/redis/RedisKit.java b/src/main/java/io/github/sinri/keel/redis/RedisKit.java index 0272dca..d6d9547 100644 --- a/src/main/java/io/github/sinri/keel/redis/RedisKit.java +++ b/src/main/java/io/github/sinri/keel/redis/RedisKit.java @@ -24,7 +24,7 @@ public RedisKit(String redisInstanceKey) { /* * URL should be redis://[:password@]host[:port][/db-number] */ - String url = Keel.getConfiguration().getValueAsString(List.of("redis", redisInstanceKey, "url"), null); + String url = Keel.getConfiguration().readString(List.of("redis", redisInstanceKey, "url"), null); Objects.requireNonNull(url); this.client = Redis.createClient(Keel.getVertx(), new RedisOptions() .setConnectionString(url) From d0fba902321bff4e3079afd11abfeaf28255b424 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Tue, 2 Apr 2024 15:04:09 +0800 Subject: [PATCH 06/13] 3.2.3-SNAPSHOT ES API Response as Json Array... let it be wrapped in Json Object Signed-off-by: Sinri Edogawa --- .../sinri/keel/elasticsearch/ESApiMixin.java | 26 ++++++++++++-- .../lab/elasticsearch/ESCatIndicesTest.java | 36 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/java/io/github/sinri/keel/test/lab/elasticsearch/ESCatIndicesTest.java diff --git a/src/main/java/io/github/sinri/keel/elasticsearch/ESApiMixin.java b/src/main/java/io/github/sinri/keel/elasticsearch/ESApiMixin.java index addaa63..f15f153 100644 --- a/src/main/java/io/github/sinri/keel/elasticsearch/ESApiMixin.java +++ b/src/main/java/io/github/sinri/keel/elasticsearch/ESApiMixin.java @@ -3,6 +3,8 @@ import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.DecodeException; +import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.client.HttpRequest; import io.vertx.ext.web.client.WebClient; @@ -64,9 +66,7 @@ default Future call(@Nonnull HttpMethod httpMethod, @Nonnull String }) .compose(bufferHttpResponse -> { int statusCode = bufferHttpResponse.statusCode(); - JsonObject resp = bufferHttpResponse.bodyAsJsonObject(); - - if ((statusCode >= 300 || statusCode < 200) || resp == null) { + if ((statusCode >= 300 || statusCode < 200)) { // this.getLogger().error(log -> { // logRequestEnricher.handle(log); // log.message("ES API Response Error") @@ -86,6 +86,14 @@ default Future call(@Nonnull HttpMethod httpMethod, @Nonnull String requestBody )); } + JsonObject resp; + try { + resp = bufferHttpResponse.bodyAsJsonObject(); + } catch (DecodeException decodeException) { + // There are situations that use Json Array as the response body! + resp = new JsonObject() + .put("array", new JsonArray(bufferHttpResponse.bodyAsString())); + } // this.getLogger().info(log -> { // logRequestEnricher.handle(log); // log.message("ES API Response Error") @@ -208,6 +216,18 @@ public ESApiException( this.requestBody = requestBody; } + @Override + public String toString() { + return getClass().getName() + + "{status_code: " + statusCode + + ", response: " + response + + ", http_method: " + httpMethod.name() + + ", endpoint: " + endpoint + + ", queries: " + queries + + ", request_body: " + requestBody + + "}"; + } + public int getStatusCode() { return statusCode; } diff --git a/src/test/java/io/github/sinri/keel/test/lab/elasticsearch/ESCatIndicesTest.java b/src/test/java/io/github/sinri/keel/test/lab/elasticsearch/ESCatIndicesTest.java new file mode 100644 index 0000000..fa35dfb --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/elasticsearch/ESCatIndicesTest.java @@ -0,0 +1,36 @@ +package io.github.sinri.keel.test.lab.elasticsearch; + +import io.github.sinri.keel.elasticsearch.ElasticSearchKit; +import io.github.sinri.keel.tesuto.KeelTest; +import io.github.sinri.keel.tesuto.TestUnit; +import io.vertx.core.Future; +import io.vertx.core.http.HttpMethod; + +import javax.annotation.Nonnull; + +import static io.github.sinri.keel.facade.KeelInstance.Keel; + +public class ESCatIndicesTest extends KeelTest { + @Nonnull + @Override + protected Future starting() { + Keel.getConfiguration().loadPropertiesFile("config.properties"); + return super.starting(); + } + + @TestUnit + public Future test() { + // {"client_code":"ai-test","timestamp":1712023360984,"checksum":"d6abf7d98af34907d97f6a6578a429b5","http_method":"GET","endpoint":"/_cat/indices"} + return new ElasticSearchKit("kumori") + .call( + HttpMethod.GET, + "/_cat/indices", + null, + null + ) + .compose(resp -> { + getLogger().info("resp", resp); + return Future.succeededFuture(); + }); + } +} From 02e2d04e3f01454a1d4ce0c4c06b80dedd8c76ac Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Tue, 2 Apr 2024 17:20:10 +0800 Subject: [PATCH 07/13] 3.2.3 Signed-off-by: Sinri Edogawa --- pom.xml | 4 ++-- .../sinri/keel/mysql/statement/ConditionsComponent.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 4075c04..de99f05 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,8 @@ io.github.sinri Keel - 3.2.3-SNAPSHOT - + + 3.2.3 Keel diff --git a/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java b/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java index ab7905e..7d55e11 100644 --- a/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java +++ b/src/main/java/io/github/sinri/keel/mysql/statement/ConditionsComponent.java @@ -21,7 +21,7 @@ public ConditionsComponent() { } public ConditionsComponent(@Nonnull ConditionsComponent another) { - this.conditions = another.conditions; + this.conditions = new ArrayList<>(another.conditions); } public boolean isEmpty() { From f482735d45ec643630de5ca275b33d905f1e97d3 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Wed, 10 Apr 2024 11:36:11 +0800 Subject: [PATCH 08/13] 3.2.4-SNAPSHOT Signed-off-by: Sinri Edogawa --- pom.xml | 20 ++--- .../sinri/keel/core/KeelCronExpression.java | 57 +++++++++----- .../sinri/keel/facade/KeelInstance.java | 7 +- .../keel/servant/sundial/KeelSundial.java | 75 +++++++++++-------- .../keel/servant/sundial/KeelSundialPlan.java | 4 +- .../servant/sundial/KeelSundialVerticle.java | 31 ++++++++ 6 files changed, 132 insertions(+), 62 deletions(-) create mode 100644 src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialVerticle.java diff --git a/pom.xml b/pom.xml index de99f05..49214b9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,18 +4,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - UTF-8 - 4.5.4 - 0.21.0 - 2.15.3 - 5.2.5 - - io.github.sinri Keel - - 3.2.3 + 3.2.4-SNAPSHOT + Keel @@ -44,6 +36,14 @@ + + UTF-8 + 4.5.4 + 0.21.0 + 2.15.3 + 5.2.5 + + io.vertx diff --git a/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java b/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java index 4d9d86c..a866978 100644 --- a/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java +++ b/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java @@ -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; @@ -13,9 +15,9 @@ public class KeelCronExpression { final Set dayOptions = new HashSet<>(); final Set monthOptions = new HashSet<>(); final Set 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+"); @@ -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 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 optionSet, int min, int max) { if (rawComponent.equals("*")) { for (int i = min; i <= max; i++) { optionSet.add(i); @@ -106,10 +104,35 @@ private void parseField(String rawComponent, Set 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(); diff --git a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java index 6a51217..f89314b 100644 --- a/src/main/java/io/github/sinri/keel/facade/KeelInstance.java +++ b/src/main/java/io/github/sinri/keel/facade/KeelInstance.java @@ -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; @@ -130,7 +133,7 @@ public KeelInstance setLogger(@Nonnull KeelEventLogger eventLogger) { return this; } - public Future gracefullyClose(@Nonnull Handler> promiseHandler) { + public Future gracefullyClose(@Nonnull io.vertx.core.Handler> promiseHandler) { Promise promise = Promise.promise(); promiseHandler.handle(promise); return promise.future().compose(v -> getVertx().close()); diff --git a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java index d814e93..592fc65 100644 --- a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java +++ b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java @@ -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 planMap = new ConcurrentHashMap<>(); @@ -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 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> 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 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(); + }); + } + ); } /** diff --git a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialPlan.java b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialPlan.java index 50f52b5..37812b2 100644 --- a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialPlan.java +++ b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialPlan.java @@ -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 execute(Calendar now); } diff --git a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialVerticle.java b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialVerticle.java new file mode 100644 index 0000000..c512904 --- /dev/null +++ b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundialVerticle.java @@ -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(); + }); + } +} From 3399b04a2b490b1ccc3ebe18937c496f235b22cb Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Wed, 10 Apr 2024 13:49:08 +0800 Subject: [PATCH 09/13] 3.2.4-SNAPSHOT + Vertx Json Schema + Keel 4.5.7 Signed-off-by: Sinri Edogawa --- pom.xml | 7 ++++++- .../github/sinri/keel/core/KeelCronExpression.java | 13 ++++++++++++- .../keel/core/json/scheme/JsonArrayScheme.java | 1 + .../keel/core/json/scheme/JsonBooleanScheme.java | 1 + .../keel/core/json/scheme/JsonElementScheme.java | 1 + .../sinri/keel/core/json/scheme/JsonNullScheme.java | 1 + .../keel/core/json/scheme/JsonNumberScheme.java | 1 + .../keel/core/json/scheme/JsonObjectScheme.java | 1 + .../keel/core/json/scheme/JsonPlainScheme.java | 1 + .../json/scheme/JsonSchemeMismatchException.java | 1 + .../keel/core/json/scheme/JsonStringScheme.java | 1 + .../keel/core/json/scheme/JsonValueScheme.java | 1 + .../sinri/keel/servant/sundial/KeelSundial.java | 7 +++---- 13 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 49214b9..9192d76 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ UTF-8 - 4.5.4 + 4.5.7 0.21.0 2.15.3 5.2.5 @@ -145,6 +145,11 @@ vertx-redis-client ${vertxVersion} + + io.vertx + vertx-json-schema + ${vertxVersion} + org.apache.poi poi diff --git a/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java b/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java index a866978..b29cd58 100644 --- a/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java +++ b/src/main/java/io/github/sinri/keel/core/KeelCronExpression.java @@ -104,6 +104,13 @@ private void parseField(@Nonnull String rawComponent, @Nonnull Set opti } } + /** + * @since 3.2.4 + */ + public static ParsedCalenderElements parseCalenderToElements(@Nonnull Calendar currentCalendar) { + return new ParsedCalenderElements(currentCalendar); + } + @Nonnull public String getRawCronExpression() { return rawCronExpression; @@ -119,17 +126,21 @@ public static class ParsedCalenderElements { public final int month; public final int weekday; + // debug use + public final int second; + 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, ... + second = currentCalendar.get(Calendar.SECOND); } @Override public String toString() { - return minute + " " + hour + " " + day + " " + month + " " + weekday; + return "(" + second + ") " + minute + " " + hour + " " + day + " " + month + " " + weekday; } } diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonArrayScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonArrayScheme.java index 35834fa..1e5b5d7 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonArrayScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonArrayScheme.java @@ -10,6 +10,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonArrayScheme extends JsonValueScheme { private final Map> indexedElementSchemeMap = new LinkedHashMap<>(); private JsonElementScheme defaultElementScheme; diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonBooleanScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonBooleanScheme.java index fd19fc7..87c90b2 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonBooleanScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonBooleanScheme.java @@ -7,6 +7,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonBooleanScheme extends JsonValueScheme { private Boolean expected; diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonElementScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonElementScheme.java index 51d0f27..206873c 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonElementScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonElementScheme.java @@ -6,6 +6,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public interface JsonElementScheme extends JsonifiableEntity> { static JsonElementScheme fromJsonObject(JsonObject jsonObject) { JsonElementSchemeType scheme_type = JsonElementSchemeType.valueOf(jsonObject.getString("scheme_type")); diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNullScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNullScheme.java index bc5f0ce..66a7c1a 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNullScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNullScheme.java @@ -7,6 +7,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonNullScheme extends JsonValueScheme { public JsonNullScheme() { super(); diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNumberScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNumberScheme.java index 03fd98d..5ea412f 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNumberScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonNumberScheme.java @@ -8,6 +8,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonNumberScheme extends JsonValueScheme { //private boolean withFractions; diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonObjectScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonObjectScheme.java index 6472614..f15e870 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonObjectScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonObjectScheme.java @@ -9,6 +9,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonObjectScheme extends JsonValueScheme { private final Map> elementSchemeMap = new LinkedHashMap<>(); diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonPlainScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonPlainScheme.java index 520b636..aafe81c 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonPlainScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonPlainScheme.java @@ -4,6 +4,7 @@ import javax.annotation.Nonnull; +@Deprecated(since = "3.2.4") public class JsonPlainScheme extends JsonValueScheme { @Override diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonSchemeMismatchException.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonSchemeMismatchException.java index c9b9e46..58f6dea 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonSchemeMismatchException.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonSchemeMismatchException.java @@ -6,6 +6,7 @@ import static io.github.sinri.keel.helper.KeelHelpersInterface.KeelHelpers; +@Deprecated(since = "3.2.4") public class JsonSchemeMismatchException extends Exception { public static final String RuleSchemeError = "SchemeError"; public static final String RuleEmptyArrayNotAllowed = "EmptyArrayNotAllowed"; diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonStringScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonStringScheme.java index a426b0e..70a847d 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonStringScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonStringScheme.java @@ -8,6 +8,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") public class JsonStringScheme extends JsonValueScheme { private Pattern pattern; diff --git a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonValueScheme.java b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonValueScheme.java index 1e4c402..3ac056a 100644 --- a/src/main/java/io/github/sinri/keel/core/json/scheme/JsonValueScheme.java +++ b/src/main/java/io/github/sinri/keel/core/json/scheme/JsonValueScheme.java @@ -7,6 +7,7 @@ /** * @since 2.7 */ +@Deprecated(since = "3.2.4") abstract public class JsonValueScheme implements JsonElementScheme { protected T digested; diff --git a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java index 592fc65..1a2583a 100644 --- a/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java +++ b/src/main/java/io/github/sinri/keel/servant/sundial/KeelSundial.java @@ -32,10 +32,9 @@ protected KeelEventLogger buildEventLogger() { @Override public void start() throws Exception { - long delaySeconds = 60 - (System.currentTimeMillis() / 1000) % 60; - this.timerID = Keel.getVertx().setPeriodic(delaySeconds, 60_000L, timerID -> { - Calendar calendar = Calendar.getInstance(); - handleEveryMinute(calendar); + int delaySeconds = 61 - KeelCronExpression.parseCalenderToElements(Calendar.getInstance()).second; + this.timerID = Keel.getVertx().setPeriodic(delaySeconds * 1000L, 60_000L, timerID -> { + handleEveryMinute(Calendar.getInstance()); refreshPlans(); }); } From acfebc240661057c438bb70457999d75f304fbeb Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Wed, 10 Apr 2024 14:34:10 +0800 Subject: [PATCH 10/13] An IDEA 2024.1 issue Signed-off-by: Sinri Edogawa --- .../keel/test/lab/idea/ChildWithoutMainButSuperHas.java | 4 ++++ .../io/github/sinri/keel/test/lab/idea/SuperWithMain.java | 7 +++++++ .../io/github/sinri/keel/test/lab/idea/package-info.java | 1 + 3 files changed, 12 insertions(+) create mode 100644 src/test/java/io/github/sinri/keel/test/lab/idea/ChildWithoutMainButSuperHas.java create mode 100644 src/test/java/io/github/sinri/keel/test/lab/idea/SuperWithMain.java create mode 100644 src/test/java/io/github/sinri/keel/test/lab/idea/package-info.java diff --git a/src/test/java/io/github/sinri/keel/test/lab/idea/ChildWithoutMainButSuperHas.java b/src/test/java/io/github/sinri/keel/test/lab/idea/ChildWithoutMainButSuperHas.java new file mode 100644 index 0000000..254f0e9 --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/idea/ChildWithoutMainButSuperHas.java @@ -0,0 +1,4 @@ +package io.github.sinri.keel.test.lab.idea; + +public class ChildWithoutMainButSuperHas extends SuperWithMain { +} diff --git a/src/test/java/io/github/sinri/keel/test/lab/idea/SuperWithMain.java b/src/test/java/io/github/sinri/keel/test/lab/idea/SuperWithMain.java new file mode 100644 index 0000000..377b33b --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/idea/SuperWithMain.java @@ -0,0 +1,7 @@ +package io.github.sinri.keel.test.lab.idea; + +public class SuperWithMain { + public static void main(String[] args) { + System.out.println("Super!"); + } +} diff --git a/src/test/java/io/github/sinri/keel/test/lab/idea/package-info.java b/src/test/java/io/github/sinri/keel/test/lab/idea/package-info.java new file mode 100644 index 0000000..d91c756 --- /dev/null +++ b/src/test/java/io/github/sinri/keel/test/lab/idea/package-info.java @@ -0,0 +1 @@ +package io.github.sinri.keel.test.lab.idea; \ No newline at end of file From 02438043275a4011986bbde9fac02000c7a45085 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Wed, 10 Apr 2024 17:19:22 +0800 Subject: [PATCH 11/13] Still https://youtrack.jetbrains.com/issue/IDEA-351297/Could-not-direct-run-classes-with-main-method-defined-in-their-super-classes-as-of-2024.1 Signed-off-by: Sinri Edogawa --- .../sinri/keel/test/lab/blocking/BlockingVerticlePlanA.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/io/github/sinri/keel/test/lab/blocking/BlockingVerticlePlanA.java b/src/test/java/io/github/sinri/keel/test/lab/blocking/BlockingVerticlePlanA.java index 2757e52..3210f21 100644 --- a/src/test/java/io/github/sinri/keel/test/lab/blocking/BlockingVerticlePlanA.java +++ b/src/test/java/io/github/sinri/keel/test/lab/blocking/BlockingVerticlePlanA.java @@ -45,7 +45,7 @@ public static void main(String[] args) { // System.out.println("isWorkerContext: " + futureForBlocking.context.isWorkerContext()); // System.out.println("isEventLoopContext: " + futureForBlocking.context.isEventLoopContext()); - return Future.succeededFuture(); + return io.vertx.core.Future.succeededFuture(); }) .compose(ready -> { return Future.all( From 89c21865aa94f162782a6a2b0bbb9bd0ffb2ad22 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Fri, 12 Apr 2024 16:24:21 +0800 Subject: [PATCH 12/13] 3.2.4-SNAPSHOT Signed-off-by: Sinri Edogawa --- .../sinri/keel/mysql/condition/AmongstCondition.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/io/github/sinri/keel/mysql/condition/AmongstCondition.java b/src/main/java/io/github/sinri/keel/mysql/condition/AmongstCondition.java index fcaa3b1..ccb2c0e 100644 --- a/src/main/java/io/github/sinri/keel/mysql/condition/AmongstCondition.java +++ b/src/main/java/io/github/sinri/keel/mysql/condition/AmongstCondition.java @@ -2,6 +2,7 @@ import io.github.sinri.keel.mysql.Quoter; import io.github.sinri.keel.mysql.exception.KeelSQLGenerateError; +import io.github.sinri.keel.mysql.statement.AbstractReadStatement; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -207,6 +208,14 @@ public AmongstCondition amongstExpressionList(@Nonnull List values) { return this; } + /** + * @param readStatement A READ Statement, such as SELECT. + * @since 3.2.4 + */ + public AmongstCondition amongstReadStatement(@Nonnull AbstractReadStatement readStatement) { + return this.amongstExpression(readStatement.toString()); + } + /** * 生成SQL的比较条件表达式文本。如果出错,则抛出 KeelSQLGenerateError 异常。 * From a0f0e455c60ac100ab3ae75efa21448f2198d791 Mon Sep 17 00:00:00 2001 From: Sinri Edogawa Date: Mon, 15 Apr 2024 13:43:04 +0800 Subject: [PATCH 13/13] 3.2.4 Signed-off-by: Sinri Edogawa --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9192d76..13a71cc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,8 +6,8 @@ io.github.sinri Keel - 3.2.4-SNAPSHOT - + + 3.2.4 Keel