Skip to content

Commit

Permalink
#30315 Improving upgrade task to not fail if it is executed multiple …
Browse files Browse the repository at this point in the history
…times.
  • Loading branch information
jgambarios committed Oct 10, 2024
1 parent 98a33f7 commit 2b3df6a
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.dotmarketing.startup.runonce;

import com.dotmarketing.common.db.DotConnect;
import com.dotmarketing.common.db.DotDatabaseMetaData;
import com.dotmarketing.db.DbConnectionFactory;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.startup.StartupTask;
import com.dotmarketing.util.Logger;
import java.sql.Connection;
import java.sql.SQLException;

/**
* Upgrade task to create the necessary tables and indexes for the Postgres Job Queue
Expand All @@ -26,13 +31,32 @@ public boolean forceRun() {
@Override
public void executeUpgrade() throws DotDataException, DotRuntimeException {

// Create the job queue tables
createJobQueueTable();
createJobTable();
createJobHistoryTable();
final Connection connection = DbConnectionFactory.getConnection();
final DotDatabaseMetaData databaseMetaData = new DotDatabaseMetaData();

// Create the indexes
createIndexes();
try {

// job_queue table
if (!databaseMetaData.tableExists(connection, "job_queue")) {
createJobQueueTable();
createJobQueueTableIndexes();
}

// job table
if (!databaseMetaData.tableExists(connection, "job")) {
createJobTable();
createJobTableIndexes();
}

// job_history table
if (!databaseMetaData.tableExists(connection, "job_history")) {
createJobHistoryTable();
createJobHistoryTableIndexes();
}
} catch (SQLException e) {
Logger.error("Error creating job queue tables", e);
throw new DotRuntimeException(e.getMessage(), e);
}
}

/**
Expand All @@ -55,6 +79,22 @@ private void createJobQueueTable() throws DotDataException {
}
}

/**
* Creates the necessary indexes for the job_queue table.
*
* @throws DotDataException if an error occurs while creating the indexes.
*/
private void createJobQueueTableIndexes() throws DotDataException {
try {
new DotConnect().executeStatement(
"CREATE INDEX idx_job_queue_status ON job_queue (state)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_queue_priority_created_at ON job_queue (priority DESC, created_at ASC)");
} catch (Exception ex) {
throw new DotDataException(ex.getMessage(), ex);
}
}

/**
* Creates the job table.
*
Expand Down Expand Up @@ -82,6 +122,25 @@ private void createJobTable() throws DotDataException {
}
}

/**
* Creates the necessary indexes for the job table.
*
* @throws DotDataException if an error occurs while creating the indexes.
*/
private void createJobTableIndexes() throws DotDataException {
try {
new DotConnect().executeStatement(
"CREATE INDEX idx_job_parameters ON job USING GIN (parameters)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_result ON job USING GIN (result)");
new DotConnect().executeStatement("CREATE INDEX idx_job_status ON job (state)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_created_at ON job (created_at)");
} catch (Exception ex) {
throw new DotDataException(ex.getMessage(), ex);
}
}

/**
* Creates the job_history table.
*
Expand All @@ -105,23 +164,12 @@ private void createJobHistoryTable() throws DotDataException {
}

/**
* Creates the necessary indexes for the job queue tables.
* Creates the necessary indexes for the job_history table.
*
* @throws DotDataException if an error occurs while creating the indexes.
*/
private void createIndexes() throws DotDataException {
private void createJobHistoryTableIndexes() throws DotDataException {
try {
new DotConnect().executeStatement(
"CREATE INDEX idx_job_queue_status ON job_queue (state)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_queue_priority_created_at ON job_queue (priority DESC, created_at ASC)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_parameters ON job USING GIN (parameters)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_result ON job USING GIN (result)");
new DotConnect().executeStatement("CREATE INDEX idx_job_status ON job (state)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_created_at ON job (created_at)");
new DotConnect().executeStatement(
"CREATE INDEX idx_job_history_job_id ON job_history (job_id)");
new DotConnect().executeStatement(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.util.Logger;
import java.sql.Connection;
import java.sql.SQLException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

Expand All @@ -36,13 +38,12 @@ public static void setup() throws Exception {

// Setting web app environment
IntegrationTestInitService.getInstance().init();
LocalTransaction.wrap(Task241009CreatePostgresJobQueueTablesTest::dropTablesIfExist);
}

/**
* Drops the job queue tables if they exist.
*/
private static void dropTablesIfExist() {
private void dropTablesIfExist() {

try {

Expand Down Expand Up @@ -79,6 +80,75 @@ private static void dropTablesIfExist() {
@Test
public void executeTaskUpgrade() throws SQLException, DotDataException, DotSecurityException {

try {
// First, ensure the tables do not exist
LocalTransaction.wrap(() -> {
try {
dropTablesIfExist();
} catch (Exception e) {
throw new DotRuntimeException(e);
}
});

// Running the upgrade task and validating the tables were created
executeUpgradeAndValidate();
} finally {
DbConnectionFactory.closeSilently();
}
}

/**
* Method to test {@link Task241009CreatePostgresJobQueueTables#executeUpgrade()} and
* {@link Task241009CreatePostgresJobQueueTables#forceRun()}.
* <p>
* Given Scenario: The job queue tables do not exist, and the upgrade task is run twice.
* <p>
* Expected Result: The job queue tables will be created after running the upgrade task the
* first time and should not fail when running the upgrade task again.
*
* @throws SQLException if a SQL error occurs.
* @throws DotDataException if a data access error occurs.
* @throws DotSecurityException if a security error occurs.
*/
@Test
public void executeTaskUpgradeTwice()
throws SQLException, DotDataException, DotSecurityException {

try {
// First, ensure the tables do not exist
LocalTransaction.wrap(() -> {
try {
dropTablesIfExist();
} catch (Exception e) {
throw new DotRuntimeException(e);
}
});

// Run the upgrade task for the first time, it should create the tables
executeUpgradeAndValidate();

// Run the upgrade task again, should not fail
LocalTransaction.wrap(() -> {
try {
final var task = new Task241009CreatePostgresJobQueueTables();
task.executeUpgrade();
} catch (Exception e) {
final var message = "The upgrade task should not fail when the tables already exist";
Logger.error(message, e);
Assert.fail(message);
}
});
} finally {
DbConnectionFactory.closeSilently();
}
}

/**
* Executes the upgrade task and validates the job queue tables were created.
*/
private static void executeUpgradeAndValidate()
throws SQLException, DotDataException, DotSecurityException {

final var task = new Task241009CreatePostgresJobQueueTables();
final Connection connection = DbConnectionFactory.getConnection();
final DotDatabaseMetaData databaseMetaData = new DotDatabaseMetaData();
Expand All @@ -102,4 +172,5 @@ public void executeTaskUpgrade() throws SQLException, DotDataException, DotSecur
assertTrue(databaseMetaData.tableExists(connection, "job"));
assertTrue(databaseMetaData.tableExists(connection, "job_history"));
}

}

0 comments on commit 2b3df6a

Please sign in to comment.