Skip to content

Commit

Permalink
[#12048] Patch Usage Statistics Migration (#12889)
Browse files Browse the repository at this point in the history
* Patch Usage Statistics

* Add fix

* Remove static

* Fix bug for createdAt

---------

Co-authored-by: FergusMok <[email protected]>
  • Loading branch information
ziqing26 and FergusMok authored Mar 18, 2024
1 parent 868982f commit 2eedf1d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ public DataMigrationEntitiesBaseScriptSql() {
*/
protected abstract boolean isPreview();

/**
* Sets the criterias used in {@link #isMigrationNeeded(E entity)} on whether migration is needed.
* Ran during initialization.
*/
protected abstract void setMigrationCriteria();

/**
* Checks whether data migration is needed.
*
Expand Down Expand Up @@ -181,6 +187,7 @@ private void migrateWithTrx(Key<E> entityKey) {
protected void doOperation() {
log("Running " + getClass().getSimpleName() + "...");
log("Preview: " + isPreview());
setMigrationCriteria();

Cursor cursor = readPositionOfCursorFromFile().orElse(null);
if (cursor == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ protected boolean isPreview() {
return false;
}

/*
* Sets the migration criteria used in isMigrationNeeded.
*/
@Override
protected void setMigrationCriteria() {
// No migration criteria currently needed.
}

/**
* Always returns true, as the migration is needed for all entities from
* Datastore to CloudSQL.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ protected boolean isPreview() {
return false;
}

/*
* Sets the migration criteria used in isMigrationNeeded.
*/
@Override
protected void setMigrationCriteria() {
// No migration criteria currently needed.
}

@Override
protected boolean isMigrationNeeded(Notification entity) {
HibernateUtil.beginTransaction();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package teammates.client.scripts.sql;

// CHECKSTYLE.OFF:ImportOrder
import java.time.Instant;
import java.util.UUID;

import com.googlecode.objectify.cmd.Query;

import teammates.common.util.HibernateUtil;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import teammates.storage.sqlentity.UsageStatistics;
// CHECKSTYLE.ON:ImportOrder

/**
* Data migration class for usage statistics.
*/
@SuppressWarnings("PMD")
public class DataMigrationForUsageStatisticsSql extends
DataMigrationEntitiesBaseScriptSql<
teammates.storage.entity.UsageStatistics,
UsageStatistics> {
DataMigrationEntitiesBaseScriptSql<teammates.storage.entity.UsageStatistics, UsageStatistics> {

// Runs the migration only for newly-created SQL entities since the initial migration.
private static final boolean IS_PATCHING_MIGRATION = true;

private Instant patchingStartTime;

public static void main(String[] args) {
new DataMigrationForUsageStatisticsSql().doOperationRemotely();
Expand All @@ -33,11 +45,43 @@ protected boolean isPreview() {
}

/**
* Always returns true, as the migration is needed for all entities from Datastore to CloudSQL .
* Queries for the latest SQL entity created, so that patching will only migrate newly created Datastore entities.
*/
@Override
protected void setMigrationCriteria() {
if (!IS_PATCHING_MIGRATION) {
return;
}

HibernateUtil.beginTransaction();
CriteriaBuilder cb = HibernateUtil.getCriteriaBuilder();
CriteriaQuery<Instant> cq = cb.createQuery(Instant.class);
Root<UsageStatistics> root = cq.from(UsageStatistics.class);
cq.select(cb.greatest(root.<Instant>get("startTime")));

// If no entity found, Hibernate will return null for Instant instead of throwing NoResultException.
patchingStartTime = HibernateUtil.createQuery(cq).getSingleResult();
HibernateUtil.commitTransaction();

if (patchingStartTime == null) {
System.out.println(this.getClass().getSimpleName() + " Patching enabled, but unable to find SQL entity");
System.exit(1);
}

System.out.println(this.getClass().getSimpleName() + " Patching migration, with time " + patchingStartTime);
}

/**
* Always returns true, as the migration is needed for all entities from
* Datastore to CloudSQL.
*/
@SuppressWarnings("unused")
@Override
protected boolean isMigrationNeeded(teammates.storage.entity.UsageStatistics entity) {
return true;
if (patchingStartTime == null) {
return true;
}
return entity.getStartTime().isAfter(patchingStartTime);
}

@Override
Expand Down

0 comments on commit 2eedf1d

Please sign in to comment.