Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize: check relation of before status and after status when updating global session #4629

Merged
merged 21 commits into from Jun 10, 2022
Merged
54 changes: 54 additions & 0 deletions server/src/main/java/io/seata/server/session/SessionHelper.java
Expand Up @@ -202,13 +202,67 @@ public static void endRollbackFailed(GlobalSession globalSession, boolean retryG
MetricsPublisher.postSessionDoneEvent(globalSession, retryGlobal, false);
}

/**
* is timeout global status timeout
*
* @param status the global session
*/
public static boolean isTimeoutGlobalStatus(GlobalStatus status) {
return status == GlobalStatus.TimeoutRollbacked
|| status == GlobalStatus.TimeoutRollbackFailed
|| status == GlobalStatus.TimeoutRollbacking
|| status == GlobalStatus.TimeoutRollbackRetrying;
}

/**
* is rollback global status timeout
*
* @param status the global session
*/
public static boolean isRollbackGlobalStatus(GlobalStatus status) {
return status == GlobalStatus.Rollbacking
|| status == GlobalStatus.RollbackRetrying
|| status == GlobalStatus.Rollbacked
|| status == GlobalStatus.RollbackFailed
|| status == GlobalStatus.RollbackRetryTimeout;
}

/**
* is commit global status timeout
*
* @param status the global session
*/
public static boolean isCommitGlobalStatus(GlobalStatus status) {
return status == GlobalStatus.Committing
|| status == GlobalStatus.AsyncCommitting
|| status == GlobalStatus.CommitRetrying
|| status == GlobalStatus.Committed
|| status == GlobalStatus.CommitFailed
|| status == GlobalStatus.CommitRetryTimeout;
}

/**
* check the relation of before status and after status
*
* @param before the global session
* @param after the global session
*/
public static boolean validateUpdateStatus(GlobalStatus before, GlobalStatus after) {
if (isTimeoutGlobalStatus(before) && isCommitGlobalStatus(after)) {
return false;
}
if (isCommitGlobalStatus(before) && isTimeoutGlobalStatus(after)) {
return false;
}
if (isRollbackGlobalStatus(before) && isCommitGlobalStatus(after)) {
return false;
}
if (isCommitGlobalStatus(before) && isRollbackGlobalStatus(after)) {
return false;
}
return true;
}

/**
* Foreach global sessions.
*
Expand Down
Expand Up @@ -28,6 +28,7 @@
import java.util.stream.Collectors;
import io.seata.config.Configuration;
import io.seata.config.ConfigurationFactory;
import io.seata.server.session.SessionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -326,6 +327,10 @@ private boolean updateGlobalTransactionDO(GlobalTransactionDO globalTransactionD
jedis.unwatch();
return true;
}
if (SessionHelper.validateUpdateStatus(GlobalStatus.get(Integer.parseInt(previousStatus)),
GlobalStatus.get(globalTransactionDO.getStatus()))) {
throw new StoreException("illegal changing of global status, update global transaction failed.");
Bughue marked this conversation as resolved.
Show resolved Hide resolved
}
Bughue marked this conversation as resolved.
Show resolved Hide resolved

String previousGmtModified = statusAndGmtModified.get(1);
Transaction multi = jedis.multi();
Expand Down