Skip to content

Commit

Permalink
Rework how to enable/activate Flyway
Browse files Browse the repository at this point in the history
  • Loading branch information
gsmet committed Sep 19, 2023
1 parent f974941 commit f6027e8
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -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<FeatureBuildItem> 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());
}
}
Original file line number Diff line number Diff line change
@@ -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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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";
Expand All @@ -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<FeatureBuildItem> featureProducer,
BuildProducer<NativeImageResourceBuildItem> resourceProducer,
MigrationStateBuildItem build(BuildProducer<NativeImageResourceBuildItem> resourceProducer,
BuildProducer<ReflectiveClassBuildItem> reflectiveClassProducer,
BuildProducer<HotDeploymentWatchedFileBuildItem> hotDeploymentProducer,
FlywayRecorder recorder,
RecorderContext context,
CombinedIndexBuildItem combinedIndexBuildItem,
List<JdbcDataSourceBuildItem> jdbcDataSourceBuildItems) throws Exception {

featureProducer.produce(new FeatureBuildItem(Feature.FLYWAY));
List<JdbcDataSourceBuildItem> jdbcDataSourceBuildItems,
FlywayBuildTimeConfig flywayBuildTimeConfig) throws Exception {

Collection<String> dataSourceNames = getDataSourceNames(jdbcDataSourceBuildItems);
Map<String, Collection<String>> applicationMigrationsToDs = new HashMap<>();
for (var i : dataSourceNames) {
for (var dataSourceName : dataSourceNames) {
FlywayDataSourceBuildTimeConfig flywayDataSourceBuildTimeConfig = flywayBuildTimeConfig
.getConfigForDataSourceName(dataSourceName);

Collection<String> migrationLocations = discoverApplicationMigrations(
flywayBuildConfig.getConfigForDataSourceName(i).locations);
applicationMigrationsToDs.put(i, migrationLocations);
flywayDataSourceBuildTimeConfig.locations);
applicationMigrationsToDs.put(dataSourceName, migrationLocations);
}
Set<String> datasourcesWithMigrations = new HashSet<>();
Set<String> datasourcesWithoutMigrations = new HashSet<>();
Expand Down Expand Up @@ -138,7 +129,7 @@ MigrationStateBuildItem build(BuildProducer<FeatureBuildItem> featureProducer,

final Map<String, Collection<Callback>> callbacks = FlywayCallbacksLocator.with(
dataSourceNames,
flywayBuildConfig,
flywayBuildTimeConfig,
combinedIndexBuildItem,
reflectiveClassProducer).getCallbacks();
recorder.setApplicationCallbackClasses(callbacks);
Expand Down Expand Up @@ -170,7 +161,8 @@ void createBeans(FlywayRecorder recorder,
List<JdbcInitialSQLGeneratorBuildItem> sqlGeneratorBuildItems,
BuildProducer<AdditionalBeanBuildItem> additionalBeans,
BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer,
MigrationStateBuildItem migrationsBuildItem) {
MigrationStateBuildItem migrationsBuildItem,
FlywayBuildTimeConfig flywayBuildTimeConfig) {
// make a FlywayContainerProducer bean
additionalBeans.produce(AdditionalBeanBuildItem.builder().addBeanClasses(FlywayContainerProducer.class).setUnremovable()
.setDefaultScope(DotNames.SINGLETON).build());
Expand Down Expand Up @@ -341,25 +333,6 @@ private Set<String> 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<String> hasMigrations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ public Flyway apply(SyntheticCreationalContext<Flyway> context) {
}

public void doStartActions() {
if (!config.getValue().enabled) {
return;
}

for (InstanceHandle<FlywayContainer> flywayContainerHandle : Arc.container().listAll(FlywayContainer.class)) {
FlywayContainer flywayContainer = flywayContainerHandle.get();

if (!config.getValue().getConfigForDataSourceName(flywayContainer.getDataSourceName()).active) {
return;
}

if (flywayContainer.isCleanAtStart()) {
flywayContainer.getFlyway().clean();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down

0 comments on commit f6027e8

Please sign in to comment.