com.amazonaws.services.simpleworkflow.flow.worker.WorkflowClockImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.amazonaws.services.simpleworkflow.flow.worker.WorkflowClockImpl.java

Source

/*
 * Copyright 2012-2014 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.Map;
import java.util.concurrent.CancellationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.services.simpleworkflow.flow.StartTimerFailedException;
import com.amazonaws.services.simpleworkflow.flow.WorkflowClock;
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.Promise;
import com.amazonaws.services.simpleworkflow.model.HistoryEvent;
import com.amazonaws.services.simpleworkflow.model.StartTimerDecisionAttributes;
import com.amazonaws.services.simpleworkflow.model.StartTimerFailedEventAttributes;
import com.amazonaws.services.simpleworkflow.model.TimerCanceledEventAttributes;
import com.amazonaws.services.simpleworkflow.model.TimerFiredEventAttributes;

class WorkflowClockImpl implements WorkflowClock {

    private static final Log log = LogFactory.getLog(WorkflowClockImpl.class);

    private final class TimerCancellationHandler implements ExternalTaskCancellationHandler {

        private final String timerId;

        private TimerCancellationHandler(String timerId) {
            this.timerId = timerId;
        }

        @Override
        public void handleCancellation(Throwable cause) {
            decisions.cancelTimer(timerId, new Runnable() {

                @Override
                public void run() {
                    OpenRequestInfo<?, ?> scheduled = scheduledTimers.remove(timerId);
                    ExternalTaskCompletionHandle context = scheduled.getCompletionHandle();
                    context.complete();
                }
            });
        }
    }

    private final DecisionsHelper decisions;

    private final Map<String, OpenRequestInfo<?, ?>> scheduledTimers = new HashMap<String, OpenRequestInfo<?, ?>>();

    private long replayCurrentTimeMilliseconds;

    private boolean replaying = true;

    WorkflowClockImpl(DecisionsHelper decisions) {
        this.decisions = decisions;
    }

    @Override
    public long currentTimeMillis() {
        return replayCurrentTimeMilliseconds;
    }

    void setReplayCurrentTimeMilliseconds(long replayCurrentTimeMilliseconds) {
        this.replayCurrentTimeMilliseconds = replayCurrentTimeMilliseconds;
    }

    @Override
    public boolean isReplaying() {
        return replaying;
    }

    void setReplaying(boolean replaying) {
        this.replaying = replaying;
    }

    @Override
    public Promise<Void> createTimer(long delaySeconds) {
        return createTimer(delaySeconds, null);
    }

    @Override
    public <T> Promise<T> createTimer(final long delaySeconds, final T userContext) {
        if (delaySeconds < 0) {
            throw new IllegalArgumentException("Negative delaySeconds: " + delaySeconds);
        }
        if (delaySeconds == 0) {
            return Promise.asPromise(userContext);
        }
        final OpenRequestInfo<T, Object> context = new OpenRequestInfo<T, Object>(userContext);
        final StartTimerDecisionAttributes timer = new StartTimerDecisionAttributes();
        timer.setStartToFireTimeout(FlowHelpers.secondsToDuration(delaySeconds));
        final String timerId = decisions.getNextId();
        timer.setTimerId(timerId);
        String taskName = "timerId=" + timer.getTimerId() + ", delaySeconds=" + timer.getStartToFireTimeout();
        new ExternalTask() {

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

                decisions.startTimer(timer, userContext);
                context.setCompletionHandle(handle);
                scheduledTimers.put(timerId, context);
                return new TimerCancellationHandler(timerId);
            }
        }.setName(taskName);
        context.setResultDescription("createTimer " + taskName);
        return context.getResult();
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    void handleTimerFired(Long eventId, TimerFiredEventAttributes attributes) {
        String timerId = attributes.getTimerId();
        if (decisions.handleTimerClosed(timerId)) {
            OpenRequestInfo scheduled = scheduledTimers.remove(timerId);
            if (scheduled != null) {
                ExternalTaskCompletionHandle completionHandle = scheduled.getCompletionHandle();
                scheduled.getResult().set(scheduled.getUserContext());
                completionHandle.complete();
            }
        } else {
            log.debug("handleTimerFired not complete");
        }
    }

    @SuppressWarnings({ "rawtypes" })
    void handleStartTimerFailed(HistoryEvent event) {
        StartTimerFailedEventAttributes attributes = event.getStartTimerFailedEventAttributes();
        String timerId = attributes.getTimerId();
        if (decisions.handleStartTimerFailed(event)) {
            OpenRequestInfo scheduled = scheduledTimers.remove(timerId);
            if (scheduled != null) {
                ExternalTaskCompletionHandle completionHandle = scheduled.getCompletionHandle();
                Object createTimerUserContext = scheduled.getUserContext();
                String cause = attributes.getCause();
                Throwable failure = new StartTimerFailedException(event.getEventId(), timerId,
                        createTimerUserContext, cause);
                completionHandle.fail(failure);
            }
        } else {
            log.debug("handleStartTimerFailed not complete");
        }
    }

    void handleTimerCanceled(HistoryEvent event) {
        TimerCanceledEventAttributes attributes = event.getTimerCanceledEventAttributes();
        String timerId = attributes.getTimerId();
        if (decisions.handleTimerCanceled(event)) {
            OpenRequestInfo<?, ?> scheduled = scheduledTimers.remove(timerId);
            if (scheduled != null) {
                ExternalTaskCompletionHandle completionHandle = scheduled.getCompletionHandle();
                CancellationException exception = new CancellationException();
                completionHandle.fail(exception);
            }
        } else {
            log.debug("handleTimerCanceled not complete");
        }
    }

}