Search in sources :

Example 1 with Failure

use of io.camunda.zeebe.engine.processing.common.Failure in project zeebe by zeebe-io.

the class BpmnDecisionBehavior method evaluateDecision.

/**
 * Evaluate a decision during the processing of a bpmn element.
 *
 * @param element the called decision of the current bpmn element
 * @param context process instance-related data of the element that is executed
 * @return either an evaluated decision's result or a failure
 */
public Either<Failure, DecisionEvaluationResult> evaluateDecision(final ExecutableCalledDecision element, final BpmnElementContext context) {
    final var scopeKey = context.getElementInstanceKey();
    final var decisionIdOrFailure = evalDecisionIdExpression(element, scopeKey);
    if (decisionIdOrFailure.isLeft()) {
        return Either.left(decisionIdOrFailure.getLeft());
    }
    final var decisionId = decisionIdOrFailure.get();
    // todo(#8571): avoid parsing drg every time
    final var decisionOrFailure = findDecisionById(decisionId);
    final var resultOrFailure = decisionOrFailure.flatMap(this::findDrgByDecision).mapLeft(failure -> new Failure("Expected to evaluate decision '%s', but %s".formatted(decisionId, failure.getMessage()))).flatMap(drg -> parseDrg(drg.getResource())).mapLeft(f -> new Failure(f.getMessage(), ErrorType.CALLED_DECISION_ERROR, scopeKey)).flatMap(drg -> {
        final var evaluationResult = evaluateDecisionInDrg(drg, decisionId, scopeKey);
        final var decision = decisionOrFailure.get();
        writeDecisionEvaluationEvent(decision, evaluationResult, context);
        if (evaluationResult.isFailure()) {
            metrics.increaseFailedEvaluatedDmnElements(evaluationResult.getEvaluatedDecisions().size());
            return Either.left(new Failure(evaluationResult.getFailureMessage(), ErrorType.DECISION_EVALUATION_ERROR, scopeKey));
        } else {
            metrics.increaseSuccessfullyEvaluatedDmnElements(evaluationResult.getEvaluatedDecisions().size());
            return Either.right(evaluationResult);
        }
    });
    resultOrFailure.ifRight(result -> {
        // The output mapping behavior determines what to do with the decision result. Since the
        // output mapping may fail and raise an incident, we need to write the variable to a
        // record. This is because we want to evaluate the decision on element activation, while
        // the output mapping happens on element completion. We don't want to re-evaluate the
        // decision for output mapping related incidents.
        triggerProcessEventWithResultVariable(context, element.getResultVariable(), result);
    });
    return resultOrFailure;
}
Also used : BpmnElementContext(io.camunda.zeebe.engine.processing.bpmn.BpmnElementContext) ErrorType(io.camunda.zeebe.protocol.record.value.ErrorType) DecisionEvaluationResult(io.camunda.zeebe.dmn.DecisionEvaluationResult) ExecutableCalledDecision(io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableCalledDecision) VariableState(io.camunda.zeebe.engine.state.immutable.VariableState) ZeebeState(io.camunda.zeebe.engine.state.immutable.ZeebeState) MatchedRule(io.camunda.zeebe.dmn.MatchedRule) ByteArrayInputStream(java.io.ByteArrayInputStream) Failure(io.camunda.zeebe.engine.processing.common.Failure) DecisionEngine(io.camunda.zeebe.dmn.DecisionEngine) Either(io.camunda.zeebe.util.Either) DecisionState(io.camunda.zeebe.engine.state.immutable.DecisionState) StateWriter(io.camunda.zeebe.engine.processing.streamprocessor.writers.StateWriter) EvaluatedInput(io.camunda.zeebe.dmn.EvaluatedInput) MsgPackConverter(io.camunda.zeebe.protocol.impl.encoding.MsgPackConverter) BufferUtil.bufferAsString(io.camunda.zeebe.util.buffer.BufferUtil.bufferAsString) EvaluatedDecision(io.camunda.zeebe.dmn.EvaluatedDecision) MatchedRuleRecord(io.camunda.zeebe.protocol.impl.record.value.decision.MatchedRuleRecord) EvaluatedDecisionRecord(io.camunda.zeebe.protocol.impl.record.value.decision.EvaluatedDecisionRecord) PersistedDecisionRequirements(io.camunda.zeebe.engine.state.deployment.PersistedDecisionRequirements) KeyGenerator(io.camunda.zeebe.engine.state.KeyGenerator) DecisionEvaluationIntent(io.camunda.zeebe.protocol.record.intent.DecisionEvaluationIntent) ExpandableArrayBuffer(org.agrona.ExpandableArrayBuffer) Collectors(java.util.stream.Collectors) MsgPackWriter(io.camunda.zeebe.msgpack.spec.MsgPackWriter) ExpressionProcessor(io.camunda.zeebe.engine.processing.common.ExpressionProcessor) VariablesContext(io.camunda.zeebe.dmn.impl.VariablesContext) ParsedDecisionRequirementsGraph(io.camunda.zeebe.dmn.ParsedDecisionRequirementsGraph) DecisionEvaluationRecord(io.camunda.zeebe.protocol.impl.record.value.decision.DecisionEvaluationRecord) ProcessEngineMetrics(io.camunda.zeebe.engine.metrics.ProcessEngineMetrics) PersistedDecision(io.camunda.zeebe.engine.state.deployment.PersistedDecision) EventTriggerBehavior(io.camunda.zeebe.engine.processing.common.EventTriggerBehavior) EvaluatedOutput(io.camunda.zeebe.dmn.EvaluatedOutput) BufferUtil(io.camunda.zeebe.util.buffer.BufferUtil) DirectBuffer(org.agrona.DirectBuffer) Failure(io.camunda.zeebe.engine.processing.common.Failure)

