if (!ctx.isInTxScope()) {
stateTransferLock.acquireSharedTopologyLock();
try {
// We only retry non-tx write commands
if (command instanceof WriteCommand) {
WriteCommand writeCommand = (WriteCommand) command;
// Can't perform the check during preload or if the cache isn't clustered
boolean isSync = (cacheConfiguration.clustering().cacheMode().isSynchronous() &&
!command.hasFlag(Flag.FORCE_ASYNCHRONOUS)) || command.hasFlag(Flag.FORCE_SYNCHRONOUS);
if (writeCommand.isSuccessful() && stateConsumer != null &&
stateConsumer.getCacheTopology() != null) {
int commandTopologyId = command.getTopologyId();
int currentTopologyId = stateConsumer.getCacheTopology().getTopologyId();
// TotalOrderStateTransferInterceptor doesn't set the topology id for PFERs.
if (isSync && currentTopologyId != commandTopologyId && commandTopologyId != -1) {
// If we were the originator of a data command which we didn't own the key at the time means it
// was already committed, so there is no need to throw the OutdatedTopologyException
// This will happen if we submit a command to the primary owner and it responds and then a topology
// change happens before we get here
if (!ctx.isOriginLocal() || !(command instanceof DataCommand) ||
ctx.hasLockedKey(((DataCommand)command).getKey())) {
if (trace) log.tracef("Cache topology changed while the command was executing: expected %d, got %d",
commandTopologyId, currentTopologyId);
// This shouldn't be necessary, as we'll have a fresh command instance when retrying
writeCommand.setValueMatcher(writeCommand.getValueMatcher().matcherForRetry());
throw new OutdatedTopologyException("Cache topology changed while the command was executing: expected " +
commandTopologyId + ", got " + currentTopologyId);
}
}
}