2019-05-14 15:52:05 +02:00
|
|
|
package sonia.scm.update;
|
|
|
|
|
|
2019-05-15 13:29:50 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
import sonia.scm.migration.UpdateException;
|
2019-05-14 15:52:05 +02:00
|
|
|
import sonia.scm.migration.UpdateStep;
|
|
|
|
|
import sonia.scm.store.ConfigurationEntryStore;
|
|
|
|
|
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
|
|
|
|
|
|
|
|
|
import javax.inject.Inject;
|
|
|
|
|
import java.util.Comparator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
|
|
import static java.util.stream.Collectors.toList;
|
|
|
|
|
|
|
|
|
|
public class UpdateEngine {
|
|
|
|
|
|
2019-05-15 13:29:50 +02:00
|
|
|
public static final Logger LOG = LoggerFactory.getLogger(UpdateEngine.class);
|
|
|
|
|
|
2019-05-14 15:52:05 +02:00
|
|
|
private static final String STORE_NAME = "executedUpdates";
|
|
|
|
|
|
|
|
|
|
private final List<UpdateStep> steps;
|
|
|
|
|
private final ConfigurationEntryStore<UpdateVersionInfo> store;
|
|
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
|
public UpdateEngine(Set<UpdateStep> steps, ConfigurationEntryStoreFactory storeFactory) {
|
|
|
|
|
this.steps = sortSteps(steps);
|
|
|
|
|
this.store = storeFactory.withType(UpdateVersionInfo.class).withName(STORE_NAME).build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<UpdateStep> sortSteps(Set<UpdateStep> steps) {
|
2019-05-15 13:29:50 +02:00
|
|
|
LOG.trace("sorting available update steps:");
|
|
|
|
|
List<UpdateStep> sortedSteps = steps.stream()
|
2019-06-20 16:12:16 +02:00
|
|
|
.sorted(
|
|
|
|
|
Comparator
|
|
|
|
|
.comparing(UpdateStep::getTargetVersion)
|
|
|
|
|
.thenComparing(this::isCoreUpdateStep)
|
|
|
|
|
.reversed())
|
2019-05-14 15:52:05 +02:00
|
|
|
.collect(toList());
|
2019-05-15 13:29:50 +02:00
|
|
|
sortedSteps.forEach(step -> LOG.trace("{} for version {}", step.getAffectedDataType(), step.getTargetVersion()));
|
|
|
|
|
return sortedSteps;
|
2019-05-14 15:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-20 16:12:16 +02:00
|
|
|
private boolean isCoreUpdateStep(UpdateStep updateStep) {
|
|
|
|
|
return updateStep instanceof CoreUpdateStep;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 15:52:05 +02:00
|
|
|
public void update() {
|
|
|
|
|
steps
|
|
|
|
|
.stream()
|
|
|
|
|
.filter(this::notRunYet)
|
|
|
|
|
.forEach(this::execute);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void execute(UpdateStep updateStep) {
|
2019-05-15 13:29:50 +02:00
|
|
|
try {
|
|
|
|
|
LOG.info("running update step for type {} and version {}",
|
|
|
|
|
updateStep.getAffectedDataType(),
|
|
|
|
|
updateStep.getTargetVersion()
|
|
|
|
|
);
|
|
|
|
|
updateStep.doUpdate();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new UpdateException(
|
|
|
|
|
String.format(
|
2019-07-01 10:57:11 +02:00
|
|
|
"could not execute update for type %s to version %s in %s",
|
2019-05-15 13:29:50 +02:00
|
|
|
updateStep.getAffectedDataType(),
|
|
|
|
|
updateStep.getTargetVersion(),
|
|
|
|
|
updateStep.getClass()),
|
|
|
|
|
e);
|
|
|
|
|
}
|
2019-05-14 15:52:05 +02:00
|
|
|
UpdateVersionInfo newVersionInfo = new UpdateVersionInfo(updateStep.getTargetVersion().getParsedVersion());
|
2019-05-15 13:29:50 +02:00
|
|
|
store.put(updateStep.getAffectedDataType(), newVersionInfo);
|
2019-05-14 15:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean notRunYet(UpdateStep updateStep) {
|
2019-05-15 13:29:50 +02:00
|
|
|
LOG.trace("checking whether to run update step for type {} and version {}",
|
|
|
|
|
updateStep.getAffectedDataType(),
|
|
|
|
|
updateStep.getTargetVersion()
|
|
|
|
|
);
|
|
|
|
|
UpdateVersionInfo updateVersionInfo = store.get(updateStep.getAffectedDataType());
|
2019-05-14 15:52:05 +02:00
|
|
|
if (updateVersionInfo == null) {
|
2019-05-15 13:29:50 +02:00
|
|
|
LOG.trace("no updates for type {} run yet; step will be executed", updateStep.getAffectedDataType());
|
2019-05-14 15:52:05 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-05-15 13:29:50 +02:00
|
|
|
boolean result = updateStep.getTargetVersion().isNewer(updateVersionInfo.getLatestVersion());
|
|
|
|
|
LOG.trace("latest version for type {}: {}; step will be executed: {}",
|
|
|
|
|
updateStep.getAffectedDataType(),
|
|
|
|
|
updateVersionInfo.getLatestVersion(),
|
|
|
|
|
result
|
|
|
|
|
);
|
|
|
|
|
return result;
|
2019-05-14 15:52:05 +02:00
|
|
|
}
|
|
|
|
|
}
|