[Bugfix] fixed broken migrations in multiple realms
This commit is contained in:
parent
f43088d680
commit
cfb30486e0
|
@ -2,6 +2,7 @@ package li.strolch.migrations;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.SortedSet;
|
||||
|
@ -25,14 +26,15 @@ public class Migrations {
|
|||
private Map<String, Version> currentVersions;
|
||||
private boolean verbose;
|
||||
|
||||
private SortedSet<DataMigration> dataMigrations;
|
||||
private SortedSet<CodeMigration> codeMigrations;
|
||||
private Map<String, SortedSet<DataMigration>> dataMigrations;
|
||||
private Map<String, SortedSet<CodeMigration>> codeMigrations;
|
||||
|
||||
private MapOfLists<String, Version> migrationsRan;
|
||||
|
||||
public Migrations(ComponentContainer container, Map<String, Version> currentVersions) {
|
||||
public Migrations(ComponentContainer container, Map<String, Version> currentVersions, boolean verbose) {
|
||||
this.container = container;
|
||||
this.currentVersions = currentVersions;
|
||||
this.verbose = verbose;
|
||||
}
|
||||
|
||||
public void setVerbose(boolean verbose) {
|
||||
|
@ -75,15 +77,17 @@ public class Migrations {
|
|||
CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null);
|
||||
DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null);
|
||||
|
||||
if (!this.codeMigrations.isEmpty()) {
|
||||
for (CodeMigration migration : this.codeMigrations.tailSet(currentCodeMigration)) {
|
||||
SortedSet<CodeMigration> codeMigrations = this.codeMigrations.get(realm);
|
||||
if (codeMigrations != null && !codeMigrations.isEmpty()) {
|
||||
for (CodeMigration migration : codeMigrations.tailSet(currentCodeMigration)) {
|
||||
migration.migrate(container, certificate);
|
||||
migrationsRan.addElement(realm, migration.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.dataMigrations.isEmpty()) {
|
||||
for (DataMigration migration : this.dataMigrations.tailSet(currentDataMigration)) {
|
||||
SortedSet<DataMigration> dataMigrations = this.dataMigrations.get(realm);
|
||||
if (dataMigrations != null && !dataMigrations.isEmpty()) {
|
||||
for (DataMigration migration : dataMigrations.tailSet(currentDataMigration)) {
|
||||
migration.migrate(container, certificate);
|
||||
migrationsRan.addElement(realm, migration.getVersion());
|
||||
}
|
||||
|
@ -100,12 +104,14 @@ public class Migrations {
|
|||
}
|
||||
|
||||
private static void logDetectedMigrations(Map<String, Version> currentVersions,
|
||||
SortedSet<DataMigration> dataMigrations, SortedSet<CodeMigration> codeMigrations) {
|
||||
Map<String, SortedSet<DataMigration>> allDataMigrations,
|
||||
Map<String, SortedSet<CodeMigration>> allCodeMigrations) {
|
||||
for (Entry<String, Version> entry : currentVersions.entrySet()) {
|
||||
String realm = entry.getKey();
|
||||
Version currentVersion = entry.getValue();
|
||||
|
||||
if (codeMigrations.isEmpty()) {
|
||||
SortedSet<CodeMigration> codeMigrations = allCodeMigrations.get(realm);
|
||||
if (codeMigrations == null || codeMigrations.isEmpty()) {
|
||||
logger.info("[" + realm + "] Found no code migrations.");
|
||||
} else {
|
||||
logger.info("[" + realm + "] Found " + codeMigrations.size() + " code migrations");
|
||||
|
@ -117,7 +123,8 @@ public class Migrations {
|
|||
}
|
||||
}
|
||||
|
||||
if (dataMigrations.isEmpty()) {
|
||||
SortedSet<DataMigration> dataMigrations = allDataMigrations.get(realm);
|
||||
if (dataMigrations == null || dataMigrations.isEmpty()) {
|
||||
logger.info("[" + realm + "] Found no data migrations.");
|
||||
} else {
|
||||
logger.info("[" + realm + "] Found " + dataMigrations.size() + " data migrations");
|
||||
|
@ -131,68 +138,68 @@ public class Migrations {
|
|||
}
|
||||
}
|
||||
|
||||
private static SortedSet<DataMigration> loadDataMigrations(Map<String, Version> currentVersions, File migrationsPath) {
|
||||
private static Map<String, SortedSet<DataMigration>> loadDataMigrations(Map<String, Version> currentVersions,
|
||||
File migrationsPath) {
|
||||
|
||||
SortedSet<DataMigration> dataMigrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(o2.getVersion()));
|
||||
Map<String, SortedSet<DataMigration>> migrationsByRealm = new HashMap<>();
|
||||
|
||||
File dataDir = new File(migrationsPath, "data");
|
||||
if (dataDir.exists()) {
|
||||
DBC.PRE.assertTrue("migrations/data must be a directory!", dataDir.isDirectory());
|
||||
|
||||
File[] realmMigrations = dataDir.listFiles();
|
||||
// only list directories where name is a realmName
|
||||
File[] realmMigrations = dataDir
|
||||
.listFiles((FileFilter) path -> currentVersions.containsKey(path.getName()));
|
||||
|
||||
for (File realmMigration : realmMigrations) {
|
||||
|
||||
DBC.PRE.assertTrue("found non directory in migrations path: " + realmMigration.getAbsolutePath(),
|
||||
realmMigration.isDirectory());
|
||||
String realm = realmMigration.getName();
|
||||
if (!currentVersions.containsKey(realm)) {
|
||||
logger.warn("Found non realm migration directory: " + realmMigration.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
File[] migrations = realmMigration.listFiles((FileFilter) pathname -> pathname.getName().endsWith(
|
||||
SortedSet<DataMigration> migrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(
|
||||
o2.getVersion()));
|
||||
migrationsByRealm.put(realm, migrations);
|
||||
|
||||
File[] migrationFiles = realmMigration.listFiles((FileFilter) pathname -> pathname.getName().endsWith(
|
||||
".xml"));
|
||||
for (File file : migrations) {
|
||||
for (File file : migrationFiles) {
|
||||
String name = file.getName();
|
||||
Version version = Version.valueOf(name.substring(0, name.length() - 4));
|
||||
dataMigrations.add(new DataMigration(realm, version, file));
|
||||
migrations.add(new DataMigration(realm, version, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataMigrations;
|
||||
return migrationsByRealm;
|
||||
}
|
||||
|
||||
private static SortedSet<CodeMigration> loadCodeMigrations(Map<String, Version> currentVersions, File migrationsPath) {
|
||||
private static Map<String, SortedSet<CodeMigration>> loadCodeMigrations(Map<String, Version> currentVersions,
|
||||
File migrationsPath) {
|
||||
|
||||
SortedSet<CodeMigration> codeMigrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(o2.getVersion()));
|
||||
Map<String, SortedSet<CodeMigration>> migrationsByRealm = new HashMap<>(); //new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(o2.getVersion()));
|
||||
|
||||
File codeDir = new File(migrationsPath, "code");
|
||||
if (codeDir.exists()) {
|
||||
DBC.PRE.assertTrue("migrations/code must be a directory!", codeDir.isDirectory());
|
||||
|
||||
File[] realmMigrations = codeDir.listFiles();
|
||||
File[] realmMigrations = codeDir
|
||||
.listFiles((FileFilter) path -> currentVersions.containsKey(path.getName()));
|
||||
for (File realmMigration : realmMigrations) {
|
||||
|
||||
DBC.PRE.assertTrue("found non directory in migrations path: " + realmMigration.getAbsolutePath(),
|
||||
realmMigration.isDirectory());
|
||||
String realm = realmMigration.getName();
|
||||
if (!currentVersions.containsKey(realm)) {
|
||||
logger.warn("Found non realm migration directory: " + realmMigration.getAbsolutePath());
|
||||
continue;
|
||||
}
|
||||
|
||||
File[] migrations = realmMigration.listFiles((FileFilter) pathname -> pathname.getName().endsWith(
|
||||
SortedSet<CodeMigration> migrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(
|
||||
o2.getVersion()));
|
||||
migrationsByRealm.put(realm, migrations);
|
||||
|
||||
File[] migrationFiles = realmMigration.listFiles((FileFilter) pathname -> pathname.getName().endsWith(
|
||||
".xml"));
|
||||
for (File file : migrations) {
|
||||
for (File file : migrationFiles) {
|
||||
String name = file.getName();
|
||||
Version version = Version.valueOf(name.substring(0, name.length() - 4));
|
||||
codeMigrations.add(new CodeMigration(realm, version, file));
|
||||
migrations.add(new CodeMigration(realm, version, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return codeMigrations;
|
||||
return migrationsByRealm;
|
||||
}
|
||||
|
||||
public MapOfLists<String, Version> getMigrationsToRun() {
|
||||
|
@ -205,15 +212,22 @@ public class Migrations {
|
|||
CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null);
|
||||
DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null);
|
||||
|
||||
SortedSet<CodeMigration> codeMigrations = this.codeMigrations.tailSet(currentCodeMigration);
|
||||
for (CodeMigration codeMigration : codeMigrations) {
|
||||
if (!migrationsToRun.containsElement(realm, codeMigration.getVersion()))
|
||||
migrationsToRun.addElement(realm, codeMigration.getVersion());
|
||||
SortedSet<CodeMigration> allCodeMigrations = this.codeMigrations.get(realm);
|
||||
if (allCodeMigrations != null) {
|
||||
SortedSet<CodeMigration> codeMigrations = allCodeMigrations.tailSet(currentCodeMigration);
|
||||
for (CodeMigration codeMigration : codeMigrations) {
|
||||
if (!migrationsToRun.containsElement(realm, codeMigration.getVersion()))
|
||||
migrationsToRun.addElement(realm, codeMigration.getVersion());
|
||||
}
|
||||
}
|
||||
SortedSet<DataMigration> dataMigrations = this.dataMigrations.tailSet(currentDataMigration);
|
||||
for (DataMigration dataMigration : dataMigrations) {
|
||||
if (!migrationsToRun.containsElement(realm, dataMigration.getVersion()))
|
||||
migrationsToRun.addElement(realm, dataMigration.getVersion());
|
||||
|
||||
SortedSet<DataMigration> allDataMigrations = this.dataMigrations.get(realm);
|
||||
if (allDataMigrations != null) {
|
||||
SortedSet<DataMigration> dataMigrations = allDataMigrations.tailSet(currentDataMigration);
|
||||
for (DataMigration dataMigration : dataMigrations) {
|
||||
if (!migrationsToRun.containsElement(realm, dataMigration.getVersion()))
|
||||
migrationsToRun.addElement(realm, dataMigration.getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,9 +75,8 @@ public class MigrationsHandler extends StrolchComponent {
|
|||
}
|
||||
|
||||
Map<String, Version> currentVersions = getCurrentVersions(cert);
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions);
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions, this.verbose);
|
||||
migrations.parseMigrations(this.migrationsPath);
|
||||
migrations.setVerbose(this.verbose);
|
||||
|
||||
this.migrations = migrations;
|
||||
return this.migrations.getMigrationsToRun();
|
||||
|
@ -107,9 +106,8 @@ public class MigrationsHandler extends StrolchComponent {
|
|||
privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, action);
|
||||
Map<String, Version> currentVersions = query.getCurrentVersions();
|
||||
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions);
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions, this.verbose);
|
||||
migrations.parseMigrations(this.migrationsPath);
|
||||
migrations.setVerbose(this.verbose);
|
||||
|
||||
this.migrations = migrations;
|
||||
}
|
||||
|
@ -172,9 +170,8 @@ public class MigrationsHandler extends StrolchComponent {
|
|||
privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction);
|
||||
Map<String, Version> currentVersions = query.getCurrentVersions();
|
||||
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions);
|
||||
Migrations migrations = new Migrations(getContainer(), currentVersions, MigrationsHandler.this.verbose);
|
||||
migrations.parseMigrations(MigrationsHandler.this.migrationsPath);
|
||||
migrations.setVerbose(MigrationsHandler.this.verbose);
|
||||
|
||||
MigrationsHandler.this.migrations = migrations;
|
||||
|
||||
|
|
|
@ -55,11 +55,13 @@ public class MigrationsTest {
|
|||
MigrationsHandler migrationsHandler = runtimeMock.getContainer().getComponent(MigrationsHandler.class);
|
||||
Map<String, Version> currentVersions = migrationsHandler.getCurrentVersions(cert);
|
||||
assertEquals("1.1.1", currentVersions.get(StrolchConstants.DEFAULT_REALM).toString());
|
||||
assertEquals("0.0.0", currentVersions.get("other").toString());
|
||||
|
||||
MapOfLists<String, Version> lastMigrations = migrationsHandler.getLastMigrations();
|
||||
List<Version> expectedMigrations = Arrays.asList(Version.valueOf("0.1.0"), Version.valueOf("0.1.1"),
|
||||
Version.valueOf("0.5.2"), Version.valueOf("1.0.0"), Version.valueOf("1.0.5"), Version.valueOf("1.1.1"));
|
||||
assertEquals(expectedMigrations, lastMigrations.getList(StrolchConstants.DEFAULT_REALM));
|
||||
assertEquals(null, lastMigrations.getList("other"));
|
||||
|
||||
MapOfLists<String, Version> migrationsToRun = migrationsHandler.queryMigrationsToRun(cert);
|
||||
assertTrue("Expected to have all migrations run", migrationsToRun.isEmpty());
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
|
||||
<depends>PrivilegeHandler</depends>
|
||||
<Properties>
|
||||
<realms>defaultRealm</realms>
|
||||
<realms>defaultRealm, other</realms>
|
||||
<dataStoreMode>TRANSIENT</dataStoreMode>
|
||||
<dataStoreFile>StrolchModel.xml</dataStoreFile>
|
||||
<dataStoreMode.other>TRANSIENT</dataStoreMode.other>
|
||||
<dataStoreFile.other>StrolchModel.xml</dataStoreFile.other>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component>
|
||||
|
|
Loading…
Reference in New Issue