[DEV] implemet base of migration

This commit is contained in:
Edouard DUPIN 2023-05-02 21:06:39 +02:00
parent 37212ba70e
commit 1501b7a21e
7 changed files with 247 additions and 13 deletions

View File

@ -1,5 +0,0 @@
package org.kar.archidata;
public class MigrationAction {
}

View File

@ -1,8 +0,0 @@
package org.kar.archidata;
import java.util.List;
public class MigrationSystem {
public MigrationSystem(List<MigrationAction> actions, List<Class<?>> implementationModel) {
}
}

View File

@ -0,0 +1,130 @@
package org.kar.archidata.migration;
import java.util.ArrayList;
import java.util.List;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.db.DBEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MigrationEngine {
final static Logger LOGGER = LoggerFactory.getLogger(MigrationEngine.class);
// List of order migrations
private final List<MigrationInterface> datas;
// initialization of the migration if the DB is not present...
private MigrationInterface init;
public MigrationEngine() {
this(new ArrayList<MigrationInterface>(), null);
}
public MigrationEngine( List<MigrationInterface> datas, MigrationInterface init) {
this.datas = datas;
this.init = init;
}
public void add(MigrationInterface migration) {
datas.add(migration);
}
public void setInit(MigrationInterface migration) {
init = migration;
}
/**
* Get the current version/migration name
* @return String represent the last migration. If null then no migration has been done.
*/
public String getCurrentVersion() {
try {
List<MigrationModel> data = SqlWrapper.gets(MigrationModel.class, false);
if (data == null) {
LOGGER.error("Can not collect the migration table in the DB:{}" );
return null;
}
if (data.size() == 0) {
LOGGER.error("Fail to Request migration table in the DB: empty size");
return null;
}
return data.get(data.size()-1).name;
} catch (Exception ex) {
LOGGER.error("Fail to Request migration table in the DB:{}", ex.getMessage());
ex.printStackTrace();
}
return null;
}
/**
* Get the current migration log generated
* @return String represent migration log (separate with \\n)
*/
public String getLastLog() {
try {
List<MigrationModel> data = SqlWrapper.gets(MigrationModel.class, false);
if (data == null) {
LOGGER.error("Can not collect the migration table in the DB:{}");
return null;
}
if (data.size() == 0) {
LOGGER.error("Fail to Request migration table in the DB: empty size");
return null;
}
return data.get(data.size()-1).log;
} catch (Exception ex) {
LOGGER.error("Fail to Request migration table in the DB:{}", ex.getMessage());
ex.printStackTrace();
}
return null;
}
public void migrate(DBEntry entry) {
String currentVersion = getCurrentVersion();
List<MigrationInterface> toApply = new ArrayList<>();
boolean find = false;
for (int iii=0; iii<this.datas.size(); iii++) {
if ( ! find) {
if (this.datas.get(iii).getName() == currentVersion) {
find = true;
}
continue;
}
toApply.add(this.datas.get(iii));
}
for (MigrationInterface elem : toApply) {
migrateSingle(entry, elem);
}
}
public void migrateSingle(DBEntry entry, MigrationInterface elem) {
LOGGER.info("Revert migration: {} [BEGIN]", elem.getName());
StringBuilder log = new StringBuilder();
if (elem.applyMigration(entry, log)) {
}
LOGGER.info("Revert migration: {} [ END ]", elem.getName());
}
public void revertTo(DBEntry entry, String migrationName) {
String currentVersion = getCurrentVersion();
List<MigrationInterface> toApply = new ArrayList<>();
boolean find = false;
for (int iii=this.datas.size()-1; iii>=0; iii--) {
if ( ! find) {
if (this.datas.get(iii).getName() == currentVersion) {
find = true;
}
continue;
}
if (this.datas.get(iii).getName() == currentVersion) {
break;
}
toApply.add(this.datas.get(iii));
}
for (MigrationInterface elem : toApply) {
revertSingle(entry, elem);
}
}
public void revertSingle(DBEntry entry, MigrationInterface elem) {
LOGGER.info("Revert migration: {} [BEGIN]", elem.getName());
LOGGER.info("Revert migration: {} [ END ]", elem.getName());
}
}

View File

@ -0,0 +1,7 @@
package org.kar.archidata.migration;
public class MigrationException extends Exception {
private static final long serialVersionUID = 20230502L;
}

View File

@ -0,0 +1,25 @@
package org.kar.archidata.migration;
import org.kar.archidata.db.DBEntry;
public interface MigrationInterface {
/**
* Get Name of the migration
* @return Migration name
*/
String getName();
/**
* Migrate the system to a new version.
* @param entry DB interface for the migration.
* @param log Stored data in the BDD for the migration progression.
* @return true if migration is finished.
*/
boolean applyMigration(DBEntry entry, StringBuilder log);
/**
* Remove a migration the system to the previous version.
* @param entry DB interface for the migration.
* @param log Stored data in the BDD for the migration progression.
* @return true if migration is finished.
*/
boolean revertMigration(DBEntry entry, StringBuilder log);
}

View File

@ -0,0 +1,24 @@
package org.kar.archidata.migration;
import org.kar.archidata.annotation.SQLComment;
import org.kar.archidata.annotation.SQLIfNotExists;
import org.kar.archidata.annotation.SQLLimitSize;
import org.kar.archidata.annotation.SQLTableName;
import org.kar.archidata.model.GenericTable;
import com.fasterxml.jackson.annotation.JsonInclude;
@SQLTableName ("KAR_migration")
@SQLIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MigrationModel extends GenericTable{
@SQLComment("Name of the migration")
@SQLLimitSize(256)
public String name;
@SQLComment("index in the migration progression")
public Integer index;
@SQLComment("number of element in the migration")
public Integer count;
@SQLComment("Log generate by the migration")
public String log;
}

View File

@ -0,0 +1,61 @@
package org.kar.archidata.migration;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.db.DBEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MigrationSqlStep implements MigrationInterface{
final static Logger LOGGER = LoggerFactory.getLogger(MigrationSqlStep.class);
private List<String> actions = new ArrayList<>();
@Override
public String getName() {
return getClass().getCanonicalName();
}
@Override
public boolean applyMigration(DBEntry entry, StringBuilder log) {
for (int iii=0; iii<actions.size(); iii++) {
log.append("action [" + iii + "/" + actions.size() + "]\n");
LOGGER.debug(" >>>> SQL ACTION : {}/{}", iii, actions.size());
String action = actions.get(iii);
LOGGER.debug("SQL request: ```{}```", action);
log.append("SQL: " + action + "\n");
try {
SqlWrapper.executeSimpleQuerry(action);
} catch (SQLException ex) {
ex.printStackTrace();
LOGGER.debug("SQL request ERROR: ", ex.getMessage());
log.append("SQL request ERROR: " + ex.getMessage() + "\n");
return false;
} catch (IOException ex) {
ex.printStackTrace();
LOGGER.debug("IO request ERROR: ", ex.getMessage());
log.append("IO request ERROR: " + ex.getMessage() + "\n");
return false;
}
log.append("action [" + iii + "/" + actions.size() + "] ==> DONE\n");
LOGGER.debug(" >>>> SQL ACTION : {}/{} ==> DONE", iii, actions.size());
}
return true;
}
@Override
public boolean revertMigration(DBEntry entry, StringBuilder log) {
return false;
}
public void addAction(String action) {
actions.add(action);
}
public void addClass(Class<?> clazz) throws Exception {
actions.add(SqlWrapper.createTable(clazz));
}
}