@Override public Map<WorkflowInstance, RunState> readActiveStatesByTriggerId(String triggerId) throws IOException { return activeStatesMap.entrySet().stream() .filter((entry) -> triggerId.equals(TriggerUtil.triggerId(entry.getValue().data().trigger().get()))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); }
private static boolean backfillFound(boolean triggerExecutionEventMet, String backfillId, RunState restoredState) { return triggerExecutionEventMet && restoredState.data().trigger() .map(trigger -> backfillId.equals(TriggerUtil.triggerId(trigger))) .orElse(false); }
private boolean isPodRunState(Pod pod, RunState runState) { final String podName = pod.getMetadata().getName(); final Optional<String> executionIdOpt = runState.data().executionId(); if (!executionIdOpt.isPresent()) { LOG.debug("Pod event for state with no current executionId: {}", podName); return false; } final String executionId = executionIdOpt.get(); if (!podName.equals(executionId)) { LOG.debug("Pod event not matching current exec id, current:{} != pod:{}", executionId, podName); return false; } return true; }
public static void emitResourceLimitReachedMessage(StateManager stateManager, RunState runState, List<String> depletedResources) { if (depletedResources.isEmpty()) { throw new IllegalArgumentException(); } final List<String> depletedResourcesOrdered = depletedResources.stream().sorted().collect(toList()); final Message message = Message.info("Resource limit reached for: " + depletedResourcesOrdered); if (!runState.data().message().map(message::equals).orElse(false)) { stateManager.receiveIgnoreClosed(Event.info(runState.workflowInstance(), message), runState.counter()); } } }
private boolean shouldExecute(RunState runState) { if (runState.state() != State.QUEUED) { return false; } final Instant now = time.get(); final Instant deadline = Instant .ofEpochMilli(runState.timestamp()) .plusMillis(runState.data().retryDelayMillis().orElse(0L)); return !deadline.isAfter(now); }
@Override public RunState submitted(WorkflowInstance workflowInstance, String executionId) { switch (state()) { case SUBMITTING: return state( SUBMITTED, data().builder() .tries(data().tries() + 1) // backwards compatibility .executionId(data().executionId().orElse(executionId)) .build()); default: throw illegalTransition("submitted"); } }
private void sendDequeue(InstanceState instanceState, Set<String> resourceIds) { final WorkflowInstance workflowInstance = instanceState.workflowInstance(); final RunState state = instanceState.runState(); if (state.data().tries() == 0) { LOG.info("Executing {}", workflowInstance); } else { LOG.info("Executing {}, retry #{}", workflowInstance, state.data().tries()); } stateManager.receiveIgnoreClosed(Event.dequeue(workflowInstance, resourceIds), instanceState.runState().counter()); }
private RunState transitionUpdates(Instant instant) { return new AutoValue_RunState( workflowInstance(), state(), instant.toEpochMilli(), data(), counter() + 1); }
@Override public RunState terminate(WorkflowInstance workflowInstance, Optional<Integer> exitCode) { switch (state()) { case RUNNING: final double cost = exitCost(exitCode); final int consecutiveFailures = consecutiveFailures(data(), exitCode); final MessageLevel level = messageLevel(exitCode); final StateData newStateData = data().builder() .retryCost(data().retryCost() + cost) .lastExit(exitCode) .consecutiveFailures(consecutiveFailures) .messages(Message.create(level, "Exit code: " + exitCode.map(String::valueOf).orElse("-"))) .build(); return state(TERMINATED, newStateData); default: throw illegalTransition("terminate"); } }
@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 } }
private RunState state(State state) { return new AutoValue_RunState( workflowInstance(), state, timestamp(), data(), counter()); }
@Override public RunState retryAfter(WorkflowInstance workflowInstance, long delayMillis) { switch (state()) { case TERMINATED: case FAILED: case QUEUED: return state( QUEUED, data().builder() .retryDelayMillis(delayMillis) .executionId(empty()) .executionDescription(empty()) .resourceIds(empty()) .build()); default: throw illegalTransition("retryAfter"); } }
@Override public RunState dequeue(WorkflowInstance workflowInstance, Set<String> resourceIds) { switch (state()) { case QUEUED: return state( PREPARE, data().builder() .retryDelayMillis(empty()) .resourceIds(resourceIds) .build()); default: throw illegalTransition("dequeue"); } }
@Override public RunState info(WorkflowInstance workflowInstance, Message message) { switch (state()) { case QUEUED: return state( QUEUED, data().builder() .messages(message) .build()); default: throw illegalTransition("info"); } }
@Deprecated @Override public RunState timeTrigger(WorkflowInstance workflowInstance) { switch (state()) { case NEW: return state( // for backwards compatibility SUBMITTED, data().builder() .trigger(Trigger.unknown("UNKNOWN")) .triggerId("UNKNOWN") // for backwards compatibility .build()); default: throw illegalTransition("timeTrigger"); } }
@Override public RunState submit(WorkflowInstance workflowInstance, ExecutionDescription executionDescription, String executionId) { switch (state()) { case QUEUED: // for backwards compatibility case PREPARE: return state( SUBMITTING, data().builder() .executionDescription(executionDescription) .executionId(executionId) .build()); default: throw illegalTransition("submit"); } }
@Override public RunState triggerExecution(WorkflowInstance workflowInstance, Trigger trigger, TriggerParameters parameters) { switch (state()) { case NEW: return state( QUEUED, data().builder() .trigger(trigger) .triggerId(TriggerUtil.triggerId(trigger)) // for backwards compatibility .triggerParameters(parameters) .build()); default: throw illegalTransition("triggerExecution"); } }
private RunStateData getRunStateData(Backfill backfill, Map<WorkflowInstance, RunState> activeWorkflowInstances, Instant instant) { final WorkflowInstance wfi = WorkflowInstance .create(backfill.workflowId(), toParameter(backfill.schedule(), instant)); if (activeWorkflowInstances.containsKey(wfi)) { final RunState state = activeWorkflowInstances.get(wfi); return RunStateData.newBuilder() .workflowInstance(state.workflowInstance()) .state(state.state().name()) .stateData(state.data()) .latestTimestamp(state.timestamp()) .build(); } return ReplayEvents.getBackfillRunStateData(wfi, storage, backfill.id()) .orElse(RunStateData.create(wfi, UNKNOWN, StateData.zero())); } }
private RunStateData runStateToRunStateData(RunState state) { return RunStateData.newBuilder() .workflowInstance(state.workflowInstance()) .state(state.state().name()) .stateData(state.data()) .latestTimestamp(state.timestamp()) .build(); }