diff --git a/pom.xml b/pom.xml
index eaf90a5..7b47c5a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
17
UTF-8
UTF-8
- 3.7.4
+ 3.8.1
5.11.0
diff --git a/providers/inmemory/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/providers/inmemory/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index d02dd55..ec6f439 100644
--- a/providers/inmemory/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/providers/inmemory/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -3,6 +3,7 @@ description: "Distributed lock for your scheduled tasks"
metadata:
keywords:
- "shedlock"
+ - "provider"
- "inmemory"
# guide: https://quarkiverse.github.io/quarkiverse-docs/shedlock/dev/ # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
categories:
diff --git a/providers/jdbc/deployment/src/main/java/io/quarkiverse/shedlock/providers/jdbc/deployment/JdbcSchedulerLockProcessor.java b/providers/jdbc/deployment/src/main/java/io/quarkiverse/shedlock/providers/jdbc/deployment/JdbcSchedulerLockProcessor.java
index 3539464..2dd5956 100644
--- a/providers/jdbc/deployment/src/main/java/io/quarkiverse/shedlock/providers/jdbc/deployment/JdbcSchedulerLockProcessor.java
+++ b/providers/jdbc/deployment/src/main/java/io/quarkiverse/shedlock/providers/jdbc/deployment/JdbcSchedulerLockProcessor.java
@@ -1,18 +1,22 @@
package io.quarkiverse.shedlock.providers.jdbc.deployment;
import java.util.List;
+import java.util.stream.Stream;
+
+import jakarta.inject.Singleton;
import org.jboss.jandex.DotName;
-import io.quarkiverse.shedlock.providers.jdbc.runtime.JdbcConfig;
-import io.quarkiverse.shedlock.providers.jdbc.runtime.JdbcLockProviderInitializer;
-import io.quarkiverse.shedlock.providers.jdbc.runtime.JdbcSchedulerLock;
-import io.quarkiverse.shedlock.providers.jdbc.runtime.JdbcSchedulerLockInterceptor;
+import io.quarkiverse.shedlock.providers.jdbc.runtime.*;
import io.quarkus.agroal.spi.JdbcDataSourceBuildItem;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.ValidationPhaseBuildItem.ValidationErrorBuildItem;
+import io.quarkus.datasource.common.runtime.DataSourceUtil;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.ApplicationIndexBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
@@ -37,26 +41,50 @@ void produceBeans(final BuildProducer additionalBeanBui
@BuildStep
List validateDataSourcesDefinitionsWhenJdbcShedLockIsUsed(
final ApplicationIndexBuildItem applicationIndexBuildItem,
- final JdbcConfig jdbcConfig,
final List jdbcDataSourceBuildItems) {
+ final List dataSourceNames = getDataSourcesNameFromJdbcSchedulerLocks(applicationIndexBuildItem);
+ return dataSourceNames
+ .stream()
+ .filter(shedLockDataSourceName -> jdbcDataSourceBuildItems.stream().map(JdbcDataSourceBuildItem::getName)
+ .noneMatch(jdbcDataSourceName -> jdbcDataSourceName.equals(shedLockDataSourceName)))
+ .map(missingDataSource -> new ValidationErrorBuildItem(
+ new IllegalStateException(String.format(
+ "A missing datasource '%s' has been defined for ShedLock. Please fixe the ShedLock configuration or add the datasource",
+ missingDataSource))))
+ .toList();
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ List registerJdbcLockProviderInitializer(
+ final ApplicationIndexBuildItem applicationIndexBuildItem,
+ final DataSourceNameRecorder dataSourceNameRecorder) {
+ final List dataSourceNames = getDataSourcesNameFromJdbcSchedulerLocks(applicationIndexBuildItem);
+ List list = dataSourceNames.stream()
+ .map(dataSourceName -> SyntheticBeanBuildItem.configure(DataSourceName.class)
+ .scope(Singleton.class)
+ .identifier(dataSourceName)
+ .supplier(dataSourceNameRecorder.dataSourceNameSupplier(dataSourceName))
+ .unremovable()
+ .done())
+ .toList();
+ return list;
+ }
+
+ private List getDataSourcesNameFromJdbcSchedulerLocks(ApplicationIndexBuildItem applicationIndexBuildItem) {
final DotName jdbcSchedulerLock = DotName.createSimple(JdbcSchedulerLock.class);
- final boolean shouldCheckDataSourcesBecauseLockIsUsed = applicationIndexBuildItem.getIndex()
- .getKnownClasses().stream()
- .anyMatch(classInfo -> classInfo.hasAnnotation(jdbcSchedulerLock) || classInfo.methods().stream()
- .anyMatch(methodInfo -> methodInfo.hasAnnotation(jdbcSchedulerLock)));
- if (shouldCheckDataSourcesBecauseLockIsUsed) {
- return jdbcConfig.dataSources()
- .keySet()
- .stream()
- .filter(shedLockDataSourceName -> jdbcDataSourceBuildItems.stream().map(JdbcDataSourceBuildItem::getName)
- .noneMatch(jdbcDataSourceName -> jdbcDataSourceName.equals(shedLockDataSourceName)))
- .map(missingDataSource -> new ValidationErrorBuildItem(
- new IllegalStateException(String.format(
- "A missing datasource '%s' has been defined for ShedLock. Please fixe the ShedLock configuration or add the datasource",
- missingDataSource))))
- .toList();
- } else {
- return List.of();
- }
+ return Stream.concat(
+ applicationIndexBuildItem.getIndex().getKnownClasses()
+ .stream().filter(classInfo -> classInfo.hasAnnotation(jdbcSchedulerLock))
+ .map(classInfo -> classInfo.annotation(jdbcSchedulerLock)),
+ applicationIndexBuildItem.getIndex().getKnownClasses().stream()
+ .flatMap(classInfo -> classInfo.methods().stream())
+ .filter(methodInfo -> methodInfo.hasAnnotation(jdbcSchedulerLock))
+ .map(methodInfo -> methodInfo.annotation(jdbcSchedulerLock)))
+ .map(annotationInstance -> annotationInstance.value("dataSourceName"))
+ .map(dataSourceName -> dataSourceName != null ? dataSourceName.asString()
+ : DataSourceUtil.DEFAULT_DATASOURCE_NAME)
+ .distinct()
+ .toList();
}
}
diff --git a/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/LockableServiceUsingUnknownDataSource.java b/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/LockableServiceUsingUnknownDataSource.java
new file mode 100644
index 0000000..28d3fe8
--- /dev/null
+++ b/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/LockableServiceUsingUnknownDataSource.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.shedlock.providers.jdbc.deployment;
+
+import jakarta.enterprise.context.ApplicationScoped;
+
+import io.quarkiverse.shedlock.providers.jdbc.runtime.JdbcSchedulerLock;
+
+@ApplicationScoped
+public class LockableServiceUsingUnknownDataSource {
+ @JdbcSchedulerLock(dataSourceName = "unknownDataSource")
+ void execute() {
+ }
+}
diff --git a/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/ShouldFailWhenUsedDataSourceIsNotPresentTest.java b/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/ShouldFailWhenUsedDataSourceIsNotPresentTest.java
index 6287c76..c3208ce 100644
--- a/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/ShouldFailWhenUsedDataSourceIsNotPresentTest.java
+++ b/providers/jdbc/deployment/src/test/java/io/quarkiverse/shedlock/providers/jdbc/deployment/ShouldFailWhenUsedDataSourceIsNotPresentTest.java
@@ -19,7 +19,7 @@ public class ShouldFailWhenUsedDataSourceIsNotPresentTest {
@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
- .addClasses(LockableService.class)
+ .addClasses(LockableServiceUsingUnknownDataSource.class)
.addAsResource(new StringAsset("quarkus.shedlock.defaults-lock-at-most-for=PT30S\n" +
"quarkus.shedlock.jdbc.unknownDataSource.table-name=myShedLockTableName"),
"application.properties"))
diff --git a/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceName.java b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceName.java
new file mode 100644
index 0000000..b492522
--- /dev/null
+++ b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceName.java
@@ -0,0 +1,5 @@
+package io.quarkiverse.shedlock.providers.jdbc.runtime;
+
+public interface DataSourceName {
+ String name();
+}
diff --git a/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceNameRecorder.java b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceNameRecorder.java
new file mode 100644
index 0000000..75eaf37
--- /dev/null
+++ b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/DataSourceNameRecorder.java
@@ -0,0 +1,12 @@
+package io.quarkiverse.shedlock.providers.jdbc.runtime;
+
+import java.util.function.Supplier;
+
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class DataSourceNameRecorder {
+ public Supplier dataSourceNameSupplier(final String dataSourceName) {
+ return () -> (DataSourceName) () -> dataSourceName;
+ }
+}
diff --git a/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/JdbcLockProviderInitializer.java b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/JdbcLockProviderInitializer.java
index 1d620f4..e863c5b 100644
--- a/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/JdbcLockProviderInitializer.java
+++ b/providers/jdbc/runtime/src/main/java/io/quarkiverse/shedlock/providers/jdbc/runtime/JdbcLockProviderInitializer.java
@@ -3,13 +3,17 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.Default;
+import jakarta.enterprise.inject.Instance;
import io.agroal.api.AgroalDataSource;
+import io.quarkiverse.shedlock.common.runtime.SchedulerLockInterceptorBase;
import io.quarkus.agroal.DataSource;
import io.quarkus.arc.Arc;
import io.quarkus.datasource.common.runtime.DataSourceUtil;
@@ -18,34 +22,42 @@
@ApplicationScoped
public class JdbcLockProviderInitializer {
private final JdbcConfig jdbcConfig;
+ private final List dataSourcesName;
- public JdbcLockProviderInitializer(final JdbcConfig jdbcConfig) {
+ public JdbcLockProviderInitializer(final JdbcConfig jdbcConfig,
+ final Instance dataSourcesName) {
this.jdbcConfig = Objects.requireNonNull(jdbcConfig);
+ this.dataSourcesName = Objects.requireNonNull(dataSourcesName).stream().toList();
}
void createTable(@Observes StartupEvent startupEvent) {
- jdbcConfig.dataSources().forEach((dataSourceName, dataSourceConfig) -> {
- final AgroalDataSource agroalDataSource = Arc.container()
- .select(AgroalDataSource.class,
- DataSourceUtil.DEFAULT_DATASOURCE_NAME.equals(dataSourceName) ? new Default.Literal()
- : new DataSource.DataSourceLiteral(dataSourceName))
- .get();
- final String databaseCreationSql = """
- CREATE TABLE IF NOT EXISTS %s (
- name VARCHAR(255),
- lock_until TIMESTAMP(3) NULL,
- locked_at TIMESTAMP(3) NULL,
- locked_by VARCHAR(255),
- PRIMARY KEY (name)
- )
- """;
- try (final Connection connection = agroalDataSource.getConnection()) {
- final PreparedStatement preparedStatement = connection
- .prepareStatement(String.format(databaseCreationSql, dataSourceConfig.tableName()));
- preparedStatement.execute();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- });
+ dataSourcesName
+ .stream().map(DataSourceName::name)
+ .forEach(dataSourceName -> {
+ final AgroalDataSource agroalDataSource = Arc.container()
+ .select(AgroalDataSource.class,
+ DataSourceUtil.DEFAULT_DATASOURCE_NAME.equals(dataSourceName) ? new Default.Literal()
+ : new DataSource.DataSourceLiteral(dataSourceName))
+ .get();
+ final String databaseCreationSql = """
+ CREATE TABLE IF NOT EXISTS %s (
+ name VARCHAR(255),
+ lock_until TIMESTAMP(3) NULL,
+ locked_at TIMESTAMP(3) NULL,
+ locked_by VARCHAR(255),
+ PRIMARY KEY (name)
+ )
+ """;
+ try (final Connection connection = agroalDataSource.getConnection()) {
+ final String tableName = Optional.ofNullable(jdbcConfig.dataSources().get(dataSourceName))
+ .map(JdbcConfig.DataSourceConfig::tableName)
+ .orElse(SchedulerLockInterceptorBase.SHED_LOCK);
+ final PreparedStatement preparedStatement = connection
+ .prepareStatement(String.format(databaseCreationSql, tableName));
+ preparedStatement.execute();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ });
}
}
diff --git a/providers/jdbc/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/providers/jdbc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 4a6e9db..fc77dcb 100644
--- a/providers/jdbc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/providers/jdbc/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -3,6 +3,7 @@ description: "Distributed lock for your scheduled tasks"
metadata:
keywords:
- "shedlock"
+ - "provider"
- "jdbc"
# guide: https://quarkiverse.github.io/quarkiverse-docs/shedlock/dev/ # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
categories:
diff --git a/providers/mongo/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/providers/mongo/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index 2011252..136144a 100644
--- a/providers/mongo/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/providers/mongo/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -3,6 +3,7 @@ description: "Distributed lock for your scheduled tasks"
metadata:
keywords:
- "shedlock"
+ - "provider"
- "mongo"
# guide: https://quarkiverse.github.io/quarkiverse-docs/shedlock/dev/ # To create and publish this guide, see https://github.com/quarkiverse/quarkiverse/wiki#documenting-your-extension
categories: