package com.zillabyte.motherbrain.flow.error.strategies; import java.io.Serializable; import java.util.Set; import org.apache.log4j.Logger; import com.zillabyte.motherbrain.flow.FlowInstanceSetBuilder; import com.zillabyte.motherbrain.utils.Utils; public final class ForgivingFlowErrorStrategy implements FlowErrorStrategy, Serializable { private static final long serialVersionUID = -4153717009098010433L; private static Logger _log = Utils.getLogger(ForgivingFlowErrorStrategy.class); /**** * @param setBuilder * @return T if the flow should upgrade to ERROR */ @Override public boolean shouldTransitionToFlowError(final FlowInstanceSetBuilder setBuilder) { // We transition to error if ALL instances of a given operation are in ERROR Set<String> allOperations = setBuilder.operationIds(); // Iterate each operation with an error.. for(String opId : allOperations) { FlowInstanceSetBuilder opSetBuilder = setBuilder.ofOperation(opId).withAliveHeartbeats(); // If there are more than 2 instances in ERROR, flow should ERROR if (opSetBuilder.inState("ERROR").size() > 2) { _log.info("ERROR instance threshold exceeded."); return true; } // If all instances are in ERROR or SUSPECT, flow should ERROR if (opSetBuilder.allInState("ERROR", "SUSPECT")) { _log.info("All instances of operation '" + opId + "' are in state SUSPECT or ERROR"); return true; } // If any instance is in ERROR during a startup stage, flow should ERROR if (opSetBuilder.anyInState("ERROR") && opSetBuilder.anyInState("INITIAL", "STARTING", "STARTED")) { _log.info("ERROR during prepare stage."); return true; } } // Otherwise, don't transition to ERROR return false; } }