Skip to content

Commit

Permalink
Deployment ID enhancements and execution property (#5653)
Browse files Browse the repository at this point in the history
This PR is created in response to challenges encountered in the creation development of #5598.

The purpose of this PR is to create a deployment ID that does have to be changed/generated multiple times and is available early on in the execution timeline.

This will allow the implementation of an execution property as setup in #5598 to be created for the deployment ID.

However, the deployment ID was generated later in the process to be a time-based number that was obtained after a database lock was obtained to guarantee uniqueness. This PR aims to change the deployment ID from a time-based number to a UUIDv4 to ensure uniqueness. The UUID (36 characters) does not fit in the existing databasechangelog.deployment_id column, so the column is updated in this PR to be a length of 36 (and is updated for both creation of the table and update of existing tables).

For a full discussion of why this came to be, the discussion on #5598 can be referenced.

---------

Co-authored-by: Jason Lyle <jason.lyle@oracle.com>
Co-authored-by: Daniel Mallorga <dmallorga@liquibase.com>
  • Loading branch information
3 people authored Dec 16, 2024
1 parent beb8acb commit 78b17ce
Show file tree
Hide file tree
Showing 29 changed files with 185 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class SetupChangeLogSync extends TestSetup {

final ChangeLogHistoryService changeLogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database)
changeLogService.init()
changeLogService.generateDeploymentId()

changeLogService.reset()
CompositeResourceAccessor fileOpener = new CompositeResourceAccessor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class SetupChangelogHistory extends TestSetup {

final ChangeLogHistoryService changeLogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database)
changeLogService.init()
changeLogService.generateDeploymentId()

List<RanChangeSet> toRemoveList = new ArrayList<>()
for (RanChangeSet ranChangeSet : changeLogService.getRanChangeSets()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class SetupDatabaseStructure extends TestSetup {

final ChangeLogHistoryService changeLogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database)
changeLogService.init()
changeLogService.generateDeploymentId()

changeLogService.reset()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class SetupRollbackCount extends TestSetup {

final ChangeLogHistoryService changeLogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database)
changeLogService.init()
changeLogService.generateDeploymentId()

changeLogService.reset()
CompositeResourceAccessor fileOpener = new CompositeResourceAccessor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class SetupRunChangelog extends TestSetup {

final ChangeLogHistoryService changeLogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database)
changeLogService.init()
changeLogService.generateDeploymentId()

changeLogService.reset()
ResourceAccessor resourceAccessor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class UpdateIntegrationTest extends Specification {
given:
CommandUtil.runDropAll(testDatabase)
CommandUtil.runUpdate(testDatabase,"src/test/resources/changelogs/h2/update/execution-parameter.xml")
String expectedDeploymentId = Scope.getCurrentScope().getDeploymentId();
String sql = "select * from parameter_value_tests order by id"

when:
Expand All @@ -39,13 +40,13 @@ class UpdateIntegrationTest extends Specification {

then:
assert output == """Output of select * from parameter_value_tests order by id:
ID | CHANGELOG_FILE | CHANGESET_ID | CHANGESET_AUTHOR |
1 | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.1 | jlyle |
2 | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.2 | not_jlyle |
3 | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.3 | jlyle |
4 | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.1 | jlyle |
5 | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.2 | not_jlyle |
6 | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.3 | jlyle |
ID | DEPLOYMENT_ID | CHANGELOG_FILE | CHANGESET_ID | CHANGESET_AUTHOR |
1 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.1 | jlyle |
2 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.2 | not_jlyle |
3 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/1.xml | 1.3 | jlyle |
4 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.1 | jlyle |
5 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.2 | not_jlyle |
6 | """ + expectedDeploymentId + """ | src/test/resources/changelogs/h2/update/execution-parameter/2.xml | 2.3 | jlyle |
"""

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<changeSet id="1" author="jlyle">
<createTable tableName="parameter_value_tests">
<column name="id" type="number" autoIncrement="true" />
<column name="deployment_id" type="varchar2(36)" />
<column name="changelog_file" type="varchar(4000)" />
<column name="changeset_id" type="varchar(4000)" />
<column name="changeset_author" type="varchar(4000)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<changeSet author="jlyle" id="1.1">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand All @@ -15,6 +16,7 @@

<changeSet author="not_jlyle" id="1.2">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand All @@ -23,6 +25,7 @@

<changeSet author="jlyle" id="1.3">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<changeSet author="jlyle" id="2.1">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand All @@ -15,6 +16,7 @@

<changeSet author="not_jlyle" id="2.2">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand All @@ -23,6 +25,7 @@

<changeSet author="jlyle" id="2.3">
<insert tableName="parameter_value_tests">
<column name="deployment_id" value="${LIQUIBASE_EXECUTION_DEPLOYMENT_ID}" />
<column name="changelog_file" value="${LIQUIBASE_EXECUTION_CHANGELOG_FILE}" />
<column name="changeset_id" value="${LIQUIBASE_EXECUTION_CHANGESET_ID}" />
<column name="changeset_author" value="${LIQUIBASE_EXECUTION_CHANGESET_AUTHOR}" />
Expand Down
4 changes: 4 additions & 0 deletions liquibase-standard/src/main/java/liquibase/Scope.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public enum Attr {
executeMode,
lineSeparator,
serviceLocator,
deploymentId,

/**
* @deprecated use {@link GlobalConfiguration#FILE_ENCODING}
Expand Down Expand Up @@ -121,6 +122,7 @@ public static Scope getCurrentScope() {

rootScope.values.put(Attr.serviceLocator.name(), serviceLocator);
rootScope.values.put(Attr.osgiPlatform.name(), ContainerChecker.isOsgiPlatform());
rootScope.values.put(Attr.deploymentId.name(), UUID.randomUUID().toString());
}
return scopeManager.get().getCurrentScope();
}
Expand Down Expand Up @@ -368,6 +370,8 @@ public Database getDatabase() {
return get(Attr.database, Database.class);
}

public String getDeploymentId() { return get(Attr.deploymentId, String.class); }

public ClassLoader getClassLoader() {
return get(Attr.classLoader, Thread.currentThread().getContextClassLoader());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
package liquibase.changelog;

import liquibase.ChecksumVersion;
import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Scope;
import liquibase.*;
import liquibase.changelog.filter.ContextChangeSetFilter;
import liquibase.changelog.filter.DbmsChangeSetFilter;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.exception.DatabaseHistoryException;
import liquibase.executor.ExecutorService;
import liquibase.resource.ResourceAccessor;
import liquibase.statement.core.UpdateChangeSetChecksumStatement;
import lombok.Getter;

import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public abstract class AbstractChangeLogHistoryService implements ChangeLogHistoryService {

@Getter
private Database database;
private String deploymentId;

@Override
public void setDatabase(Database database) {
Expand Down Expand Up @@ -126,26 +124,26 @@ public void replaceChecksum(ChangeSet changeSet) throws DatabaseException {
reset();
}

/**
* @deprecated use {@link Scope#getDeploymentId()}
*/
@Override
public String getDeploymentId() {
return this.deploymentId;
}
@Deprecated
public String getDeploymentId() { return Scope.getCurrentScope().getDeploymentId(); }

/**
* @deprecated This is now handled automatically by the root scope
*/
@Override
public void resetDeploymentId() {
this.deploymentId = null;
}
@Deprecated
public void resetDeploymentId() {}

/**
* @deprecated This is now handled automatically by the root scope
*/
@Override
public void generateDeploymentId() {
if (this.deploymentId == null) {
long time = (new Date()).getTime();
String dateString = String.valueOf(time);
DecimalFormat decimalFormat = new DecimalFormat("0000000000");
this.deploymentId = dateString.length() > 9 ? dateString.substring(dateString.length() - 10) :
decimalFormat.format(time);
}
}
@Deprecated
public void generateDeploymentId() {}


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Scope;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.exception.DatabaseHistoryException;
Expand Down Expand Up @@ -67,10 +68,22 @@ default List<RanChangeSet> getRanChangeSets(boolean allowChecksumsUpgrade) throw

void destroy() throws DatabaseException;

/**
* @deprecated use {@link Scope#getDeploymentId()}
*/
@Deprecated
String getDeploymentId();

/**
* @deprecated This is now handled automatically by the root scope
*/
@Deprecated
void resetDeploymentId();

/**
* @deprecated This is now handled automatically by the root scope
*/
@Deprecated
void generateDeploymentId();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public class ChangeLogParameters {
private LabelExpression filterLabels;

private enum LiquibaseExecutionParameter {
LIQUIBASE_EXECUTION_DEPLOYMENT_ID {
@Override
public String getValue(DatabaseChangeLog changeLog) {
return Scope.getCurrentScope().getDeploymentId();
}
},
LIQUIBASE_EXECUTION_CHANGELOG_FILE {
@Override
public String getValue(DatabaseChangeLog changeLog) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package liquibase.changelog;

import liquibase.ContextExpression;
import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Labels;
import liquibase.*;
import liquibase.change.CheckSum;
import liquibase.database.Database;
import liquibase.database.core.MockDatabase;
Expand Down Expand Up @@ -119,17 +116,29 @@ public void destroy() throws DatabaseException {

}

/**
* @deprecated use {@link Scope#getDeploymentId()}
*/
@Override
@Deprecated
public String getDeploymentId() {
return null;
}

/**
* @deprecated This is now handled automatically by the root scope
*/
@Override
@Deprecated
public void resetDeploymentId() {

}

/**
* @deprecated This is now handled automatically by the root scope
*/
@Override
@Deprecated
public void generateDeploymentId() {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ protected void appendChangeSet(ChangeSet changeSet, ChangeSet.ExecType execType)
newLine[Columns.CONTEXTS.ordinal()] = (changeSet.getContextFilter() == null) ? null : changeSet.getContextFilter().toString();
newLine[Columns.LABELS.ordinal()] = (changeSet.getLabels() == null) ? null : changeSet.getLabels().toString();

newLine[Columns.DEPLOYMENT_ID.ordinal()] = getDeploymentId();
newLine[Columns.DEPLOYMENT_ID.ordinal()] = Scope.getCurrentScope().getDeploymentId();

csvWriter.writeNext(newLine);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public void init() throws DatabaseException {
Integer columnSize = type.getColumnSize();
checksumNotRightSize = (columnSize != null) && (columnSize < 35);
} else {
liquibaseColumnNotRightSize = false;
checksumNotRightSize = false;
}
}
boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null;
Expand Down Expand Up @@ -234,15 +234,34 @@ public void init() throws DatabaseException {
getLabelsSize() + ")", null));
}

boolean deploymentIdColumnNotRightSize = false;
if (!hasDeploymentIdColumn) {
executor.comment("Adding missing databasechangelog.deployment_id column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "DEPLOYMENT_ID", "VARCHAR(10)", null));
getDatabaseChangeLogTableName(), "DEPLOYMENT_ID", charTypeName + "(36)", null));
if (database instanceof DB2Database) {
statementsToExecute.add(new ReorganizeTableStatement(getLiquibaseCatalogName(),
getLiquibaseSchemaName(), getDatabaseChangeLogTableName()));
}
}
else {
if (!(this.getDatabase() instanceof SQLiteDatabase)) {
DataType type = changeLogTable.getColumn("DEPLOYMENT_ID").getType();
if (type.getTypeName().toLowerCase().startsWith("varchar") || type.getTypeName().toLowerCase().startsWith("character varying")) {
Integer columnSize = type.getColumnSize();
deploymentIdColumnNotRightSize = (columnSize != null) && (columnSize < 36);
} else {
deploymentIdColumnNotRightSize = false;
}
}
}

if (deploymentIdColumnNotRightSize) {
executor.comment("Modifying size of databasechangelog.deployment_id column");

statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "DEPLOYMENT_ID", charTypeName + "(36)"));
}

SqlStatement databaseChangeLogStatement = new SelectFromDatabaseChangeLogStatement(
new SelectFromDatabaseChangeLogStatement.ByCheckSumNotNullAndNotLike(ChecksumVersion.latest().getVersion()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private void preRunMdc(ChangeSet changeSet) {
private void postRunMdc(ChangeSet changeSet) {
try {
ChangeLogHistoryServiceFactory instance = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class);
String deploymentId = instance.getChangeLogService(database).getDeploymentId();
String deploymentId = Scope.getCurrentScope().getDeploymentId();
Scope.getCurrentScope().addMdcValue(MdcKey.DEPLOYMENT_ID, deploymentId);
} catch (Exception e) {
Scope.getCurrentScope().getLog(getClass()).fine("Failed to retrieve deployment ID for MDC", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,7 @@ protected void fireRan(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog,

private void addAttributesForMdc(ChangeSet changeSet, ExecType execType) {
changeSet.setAttribute("updateExecType", execType);
ChangeLogHistoryService changelogService = Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database);
String deploymentId = changelogService.getDeploymentId();
changeSet.setAttribute("deploymentId", deploymentId);
changeSet.setAttribute("deploymentId", Scope.getCurrentScope().getDeploymentId());
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ protected void futureRollbackSQL(Integer count, String tag, Contexts contexts, L
lockService.waitForLock();

try {
Scope.getCurrentScope().getSingleton(ChangeLogHistoryServiceFactory.class).getChangeLogService(database).generateDeploymentId();

changeLog.validate(database, contexts, labelExpression);

ChangeLogIterator logIterator;
Expand Down
Loading

0 comments on commit 78b17ce

Please sign in to comment.