Example 2 with Failure

use of io.camunda.zeebe.engine.processing.common.Failure in project zeebe by camunda.

the class BpmnResourceTransformer method transformResource.

@Override
public Either<Failure, Void> transformResource(final DeploymentResource resource, final DeploymentRecord deployment) {
    final BpmnModelInstance definition = readProcessDefinition(resource);
    final String validationError = validator.validate(definition);
    if (validationError == null) {
        // transform the model to avoid unexpected failures that are not covered by the validator
        bpmnTransformer.transformDefinitions(definition);
        return checkForDuplicateBpmnId(definition, resource, deployment).map(ok -> {
            transformProcessResource(deployment, resource, definition);
            return null;
        });
    } else {
        final var failureMessage = String.format("'%s': %s", resource.getResourceName(), validationError);
        return Either.left(new Failure(failureMessage));
    }
}
Also used : BpmnModelInstance(io.camunda.zeebe.model.bpmn.BpmnModelInstance) BufferUtil.wrapString(io.camunda.zeebe.util.buffer.BufferUtil.wrapString) Failure(io.camunda.zeebe.engine.processing.common.Failure)

Example 3 with Failure

use of io.camunda.zeebe.engine.processing.common.Failure in project zeebe by camunda.

the class DeploymentCreateProcessor method subscribeToTimerStartEventIfExists.

private void subscribeToTimerStartEventIfExists(final TypedStreamWriter streamWriter, final SideEffects sideEffects, final ProcessMetadata processMetadata, final List<ExecutableStartEvent> startEvents) {
    for (final ExecutableCatchEventElement startEvent : startEvents) {
        if (startEvent.isTimer()) {
            // There are no variables when there is no process instance yet,
            // we use a negative scope key to indicate this
            final long scopeKey = -1L;
            final Either<Failure, Timer> timerOrError = startEvent.getTimerFactory().apply(expressionProcessor, scopeKey);
            if (timerOrError.isLeft()) {
                // todo(#4323): deal with this exceptional case without throwing an exception
                throw new EvaluationException(timerOrError.getLeft().getMessage());
            }
            catchEventBehavior.subscribeToTimerEvent(NO_ELEMENT_INSTANCE, NO_ELEMENT_INSTANCE, processMetadata.getKey(), startEvent.getId(), timerOrError.get(), streamWriter, sideEffects);
        }
    }
}
Also used : Timer(io.camunda.zeebe.model.bpmn.util.time.Timer) ExecutableCatchEventElement(io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableCatchEventElement) EvaluationException(io.camunda.zeebe.engine.processing.common.ExpressionProcessor.EvaluationException) Failure(io.camunda.zeebe.engine.processing.common.Failure)

Example 4 with Failure

use of io.camunda.zeebe.engine.processing.common.Failure in project zeebe by zeebe-io.

the class TriggerTimerProcessor method rescheduleTimer.

