From 8bb35c4b79d568282820769716165b5fb1928c95 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 25 Aug 2023 21:00:03 +0200 Subject: [PATCH] Rework how to enable/activate Flyway (cherry picked from commit f6027e8080cd6ea583498898816251af934bce48) --- .../flyway/FlywayAlwaysEnabledProcessor.java | 44 ++++++++++++++ .../java/io/quarkus/flyway/FlywayEnabled.java | 24 ++++++++ .../io/quarkus/flyway/FlywayProcessor.java | 57 +++++-------------- .../flyway/runtime/FlywayBuildTimeConfig.java | 10 ++++ .../FlywayDataSourceRuntimeConfig.java | 6 ++ .../flyway/runtime/FlywayRecorder.java | 8 +-- .../flyway/runtime/FlywayRuntimeConfig.java | 7 --- 7 files changed, 103 insertions(+), 53 deletions(-) create mode 100644 extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java create mode 100644 extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java new file mode 100644 index 0000000000000..54a2023318acc --- /dev/null +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayAlwaysEnabledProcessor.java @@ -0,0 +1,44 @@ +package io.quarkus.flyway; + +import org.flywaydb.core.extensibility.Plugin; + +import io.quarkus.deployment.Feature; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.IndexDependencyBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; + +public class FlywayAlwaysEnabledProcessor { + + @BuildStep + void build(BuildProducer featureProducer) { + featureProducer.produce(new FeatureBuildItem(Feature.FLYWAY)); + } + + /** + * Reinitialize {@code InsertRowLock} to avoid using a cached seed when invoking {@code getNextRandomString} + */ + @BuildStep + public RuntimeReinitializedClassBuildItem reinitInsertRowLock() { + return new RuntimeReinitializedClassBuildItem( + "org.flywaydb.core.internal.database.InsertRowLock"); + } + + @BuildStep + public NativeImageResourceBuildItem resources() { + return new NativeImageResourceBuildItem("org/flywaydb/database/version.txt"); + } + + @BuildStep + IndexDependencyBuildItem indexFlyway() { + return new IndexDependencyBuildItem("org.flywaydb", "flyway-core"); + } + + @BuildStep + public ServiceProviderBuildItem flywayPlugins() { + return ServiceProviderBuildItem.allProvidersFromClassPath(Plugin.class.getName()); + } +} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java new file mode 100644 index 0000000000000..18060719451c6 --- /dev/null +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayEnabled.java @@ -0,0 +1,24 @@ +package io.quarkus.flyway; + +import java.util.function.BooleanSupplier; + +import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; + +/** + * Supplier that can be used to only run build steps + * if the Flyway extension is enabled. + */ +public class FlywayEnabled implements BooleanSupplier { + + private final FlywayBuildTimeConfig config; + + FlywayEnabled(FlywayBuildTimeConfig config) { + this.config = config; + } + + @Override + public boolean getAsBoolean() { + return config.enabled; + } + +} diff --git a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java index 1fb06fce2b9c2..61740d5cd0652 100644 --- a/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java +++ b/extensions/flyway/deployment/src/main/java/io/quarkus/flyway/FlywayProcessor.java @@ -25,7 +25,6 @@ import org.flywaydb.core.api.Location; import org.flywaydb.core.api.callback.Callback; import org.flywaydb.core.api.migration.JavaMigration; -import org.flywaydb.core.extensibility.Plugin; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.ClassType; @@ -43,34 +42,32 @@ import io.quarkus.arc.processor.DotNames; import io.quarkus.builder.item.SimpleBuildItem; import io.quarkus.datasource.common.runtime.DataSourceUtil; -import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.BuildSteps; import io.quarkus.deployment.annotations.Consume; import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Produce; import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.ApplicationInfoBuildItem; import io.quarkus.deployment.builditem.CombinedIndexBuildItem; -import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem; -import io.quarkus.deployment.builditem.IndexDependencyBuildItem; import io.quarkus.deployment.builditem.InitTaskBuildItem; import io.quarkus.deployment.builditem.InitTaskCompletedBuildItem; import io.quarkus.deployment.builditem.ServiceStartBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; -import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; -import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; import io.quarkus.deployment.logging.LoggingSetupBuildItem; import io.quarkus.deployment.recording.RecorderContext; import io.quarkus.flyway.runtime.FlywayBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayContainer; import io.quarkus.flyway.runtime.FlywayContainerProducer; +import io.quarkus.flyway.runtime.FlywayDataSourceBuildTimeConfig; import io.quarkus.flyway.runtime.FlywayRecorder; import io.quarkus.flyway.runtime.FlywayRuntimeConfig; import io.quarkus.runtime.util.ClassPathUtils; +@BuildSteps(onlyIf = FlywayEnabled.class) class FlywayProcessor { private static final String CLASSPATH_APPLICATION_MIGRATIONS_PROTOCOL = "classpath"; @@ -82,32 +79,26 @@ class FlywayProcessor { private static final Logger LOGGER = Logger.getLogger(FlywayProcessor.class); - FlywayBuildTimeConfig flywayBuildConfig; - - @BuildStep - IndexDependencyBuildItem indexFlyway() { - return new IndexDependencyBuildItem("org.flywaydb", "flyway-core"); - } - @Record(STATIC_INIT) @BuildStep - MigrationStateBuildItem build(BuildProducer featureProducer, - BuildProducer resourceProducer, + MigrationStateBuildItem build(BuildProducer resourceProducer, BuildProducer reflectiveClassProducer, BuildProducer hotDeploymentProducer, FlywayRecorder recorder, RecorderContext context, CombinedIndexBuildItem combinedIndexBuildItem, - List jdbcDataSourceBuildItems) throws Exception { - - featureProducer.produce(new FeatureBuildItem(Feature.FLYWAY)); + List jdbcDataSourceBuildItems, + FlywayBuildTimeConfig flywayBuildTimeConfig) throws Exception { Collection dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems); Map> applicationMigrationsToDs = new HashMap<>(); - for (var i : dataSourceNames) { + for (var dataSourceName : dataSourceNames) { + FlywayDataSourceBuildTimeConfig flywayDataSourceBuildTimeConfig = flywayBuildTimeConfig + .getConfigForDataSourceName(dataSourceName); + Collection migrationLocations = discoverApplicationMigrations( - flywayBuildConfig.getConfigForDataSourceName(i).locations); - applicationMigrationsToDs.put(i, migrationLocations); + flywayDataSourceBuildTimeConfig.locations); + applicationMigrationsToDs.put(dataSourceName, migrationLocations); } Set datasourcesWithMigrations = new HashSet<>(); Set datasourcesWithoutMigrations = new HashSet<>(); @@ -138,7 +129,7 @@ MigrationStateBuildItem build(BuildProducer featureProducer, final Map> callbacks = FlywayCallbacksLocator.with( dataSourceNames, - flywayBuildConfig, + flywayBuildTimeConfig, combinedIndexBuildItem, reflectiveClassProducer).getCallbacks(); recorder.setApplicationCallbackClasses(callbacks); @@ -170,7 +161,8 @@ void createBeans(FlywayRecorder recorder, List sqlGeneratorBuildItems, BuildProducer additionalBeans, BuildProducer syntheticBeanBuildItemBuildProducer, - MigrationStateBuildItem migrationsBuildItem) { + MigrationStateBuildItem migrationsBuildItem, + FlywayBuildTimeConfig flywayBuildTimeConfig) { // make a FlywayContainerProducer bean additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClasses(FlywayContainerProducer.class).setUnremovable() .setDefaultScope(DotNames.SINGLETON).build()); @@ -341,25 +333,6 @@ private Set getApplicationMigrationsFromPath(final String location, fina } } - /** - * Reinitialize {@code InsertRowLock} to avoid using a cached seed when invoking {@code getNextRandomString} - */ - @BuildStep - public RuntimeReinitializedClassBuildItem reinitInsertRowLock() { - return new RuntimeReinitializedClassBuildItem( - "org.flywaydb.core.internal.database.InsertRowLock"); - } - - @BuildStep - public NativeImageResourceBuildItem resources() { - return new NativeImageResourceBuildItem("org/flywaydb/database/version.txt"); - } - - @BuildStep - public ServiceProviderBuildItem flywayPlugins() { - return ServiceProviderBuildItem.allProvidersFromClassPath(Plugin.class.getName()); - } - public static final class MigrationStateBuildItem extends SimpleBuildItem { final Set hasMigrations; diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java index 47e7a4878c7f4..5560e96941cc4 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayBuildTimeConfig.java @@ -21,6 +21,16 @@ public FlywayDataSourceBuildTimeConfig getConfigForDataSourceName(String dataSou return namedDataSources.getOrDefault(dataSourceName, FlywayDataSourceBuildTimeConfig.defaultConfig()); } + /** + * Whether Flyway is enabled *during the build*. + * + * If Flyway is disabled, the Flyway beans won't be created and Flyway won't be usable. + * + * @asciidoclet + */ + @ConfigItem(defaultValue = "true") + public boolean enabled; + /** * Flyway configuration for the default datasource. */ diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java index 79f4c961a0e5a..726ada0de89fd 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayDataSourceRuntimeConfig.java @@ -22,6 +22,12 @@ public static FlywayDataSourceRuntimeConfig defaultConfig() { return new FlywayDataSourceRuntimeConfig(); } + /** + * Flag to activate/deactivate Flyway for a specific datasource at runtime. + */ + @ConfigItem(defaultValue = "true") + public boolean active = true; + /** * The maximum number of retries when attempting to connect to the database. *

diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java index 2bb0fffb51c72..8200a4b18d730 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRecorder.java @@ -96,13 +96,13 @@ public Flyway apply(SyntheticCreationalContext context) { } public void doStartActions() { - if (!config.getValue().enabled) { - return; - } - for (InstanceHandle flywayContainerHandle : Arc.container().listAll(FlywayContainer.class)) { FlywayContainer flywayContainer = flywayContainerHandle.get(); + if (!config.getValue().getConfigForDataSourceName(flywayContainer.getDataSourceName()).active) { + return; + } + if (flywayContainer.isCleanAtStart()) { flywayContainer.getFlyway().clean(); } diff --git a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java index 481ee6e821539..703e3cd0b00a1 100644 --- a/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java +++ b/extensions/flyway/runtime/src/main/java/io/quarkus/flyway/runtime/FlywayRuntimeConfig.java @@ -21,13 +21,6 @@ public FlywayDataSourceRuntimeConfig getConfigForDataSourceName(String dataSourc return namedDataSources.getOrDefault(dataSourceName, FlywayDataSourceRuntimeConfig.defaultConfig()); } - /** - * Flag to enable / disable Flyway. - * - */ - @ConfigItem(defaultValue = "true") - public boolean enabled; - /** * Flyway configuration for the default datasource. */