/*
* 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.examples.fileprocessing;
import java.io.File;
import java.io.IOException;
import com.amazonaws.services.simpleworkflow.flow.ActivitySchedulingOptions;
import com.amazonaws.services.simpleworkflow.flow.DecisionContextProviderImpl;
import com.amazonaws.services.simpleworkflow.flow.WorkflowContext;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.Settable;
import com.amazonaws.services.simpleworkflow.flow.core.TryCatchFinally;
/**
* This implementation of FileProcessingWorkflow downloads the file, zips it and
* uploads it back to S3
*/
public class FileProcessingWorkflowZipImpl implements FileProcessingWorkflow {
private final SimpleStoreActivitiesClient store;
private final FileProcessingActivitiesClient processor;
private final WorkflowContext workflowContext;
private String state = "Started";
public FileProcessingWorkflowZipImpl() {
// Create activity clients
this.store = new SimpleStoreActivitiesClientImpl();
processor = new FileProcessingActivitiesClientImpl();
workflowContext = (new DecisionContextProviderImpl()).getDecisionContext().getWorkflowContext();
}
/**
* Constructor used for unit testing or when Spring is used to configure
* workflow
*/
public FileProcessingWorkflowZipImpl(SimpleStoreActivitiesClient store, FileProcessingActivitiesClient processor,
WorkflowContext workflowContext) {
this.store = store;
this.processor = processor;
this.workflowContext = workflowContext;
}
@Override
public void processFile(final String sourceBucketName, final String sourceFilename, final String targetBucketName,
final String targetFilename) throws IOException {
// Settable to store the worker specific task list returned by the activity
final Settable<String> taskList = new Settable<String>();
// Use runId as a way to ensure that downloaded files do not get name collisions
String workflowRunId = workflowContext.getWorkflowExecution().getRunId();
File localSource = new File(sourceFilename);
final String localSourceFilename = workflowRunId + "_" + localSource.getName();
File localTarget = new File(targetFilename);
final String localTargetFilename = workflowRunId + "_" + localTarget.getName();
new TryCatchFinally() {
@Override
protected void doTry() throws Throwable {
Promise<String> activityWorkerTaskList = store.download(sourceBucketName, sourceFilename, localSourceFilename);
// chaining is a way for one promise get assigned value of another
taskList.chain(activityWorkerTaskList);
// Call processFile activity to zip the file
Promise<Void> fileProcessed = processFileOnHost(localSourceFilename, localTargetFilename, activityWorkerTaskList);
// Call upload activity to upload zipped file
upload(targetBucketName, targetFilename, localTargetFilename, taskList, fileProcessed);
}
@Override
protected void doCatch(Throwable e) throws Throwable {
state = "Failed: " + e.getMessage();
throw e;
}
@Override
protected void doFinally() throws Throwable {
if (taskList.isReady()) { // File was downloaded
// Set option to schedule activity in worker specific task list
ActivitySchedulingOptions options = new ActivitySchedulingOptions().withTaskList(taskList.get());
// Call deleteLocalFile activity using the host specific task list
store.deleteLocalFile(localSourceFilename, options);
store.deleteLocalFile(localTargetFilename, options);
}
if (!state.startsWith("Failed:")) {
state = "Completed";
}
}
};
}
@Asynchronous
private Promise<Void> processFileOnHost(String fileToProcess, String fileToUpload, Promise<String> taskList) {
state = "Downloaded to " + taskList.get();
// Call the activity to process the file using worker specific task list
ActivitySchedulingOptions options = new ActivitySchedulingOptions().withTaskList(taskList.get());
return processor.processFile(fileToProcess, fileToUpload, options);
}
@Asynchronous
private void upload(final String targetBucketName, final String targetFilename, final String localTargetFilename,
Promise<String> taskList, Promise<Void> fileProcessed) {
state = "Processed at " + taskList.get();
ActivitySchedulingOptions options = new ActivitySchedulingOptions().withTaskList(taskList.get());
store.upload(targetBucketName, localTargetFilename, targetFilename, options);
}
@Override
public String getState() {
return state;
}
}