Search code examples
spring-bootflyway

Correct Execution Order with two Datasources for Flyway Migration Spring Boot


We have a core library and several integration projects. Each of the integration projects uses the core library and inherits the core DB flyway migrations. In the core, there are the flyway migration scripts creating the schemas and some initial data. The integration projects also contain migration scripts. So far the order of execution of the migration scripts is such that the core migrations always run before those of the integration project as follows:

V1_1__core.sql
V1_2__core.sql
V2_1__core.sql
V1_1__integration.sql
V2_1__integration.sql
etc.

However, what I want is that the version takes precedence and not the project such as:

V1_1__core.sql
V1_2__core.sql
V1_1__integration.sql
V2_1__core.sql
V2_1__integration.sql
etc.

I use the following class in the core:

@Component
public class FlywayModuleMigrationConfig implements FlywayMigrationStrategy {

    @Autowired(required = false)
    private FlywayModuleMigrationConfigService flywayModuleMigrationConfigService;

    @Override
    public void migrate(Flyway flyway) {
        DataSource dataSource = flyway.getConfiguration().getDataSource();
        
        Flyway coreModule = Flyway.configure()
                .schemas("public")
                .locations("db/migration/core")
                .table("core_schema_version")
                .dataSource(dataSource).load();

        coreModule.migrate();

        //Load module specific Flyway migration scripts
        if (flywayModuleMigrationConfigService != null) flywayModuleMigrationConfigService.migrate(flyway);

    }
}

And the following in the integration project:

public class CanbFlywayModuleMigrationConfig implements FlywayModuleMigrationConfigService {

    @Override
    public void migrate(Flyway flyway) {
        DataSource dataSource = flyway.getConfiguration().getDataSource();

        Flyway module = Flyway.configure()
                .schemas("public")
                .locations("db/migration/canb")
                .table("canb_schema_version")
                .baselineOnMigrate(true)
                .dataSource(dataSource).load();

        module.migrate();
    }
}

How can this be achieved with Flyway?


Solution

  • Given multiple locations in one migrate - that is:

    flyway = Flyway.configure().locations("db/migration/core,db/migration/canb")...
    

    then Flyway will scan the locations and run everything it finds in strict version order. However it will only use one history table, which will mean that you can't have the same version number in both core and integration project, as you have in the above example - what you'd need to do is:

    V1_1__core.sql
    V1_2__core.sql
    V1_2_1__integration.sql
    V2_1__core.sql
    V2_1_1__integration.sql
    

    so that integration scripts take their version number from the corresponding required core version. If you adopted this pattern, you'd also need to move across past records from one history table to the other so that you have a complete history in an single place.