private void rescheduleTimer(final TimerRecord record, final ExecutableCatchEvent event, final TypedCommandWriter writer, final Consumer<SideEffectProducer> sideEffects) {
    final Either<Failure, Timer> timer = event.getTimerFactory().apply(expressionProcessor, record.getElementInstanceKey());
    if (timer.isLeft()) {
        final String message = String.format("Expected to reschedule repeating timer for element with id '%s', but an error occurred: %s", BufferUtil.bufferAsString(event.getId()), timer.getLeft().getMessage());
        throw new IllegalStateException(message);
    // todo(#4208): raise incident instead of throwing an exception
    }
    int repetitions = record.getRepetitions();
    if (repetitions != RepeatingInterval.INFINITE) {
        repetitions--;
    }
    final Interval interval = timer.map(Timer::getInterval).get();
    final Timer repeatingInterval = new RepeatingInterval(repetitions, interval);
    catchEventBehavior.subscribeToTimerEvent(record.getElementInstanceKey(), record.getProcessInstanceKey(), record.getProcessDefinitionKey(), event.getId(), repeatingInterval, writer, sideEffects::accept);
}
Also used : Timer(io.camunda.zeebe.model.bpmn.util.time.Timer) RepeatingInterval(io.camunda.zeebe.model.bpmn.util.time.RepeatingInterval) Failure(io.camunda.zeebe.engine.processing.common.Failure) RepeatingInterval(io.camunda.zeebe.model.bpmn.util.time.RepeatingInterval) Interval(io.camunda.zeebe.model.bpmn.util.time.Interval)

Example 5 with Failure

use of io.camunda.zeebe.engine.processing.common.Failure in project zeebe by zeebe-io.

the class CatchEventAnalyzer method findCatchEvent.

public Either<Failure, CatchEventTuple> findCatchEvent(final DirectBuffer errorCode, ElementInstance instance, final Optional<DirectBuffer> jobErrorMessage) {
    // assuming that error events are used rarely
    // - just walk through the scope hierarchy and look for a matching catch event
    final ArrayList<DirectBuffer> availableCatchEvents = new ArrayList<>();
    while (instance != null && instance.isActive()) {
        final var instanceRecord = instance.getValue();
        final var process = getProcess(instanceRecord.getProcessDefinitionKey());
        final var found = findCatchEventInProcess(errorCode, process, instance);
        if (found.isRight()) {
            return Either.right(found.get());
        } else {
            availableCatchEvents.addAll(found.getLeft());
        }
        // find in parent process instance if exists
        final var parentElementInstanceKey = instanceRecord.getParentElementInstanceKey();
        instance = elementInstanceState.getInstance(parentElementInstanceKey);
    }
    final String incidentErrorMessage = String.format("Expected to throw an error event with the code '%s'%s, but it was not caught.%s", BufferUtil.bufferAsString(errorCode), jobErrorMessage.isPresent() && jobErrorMessage.get().capacity() > 0 ? String.format(" with message '%s'", BufferUtil.bufferAsString(jobErrorMessage.get())) : "", availableCatchEvents.isEmpty() ? " No error events are available in the scope." : String.format(" Available error events are [%s]", availableCatchEvents.stream().map(BufferUtil::bufferAsString).collect(Collectors.joining(", "))));
    // no matching catch event found
    return Either.left(new Failure(incidentErrorMessage, ErrorType.UNHANDLED_ERROR_EVENT));
}
Also used : DirectBuffer(org.agrona.DirectBuffer) BufferUtil(io.camunda.zeebe.util.buffer.BufferUtil) ArrayList(java.util.ArrayList) Failure(io.camunda.zeebe.engine.processing.common.Failure)

Aggregations

Failure (io.camunda.zeebe.engine.processing.common.Failure)20 Expression (io.camunda.zeebe.el.Expression)6 ExecutableCatchEventElement (io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableCatchEventElement)6 RepeatingInterval (io.camunda.zeebe.model.bpmn.util.time.RepeatingInterval)6 Timer (io.camunda.zeebe.model.bpmn.util.time.Timer)6 ErrorType (io.camunda.zeebe.protocol.record.value.ErrorType)4 Either (io.camunda.zeebe.util.Either)4 BufferUtil (io.camunda.zeebe.util.buffer.BufferUtil)4 DirectBuffer (org.agrona.DirectBuffer)4 ExpressionLanguage (io.camunda.zeebe.el.ExpressionLanguage)3 EvaluationException (io.camunda.zeebe.engine.processing.common.ExpressionProcessor.EvaluationException)3 ExecutableMessage (io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableMessage)3 ExecutableProcess (io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableProcess)3 ExecutableSequenceFlow (io.camunda.zeebe.engine.processing.deployment.model.element.ExecutableSequenceFlow)3 ModelElementTransformer (io.camunda.zeebe.engine.processing.deployment.model.transformation.ModelElementTransformer)3 TransformContext (io.camunda.zeebe.engine.processing.deployment.model.transformation.TransformContext)3 BpmnModelInstance (io.camunda.zeebe.model.bpmn.BpmnModelInstance)3 CatchEvent (io.camunda.zeebe.model.bpmn.instance.CatchEvent)3 ErrorEventDefinition (io.camunda.zeebe.model.bpmn.instance.ErrorEventDefinition)3 EventDefinition (io.camunda.zeebe.model.bpmn.instance.EventDefinition)3