@Override public void transitionInto(RunState state) { switch (state.state()) { case TERMINATED: if (state.data().lastExit().map(v -> v.equals(0)).orElse(false)) { stateManager.receiveIgnoreClosed(Event.success(state.workflowInstance())); } else { checkRetry(state); } break; case FAILED: checkRetry(state); break; default: // do nothing } }
@VisibleForTesting static String stateInfo(RunState state) { switch (state.state()) { case NEW: case PREPARE: case ERROR: case DONE: return format("tries:%d", state.data().tries()); case SUBMITTED: case RUNNING: case FAILED: return format("tries:%d execId:%s", state.data().tries(), state.data().executionId()); case TERMINATED: return format("tries:%d execId:%s exitCode:%s", state.data().tries(), state.data().executionId(), state.data().lastExit().map( String::valueOf).orElse("-")); case QUEUED: return format("tries:%d delayMs:%s", state.data().tries(), state.data().retryDelayMillis()); default: return ""; } } }
private void checkRetry(RunState state) { final WorkflowInstance workflowInstance = state.workflowInstance(); if (state.data().retryCost() < MAX_RETRY_COST) { final Optional<Integer> exitCode = state.data().lastExit(); if (shouldFailFast(exitCode)) { stateManager.receiveIgnoreClosed(Event.stop(workflowInstance)); } else { final long delayMillis; if (isMissingDependency(exitCode)) { delayMillis = Duration.ofMinutes(MISSING_DEPS_RETRY_DELAY_MINUTES).toMillis(); } else { delayMillis = retryUtil.calculateDelay(state.data().consecutiveFailures()).toMillis(); } stateManager.receiveIgnoreClosed(Event.retryAfter(workflowInstance, delayMillis)); } } else { stateManager.receiveIgnoreClosed(Event.stop(workflowInstance)); } }
state.data().lastExit().ifPresent(v -> entity.set(PROPERTY_STATE_LAST_EXIT, v)); state.data().trigger().ifPresent(trigger -> { entity.set(PROPERTY_STATE_TRIGGER_TYPE, TriggerUtil.triggerType(trigger));