package io.smartcat.migration;
import io.smartcat.migration.exceptions.MigrationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.Session;
/**
* Migration engine wraps Migrator and provides DSL like API.
*
*/
public class MigrationEngine {
private static final Logger LOGGER = LoggerFactory.getLogger(MigrationEngine.class);
private MigrationEngine() {
}
/**
* Create migrator out of session fully prepared for doing migration of resources.
* @param session Datastax driver session object
* @return migrator instance with versioner and session which can migrate resources
*/
public static Migrator withSession(final Session session) {
return new Migrator(session);
}
/**
* Migrator handles migrations and errors.
*/
public static class Migrator {
private final Session session;
private final CassandraVersioner versioner;
/**
* Create new Migrator with active Cassandra session.
* @param session Active Cassandra session
*/
public Migrator(final Session session) {
this.session = session;
this.versioner = new CassandraVersioner(session);
}
/**
* Method that executes all migration from migration resources that are higher version than db version. If
* migration fails, method will exit.
*
* @param resources Collection of migrations to be executed
* @return Success of migration
*/
public boolean migrate(final MigrationResources resources) {
LOGGER.debug("Start migration");
for (final Migration migration : resources.getMigrations()) {
final MigrationType type = migration.getType();
final int migrationVersion = migration.getVersion();
final int version = versioner.getCurrentVersion(type);
LOGGER.info("Db is version {} for type {}.", version, type.name());
LOGGER.info("Compare {} migration version {} with description {}", type.name(), migrationVersion,
migration.getDescription());
if (migrationVersion <= version) {
LOGGER.warn("Skipping migration [{}] with version {} since db is on higher version {}.",
migration.getDescription(), migrationVersion, version);
continue;
}
migration.setSession(session);
final long start = System.currentTimeMillis();
LOGGER.info("Start executing migration to version {}.", migrationVersion);
try {
migration.execute();
} catch (final MigrationException e) {
LOGGER.error("Failed to execute migration version {}, exception {}!", migrationVersion,
e.getMessage());
LOGGER.debug("Exception stack trace: {}", e);
return false;
}
final long end = System.currentTimeMillis();
final long seconds = (end - start) / 1000;
LOGGER.info("Migration [{}] to version {} finished in {} seconds.", migration.getDescription(),
migrationVersion, seconds);
if (!versioner.updateVersion(migration)) {
LOGGER.error("Db schema update failed for migration version {}!", migrationVersion);
return false;
}
}
return true;
}
}
}