Package com.amazonaws.services.simpleworkflow.flow.worker

Source Code of com.amazonaws.services.simpleworkflow.flow.worker.GenericWorkflowClientImpl

/*
* Copyright 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
* use this file except in compliance with the License. A copy of the License is
* located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.services.simpleworkflow.flow.worker;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;

import com.amazonaws.services.simpleworkflow.flow.ChildWorkflowFailedException;
import com.amazonaws.services.simpleworkflow.flow.ChildWorkflowTerminatedException;
import com.amazonaws.services.simpleworkflow.flow.ChildWorkflowTimedOutException;
import com.amazonaws.services.simpleworkflow.flow.SignalExternalWorkflowException;
import com.amazonaws.services.simpleworkflow.flow.StartChildWorkflowFailedException;
import com.amazonaws.services.simpleworkflow.flow.WorkflowContext;
import com.amazonaws.services.simpleworkflow.flow.common.FlowHelpers;
import com.amazonaws.services.simpleworkflow.flow.core.ExternalTask;
import com.amazonaws.services.simpleworkflow.flow.core.ExternalTaskCancellationHandler;
import com.amazonaws.services.simpleworkflow.flow.core.ExternalTaskCompletionHandle;
import com.amazonaws.services.simpleworkflow.flow.core.Functor;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.Settable;
import com.amazonaws.services.simpleworkflow.flow.core.Task;
import com.amazonaws.services.simpleworkflow.flow.generic.ContinueAsNewWorkflowExecutionParameters;
import com.amazonaws.services.simpleworkflow.flow.generic.GenericWorkflowClient;
import com.amazonaws.services.simpleworkflow.flow.generic.SignalExternalWorkflowParameters;
import com.amazonaws.services.simpleworkflow.flow.generic.StartChildWorkflowExecutionParameters;
import com.amazonaws.services.simpleworkflow.flow.generic.StartChildWorkflowReply;
import com.amazonaws.services.simpleworkflow.model.ChildPolicy;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionCanceledEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionCompletedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionFailedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionStartedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionTerminatedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ChildWorkflowExecutionTimedOutEventAttributes;
import com.amazonaws.services.simpleworkflow.model.ExternalWorkflowExecutionSignaledEventAttributes;
import com.amazonaws.services.simpleworkflow.model.HistoryEvent;
import com.amazonaws.services.simpleworkflow.model.RequestCancelExternalWorkflowExecutionDecisionAttributes;
import com.amazonaws.services.simpleworkflow.model.SignalExternalWorkflowExecutionDecisionAttributes;
import com.amazonaws.services.simpleworkflow.model.SignalExternalWorkflowExecutionFailedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.StartChildWorkflowExecutionDecisionAttributes;
import com.amazonaws.services.simpleworkflow.model.StartChildWorkflowExecutionFailedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.TaskList;
import com.amazonaws.services.simpleworkflow.model.WorkflowExecution;
import com.amazonaws.services.simpleworkflow.model.WorkflowType;

class GenericWorkflowClientImpl implements GenericWorkflowClient {

    private static class StartChildWorkflowReplyImpl implements StartChildWorkflowReply {

        private String runId;

        private final Settable<String> result = new Settable<String>();

        public StartChildWorkflowReplyImpl(String runId, String description) {
            this.runId = runId;
            result.setDescription(description);
        }

        @Override
        public String getRunId() {
            return runId;
        }

        @Override
        public Promise<String> getResult() {
            return result;
        }

        public void setResult(String value) {
            result.set(value);
        }

    }

    private final class ChildWorkflowCancellationHandler implements ExternalTaskCancellationHandler {

        private final String workflowId;

        private final ExternalTaskCompletionHandle handle;

        private ChildWorkflowCancellationHandler(String workflowId, ExternalTaskCompletionHandle handle) {
            this.workflowId = workflowId;
            this.handle = handle;
        }

        @Override
        public void handleCancellation(Throwable cause) {
            RequestCancelExternalWorkflowExecutionDecisionAttributes cancelAttributes = new RequestCancelExternalWorkflowExecutionDecisionAttributes();
            cancelAttributes.setWorkflowId(workflowId);

            decisions.requestCancelExternalWorkflowExecution(true, cancelAttributes, new Runnable() {

                @Override
                public void run() {
                    OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
                    if (scheduled == null) {
                        throw new IllegalArgumentException("Workflow \"" + workflowId + "\" wasn't scheduled");
                    }
                    handle.complete();
                }
            });
        }
    }

    private final DecisionsHelper decisions;

    private final WorkflowContext workflowContext;

    private final Map<String, OpenRequestInfo<StartChildWorkflowReply, WorkflowType>> scheduledExternalWorkflows = new HashMap<String, OpenRequestInfo<StartChildWorkflowReply, WorkflowType>>();

    private final Map<String, OpenRequestInfo<Void, Void>> scheduledSignals = new HashMap<String, OpenRequestInfo<Void, Void>>();

    GenericWorkflowClientImpl(DecisionsHelper decisions, WorkflowContext workflowContext) {
        this.decisions = decisions;
        this.workflowContext = workflowContext;
    }

    @Override
    public Promise<StartChildWorkflowReply> startChildWorkflow(final StartChildWorkflowExecutionParameters parameters) {
        final OpenRequestInfo<StartChildWorkflowReply, WorkflowType> context = new OpenRequestInfo<StartChildWorkflowReply, WorkflowType>();
        final StartChildWorkflowExecutionDecisionAttributes attributes = new StartChildWorkflowExecutionDecisionAttributes();
        attributes.setWorkflowType(parameters.getWorkflowType());
        String workflowId = parameters.getWorkflowId();
        if (workflowId == null) {
            workflowId = generateUniqueId();
        }
        attributes.setWorkflowId(workflowId);
        attributes.setInput(parameters.getInput());
        attributes.setExecutionStartToCloseTimeout(FlowHelpers.secondsToDuration(parameters.getExecutionStartToCloseTimeoutSeconds()));
        attributes.setTaskStartToCloseTimeout(FlowHelpers.secondsToDuration(parameters.getTaskStartToCloseTimeoutSeconds()));
        List<String> tagList = parameters.getTagList();
        if (tagList != null) {
            attributes.setTagList(tagList);
        }
        ChildPolicy childPolicy = parameters.getChildPolicy();
        if (childPolicy != null) {
            attributes.setChildPolicy(childPolicy);
        }
        String taskList = parameters.getTaskList();
        if (taskList != null && !taskList.isEmpty()) {
            attributes.setTaskList(new TaskList().withName(taskList));
        }
        String taskName = "workflowId=" + workflowId + ", workflowType=" + attributes.getWorkflowType();
        new ExternalTask() {

            @Override
            protected ExternalTaskCancellationHandler doExecute(final ExternalTaskCompletionHandle handle) throws Throwable {
                decisions.startChildWorkflowExecution(attributes);
                context.setCompletionHandle(handle);
                scheduledExternalWorkflows.put(attributes.getWorkflowId(), context);
                return new ChildWorkflowCancellationHandler(attributes.getWorkflowId(), handle);
            }
        }.setName(taskName);
        context.setResultDescription("startChildWorkflow " + taskName);
        return context.getResult();
    }

    @Override
    public Promise<String> startChildWorkflow(String workflow, String version, String input) {
        StartChildWorkflowExecutionParameters parameters = new StartChildWorkflowExecutionParameters();
        parameters.setWorkflowType(new WorkflowType().withName(workflow).withVersion(version));
        parameters.setInput(input);
        final Promise<StartChildWorkflowReply> started = startChildWorkflow(parameters);
        return new Functor<String>(started) {

            @Override
            protected Promise<String> doExecute() throws Throwable {
                return started.get().getResult();
            }
        };
    }

    @Override
    public Promise<String> startChildWorkflow(final String workflow, final String version, final Promise<String> input) {
        final Settable<String> result = new Settable<String>();

        new Task(input) {

            @Override
            protected void doExecute() throws Throwable {
                result.chain(startChildWorkflow(workflow, version, input.get()));
            }
        };
        return result;
    }

    @Override
    public Promise<Void> signalWorkflowExecution(final SignalExternalWorkflowParameters parameters) {
        final OpenRequestInfo<Void, Void> context = new OpenRequestInfo<Void, Void>();
        final SignalExternalWorkflowExecutionDecisionAttributes attributes = new SignalExternalWorkflowExecutionDecisionAttributes();
        String signalId = decisions.getNextId();
        attributes.setControl(signalId);
        attributes.setSignalName(parameters.getSignalName());
        attributes.setInput(parameters.getInput());
        attributes.setRunId(parameters.getRunId());
        attributes.setWorkflowId(parameters.getWorkflowId());
        String taskName = "signalId=" + signalId + ", workflowId=" + parameters.getWorkflowId() + ", workflowRunId="
                + parameters.getRunId();
        new ExternalTask() {

            @Override
            protected ExternalTaskCancellationHandler doExecute(final ExternalTaskCompletionHandle handle) throws Throwable {

                decisions.signalExternalWorkflowExecution(attributes);
                context.setCompletionHandle(handle);
                final String finalSignalId = attributes.getControl();
                scheduledSignals.put(finalSignalId, context);
                return new ExternalTaskCancellationHandler() {

                    @Override
                    public void handleCancellation(Throwable cause) {
                        decisions.cancelSignalExternalWorkflowExecution(finalSignalId, null);
                        OpenRequestInfo<Void, Void> scheduled = scheduledSignals.remove(finalSignalId);
                        if (scheduled == null) {
                            throw new IllegalArgumentException("Signal \"" + finalSignalId + "\" wasn't scheduled");
                        }
                        handle.complete();
                    }
                };
            }
        }.setName(taskName);
        context.setResultDescription("signalWorkflowExecution " + taskName);
        return context.getResult();
    }

    @Override
    public void requestCancelWorkflowExecution(WorkflowExecution execution) {
        RequestCancelExternalWorkflowExecutionDecisionAttributes attributes = new RequestCancelExternalWorkflowExecutionDecisionAttributes();
        String workflowId = execution.getWorkflowId();
        attributes.setWorkflowId(workflowId);
        attributes.setRunId(execution.getRunId());
        boolean childWorkflow = scheduledExternalWorkflows.containsKey(workflowId);
        // TODO: See if immediate cancellation needed
        decisions.requestCancelExternalWorkflowExecution(childWorkflow, attributes, null);
    }

    @Override
    public void continueAsNewOnCompletion(ContinueAsNewWorkflowExecutionParameters continueParameters) {
        // TODO: add validation to check if continueAsNew is not set
        workflowContext.setContinueAsNewOnCompletion(continueParameters);
    }

    @Override
    public String generateUniqueId() {
        WorkflowExecution workflowExecution = workflowContext.getWorkflowExecution();
        String runId = workflowExecution.getRunId();
        return runId + ":" + decisions.getNextId();
    }

    public void handleChildWorkflowExecutionCancelRequested(HistoryEvent event) {
        decisions.handleChildWorkflowExecutionCancelRequested(event);
    }

    void handleChildWorkflowExecutionCanceled(HistoryEvent event) {
        ChildWorkflowExecutionCanceledEventAttributes attributes = event.getChildWorkflowExecutionCanceledEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        if (decisions.handleChildWorkflowExecutionCanceled(workflowId)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                CancellationException e = new CancellationException();
                ExternalTaskCompletionHandle completionHandle = scheduled.getCompletionHandle();
                // It is OK to fail with subclass of CancellationException when cancellation requested.
                // It allows passing information about cancellation (details in this case) to the surrounding doCatch block
                completionHandle.fail(e);
            }
        }
    }

    void handleChildWorkflowExecutionStarted(HistoryEvent event) {
        ChildWorkflowExecutionStartedEventAttributes attributes = event.getChildWorkflowExecutionStartedEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        decisions.handleChildWorkflowExecutionStarted(event);
        OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.get(workflowId);
        if (scheduled != null) {
            String runId = attributes.getWorkflowExecution().getRunId();
            Settable<StartChildWorkflowReply> result = scheduled.getResult();
            if (!result.isReady()) {
                String description = "startChildWorkflow workflowId=" + workflowId + ", runId=" + runId;
                result.set(new StartChildWorkflowReplyImpl(runId, description));
            }
        }
    }

    void handleChildWorkflowExecutionTimedOut(HistoryEvent event) {
        ChildWorkflowExecutionTimedOutEventAttributes attributes = event.getChildWorkflowExecutionTimedOutEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        if (decisions.handleChildWorkflowExecutionClosed(workflowId)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                Exception failure = new ChildWorkflowTimedOutException(event.getEventId(), execution,
                        attributes.getWorkflowType());
                ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                context.fail(failure);
            }
        }
    }

    void handleChildWorkflowExecutionTerminated(HistoryEvent event) {
        ChildWorkflowExecutionTerminatedEventAttributes attributes = event.getChildWorkflowExecutionTerminatedEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        if (decisions.handleChildWorkflowExecutionClosed(workflowId)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                Exception failure = new ChildWorkflowTerminatedException(event.getEventId(), execution,
                        attributes.getWorkflowType());
                ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                context.fail(failure);
            }
        }
    }

    void handleStartChildWorkflowExecutionFailed(HistoryEvent event) {
        StartChildWorkflowExecutionFailedEventAttributes attributes = event.getStartChildWorkflowExecutionFailedEventAttributes();
        String workflowId = attributes.getWorkflowId();
        if (decisions.handleStartChildWorkflowExecutionFailed(event)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                WorkflowExecution workflowExecution = new WorkflowExecution();
                workflowExecution.setWorkflowId(workflowId);
                WorkflowType workflowType = attributes.getWorkflowType();
                String cause = attributes.getCause();
                Exception failure = new StartChildWorkflowFailedException(event.getEventId(), workflowExecution, workflowType,
                        cause);
                ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                context.fail(failure);
            }
        }
    }

    void handleChildWorkflowExecutionFailed(HistoryEvent event) {
        ChildWorkflowExecutionFailedEventAttributes attributes = event.getChildWorkflowExecutionFailedEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        if (decisions.handleChildWorkflowExecutionClosed(workflowId)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                String reason = attributes.getReason();
                String details = attributes.getDetails();
                Exception failure = new ChildWorkflowFailedException(event.getEventId(), execution, attributes.getWorkflowType(),
                        reason, details);
                ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                context.fail(failure);
            }
        }
    }

    void handleChildWorkflowExecutionCompleted(HistoryEvent event) {
        ChildWorkflowExecutionCompletedEventAttributes attributes = event.getChildWorkflowExecutionCompletedEventAttributes();
        WorkflowExecution execution = attributes.getWorkflowExecution();
        String workflowId = execution.getWorkflowId();
        if (decisions.handleChildWorkflowExecutionClosed(workflowId)) {
            OpenRequestInfo<StartChildWorkflowReply, WorkflowType> scheduled = scheduledExternalWorkflows.remove(workflowId);
            if (scheduled != null) {
                ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                String result = attributes.getResult();
                StartChildWorkflowReplyImpl startedReply = (StartChildWorkflowReplyImpl) scheduled.getResult().get();
                startedReply.setResult(result);
                context.complete();
            }
        }
    }

    void handleSignalExternalWorkflowExecutionFailed(HistoryEvent event) {
        SignalExternalWorkflowExecutionFailedEventAttributes attributes = event.getSignalExternalWorkflowExecutionFailedEventAttributes();
        String signalId = attributes.getControl();
        if (decisions.handleSignalExternalWorkflowExecutionFailed(signalId)) {
            OpenRequestInfo<Void, Void> signalContextAndResult = scheduledSignals.remove(signalId);
            if (signalContextAndResult != null) {
                WorkflowExecution signaledExecution = new WorkflowExecution();
                signaledExecution.setWorkflowId(attributes.getWorkflowId());
                signaledExecution.setRunId(attributes.getRunId());
                Throwable failure = new SignalExternalWorkflowException(event.getEventId(), signaledExecution,
                        attributes.getCause());
                signalContextAndResult.getCompletionHandle().fail(failure);
            }
        }
    }

    void handleExternalWorkflowExecutionSignaled(HistoryEvent event) {
        ExternalWorkflowExecutionSignaledEventAttributes attributes = event.getExternalWorkflowExecutionSignaledEventAttributes();
        String signalId = decisions.getSignalIdFromExternalWorkflowExecutionSignaled(attributes.getInitiatedEventId());
        if (decisions.handleExternalWorkflowExecutionSignaled(signalId)) {
            OpenRequestInfo<Void, Void> signalContextAndResult = scheduledSignals.remove(signalId);
            if (signalContextAndResult != null) {
                signalContextAndResult.getResult().set(null);
                signalContextAndResult.getCompletionHandle().complete();
            }
        }
    }

}
TOP

Related Classes of com.amazonaws.services.simpleworkflow.flow.worker.GenericWorkflowClientImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.