in server/src/main/java/org/apache/seata/server/session/SessionHolder.java [168:280]
public static void reload(Collection<GlobalSession> allSessions, SessionMode storeMode, boolean acquireLock) {
if ((SessionMode.FILE == storeMode || SessionMode.RAFT == storeMode)
&& CollectionUtils.isNotEmpty(allSessions)) {
long currentTimeMillis = System.currentTimeMillis();
for (GlobalSession globalSession : allSessions) {
GlobalStatus globalStatus = globalSession.getStatus();
switch (globalStatus) {
case TimeoutRollbacked:
case Rollbacked:
try {
SessionHelper.endRollbacked(globalSession, true);
} catch (TransactionException e) {
LOGGER.error("Could not handle the global session, xid: {},error: {}",
globalSession.getXid(), e.getMessage());
}
break;
case Committed:
try {
SessionHelper.endCommitted(globalSession, true);
} catch (TransactionException e) {
LOGGER.error("Could not handle the global session, xid: {},error: {}",
globalSession.getXid(), e.getMessage());
}
break;
case Finished:
case UnKnown:
case CommitFailed:
case RollbackFailed:
case TimeoutRollbackFailed:
removeInErrorState(globalSession);
break;
case AsyncCommitting:
case Committing:
case CommitRetrying:
if (Objects.equals(SessionMode.RAFT, storeMode)) {
// When a state change occurs, re-electing the leader may result in the lock not being unlocked yet
// so a COMMIT unlock operation needs to be performed at the time of re-election
try {
globalSession.clean();
} catch (TransactionException e) {
throw new RuntimeException(e);
}
}
case StopCommitOrCommitRetry:
case StopRollbackOrRollbackRetry:
case Deleting:
break;
default: {
if (acquireLock) {
lockBranchSessions(globalSession.getSortedBranches());
if (GlobalStatus.Rollbacking.equals(globalSession.getStatus())
|| GlobalStatus.TimeoutRollbacking.equals(globalSession.getStatus())) {
globalSession.getBranchSessions().parallelStream()
.forEach(branchSession -> branchSession.setLockStatus(LockStatus.Rollbacking));
}
}
switch (globalStatus) {
case Rollbacking:
case RollbackRetrying:
case TimeoutRollbacking:
case TimeoutRollbackRetrying:
break;
case Begin:
if (Objects.equals(storeMode, SessionMode.RAFT)) {
// Avoid rolling back the global session created after becoming the leader.
if (globalSession.getBeginTime() < currentTimeMillis) {
try {
globalSession.changeGlobalStatus(GlobalStatus.RollbackRetrying);
LOGGER.info("change global status: {}, xid: {}", globalSession.getStatus(),
globalSession.getXid());
} catch (TransactionException e) {
LOGGER.error("change global status fail: {}", e.getMessage(), e);
}
} else {
globalSession.setActive(true);
}
} else {
globalSession.setActive(true);
}
break;
default:
LOGGER.error("Could not handle the global session, xid: {}", globalSession.getXid());
throw new ShouldNeverHappenException("NOT properly handled " + globalStatus);
}
break;
}
}
}
} else {
// Redis, db and so on
CompletableFuture.runAsync(() -> {
SessionCondition searchCondition = new SessionCondition(GlobalStatus.UnKnown, GlobalStatus.Committed,
GlobalStatus.Rollbacked, GlobalStatus.TimeoutRollbacked, GlobalStatus.Finished);
searchCondition.setLazyLoadBranch(true);
long now = System.currentTimeMillis();
List<GlobalSession> errorStatusGlobalSessions = ROOT_SESSION_MANAGER.findGlobalSessions(searchCondition);
while (!CollectionUtils.isEmpty(errorStatusGlobalSessions)) {
for (GlobalSession errorStatusGlobalSession : errorStatusGlobalSessions) {
if (errorStatusGlobalSession.getBeginTime() >= now) {
// Exit when the global transaction begin after the instance started
return;
}
removeInErrorState(errorStatusGlobalSession);
}
// Load the next part
errorStatusGlobalSessions = ROOT_SESSION_MANAGER.findGlobalSessions(searchCondition);
}
});
}
}