Add documentation

This commit is contained in:
René Pfeuffer
2019-05-20 16:34:22 +02:00
parent ca36a0a5f4
commit bacfde7cab

View File

@@ -3,11 +3,80 @@ package sonia.scm.migration;
import sonia.scm.plugin.ExtensionPoint;
import sonia.scm.version.Version;
/**
* This is the main interface for data migration/update. Using this interface, SCM-Manager provides the possibility to
* change data structures between versions for a given type of data.
* <p>The data type can be an arbitrary string, but it is considered a best practice to use a qualified name, for
* example
* <ul>
* <li><code>com.example.myPlugin.configuration</code></li> for data in plugins, or
* <li><code>com.cloudogu.scm.repository</code></li> for core data structures.
* </ul>
* </p>
* <p>The version is unrelated to other versions and therefore can be chosen freely, so that a data type can be updated
* without in various ways independent of other data types or the official version of the plugin or the core.
* A coordination between different data types and their versions is only necessary, when update steps of different data
* types rely on each other. If a update step of data type <i>A</i> has to run <b>before</b> another step for data type
* <i>B</i>, the version number of the second step has to be greater in regards to {@link Version#compareTo(Version)}.
* </p>
* <p>The algorithm looks something like this:<br>
* Whenever the SCM-Manager starts,
* <ul>
* <li>it creates a so called <i>bootstrap guice context</i>, that contains
* <ul>
* <li>a {@link sonia.scm.security.KeyGenerator},</li>
* <li>the {@link sonia.scm.repository.RepositoryLocationResolver},</li>
* <li>the {@link sonia.scm.io.FileSystem},</li>
* <li>the {@link sonia.scm.security.CipherHandler},</li>
* <li>a {@link sonia.scm.store.ConfigurationStoreFactory},</li>
* <li>a {@link sonia.scm.store.ConfigurationEntryStoreFactory},</li>
* <li>a {@link sonia.scm.store.DataStoreFactory},</li>
* <li>a {@link sonia.scm.store.BlobStoreFactory}, and</li>
* <li>the {@link sonia.scm.plugin.PluginLoader}.</li>
* </ul>
* Mind, that there are no DAOs, Managers or the like available at this time!
* </li>
* <li>It then checks whether there are instances of this interface that have not run before, that is either
* <ul>
* <li>their version number given by {@link #getTargetVersion()} is bigger than the last recorded target version of an
* executed update step for the data type given by {@link #getAffectedDataType()}, or
* </li>
* <li>there is no version number known for the given data type.
* </li>
* </ul>
* These are the <i>relevant</i> update steps.
* </li>
* <li>These relevant update steps are then sorted ascending by their target version given by
* {@link #getTargetVersion()}.
* </li>
* <li>Finally, these sorted steps are executed one after another calling {@link #doUpdate()} of each step, updating the
* version for the data type accordingly.
* </li>
* <li>If all works well, SCM-Manager then creates the runtime guice context by loading all further modules.</li>
* <li>If any of the update steps fails, the whole process is interrupted and SCM-Manager will not start up and will
* not record the version number of this update step.
* </li>
* </ul>
* </p>
*/
@ExtensionPoint
public interface UpdateStep {
/**
* Implement this to update the data to the new version. If any {@link Exception} is thrown, SCM-Manager will not
* start up.
*/
void doUpdate() throws Exception;
/**
* Declares the new version of the data type given by {@link #getAffectedDataType()}. A update step will only be
* executed, when this version is bigger than the last recorded version for its data type according to
* {@link Version#compareTo(Version)}
*/
Version getTargetVersion();
/**
* Declares the data type this update step will take care of. This should be a qualified name, like
* <code>com.example.myPlugin.configuration</code>.
*/
String getAffectedDataType();
}