Implementation for accessing AmazonSimpleWorkflow. Amazon Simple Workflow Service

The Amazon Simple Workflow Service API Reference is intended for programmers who need detailed information about the Amazon SWF actions and data types.

For an broader overview of the Amazon SWF programming model, please go to the Amazon SWF Developer Guide .

This section provides an overview of Amazon SWF actions.

Action Categories

The Amazon SWF actions can be grouped into the following major categories.

  • Actions related to Activities

  • Actions related to Deciders

  • Actions related to Workflow Executions

  • Actions related to Administration

  • Actions related to Visibility

Actions related to Activities

The following are actions that are performed by activity workers:

Activity workers use the PollForActivityTask to get new activity tasks. After a worker receives an activity task from Amazon SWF, it performs the task and responds using RespondActivityTaskCompleted if successful or RespondActivityTaskFailed if unsuccessful.

Actions related to Deciders

The following are actions that are performed by deciders:

Deciders use PollForDecisionTask to get decision tasks. After a decider receives a decision task from Amazon SWF, it examines its workflow execution history and decides what to do next. It calls RespondDecisionTaskCompleted to complete the decision task and provide zero or more next decisions.

Actions related to Workflow Executions

The following actions operate on a workflow execution:

Actions related to Administration

Although you can perform administrative tasks from the Amazon SWF console, you can use the actions in this section to automate functions or build your own administrative tools.

Activity Management

Workflow Management

Domain Management

Workflow Execution Management

Visibility Actions

Although you can perform visibility actions from the Amazon SWF console, you can use the actions in this section to build your own console or administrative tools.

Activity Visibility

Workflow Visibility

Workflow Execution Visibility

Domain Visibility

Task List Visibility

Inheritance: AmazonWebServiceClient, IAmazonSimpleWorkflow
        private static void StartEchoWorkflow()
        {
            var client = new AmazonSimpleWorkflowClient();

            var activity = WorkflowFactory.CreateActivity<string, string>("echo", Echo, 60, 10, 10, 20)
                                          .Complete();
            var workflow = WorkflowFactory.CreateWorkflow("theburningmonk.com", "echo_cs", "1")
                                          .Attach(activity)
                                          .Complete();
            
            workflow.Start(client);
        }
        private static void StartCountHtmlElementsWorkflow()
        {
            var client = new AmazonSimpleWorkflowClient();

            var echo = WorkflowFactory.CreateActivity<string, string>("echo", Echo, 60, 10, 10, 20)
                                      .Complete();
            var countDiv = WorkflowFactory.CreateActivity<string, int>("count_divs", address => CountMatches("<div", address), 60, 10, 10, 20)
                                          .WithDescription("count the number of <div> elements")
                                          .Complete();
            var countScripts = WorkflowFactory.CreateActivity<string, int>("count_scripts", address => CountMatches("<script", address), 60, 10, 10, 20)
                                              .WithDescription("count the number of <script> elements")
                                              .Complete();
            var countSpans = WorkflowFactory.CreateActivity<string, int>("count_spans", address => CountMatches("<span", address), 60, 10, 10, 20)
                                            .WithDescription("count the number of <span> elements")
                                            .Complete();

            var workflow = WorkflowFactory.CreateWorkflow("theburningmonk.com", "count_html_elements_cs", "1")
                                          .Attach(echo)
                                          .Attach(new[] { countDiv, countScripts, countSpans }, MatchesReducer)
                                          .Attach(echo)
                                          .Complete();
            
            workflow.Start(client);
        }
        public static string GetServiceOutput()
        {
            var sb = new StringBuilder(1024);
            using (var sr = new StringWriter(sb))
            {
                sr.WriteLine("===============================");
                sr.WriteLine("| AWS Simple Workflow Service |");
                sr.WriteLine("===============================");

                try
                {
                    // Print the available domains, workflows and activities. Region endpoint depends on where
                    // you chose to set up your workflow domain
                    var swfClient = new AmazonSimpleWorkflowClient(RegionEndpoint.USWest2);

                    sr.WriteLine();
                    var listDomainRequest = new ListDomainsRequest
                    {
                        RegistrationStatus = "REGISTERED"
                    };

                    var listDomainResponse = swfClient.ListDomains(listDomainRequest);
                    foreach (var domain in listDomainResponse.DomainInfos.Infos)
                    {
                        sr.WriteLine("[" + domain.Name + "]");
                        sr.WriteLine("status: " + domain.Status);
                        sr.WriteLine("description: " + domain.Description);

                        sr.WriteLine("\n  WORKFLOWS");
                        var listWorkflowRequest = new ListWorkflowTypesRequest
                        {
                            Domain = domain.Name,
                            RegistrationStatus = "REGISTERED"
                        };
                        var listWorkflowTypesResponse = swfClient.ListWorkflowTypes(listWorkflowRequest);
                        foreach (
                            var workflow in
                                listWorkflowTypesResponse.WorkflowTypeInfos.TypeInfos)
                        {
                            sr.WriteLine("  [" + workflow.WorkflowType.Name + "] (" + workflow.WorkflowType.Version + ") " + workflow.Status);
                            sr.WriteLine("  creation: " + workflow.CreationDate);
                            sr.WriteLine("  deprecation: " + workflow.DeprecationDate);
                            sr.WriteLine("  description:" + TrimStringToLength(workflow.Description, 60, "", "              "));
                            sr.WriteLine();
                        }

                        sr.WriteLine("\n  ACTIVITIES");
                        var listActivityRequest = new ListActivityTypesRequest
                        {
                            Domain = domain.Name,
                            RegistrationStatus = "REGISTERED"
                        };
                        var listActivityResponse = swfClient.ListActivityTypes(listActivityRequest);
                        foreach (
                            var activity in listActivityResponse.ActivityTypeInfos.TypeInfos)
                        {
                            sr.WriteLine("  [" + activity.ActivityType.Name + "] (" + activity.ActivityType.Version + ") " + activity.Status);
                            sr.WriteLine("  creation: " + activity.CreationDate);
                            sr.WriteLine("  deprecation: " + activity.DeprecationDate);
                            sr.WriteLine("  description:" + TrimStringToLength(activity.Description, 60, "", "              "));
                            sr.WriteLine();
                        }
                    }
                }
                catch (AmazonSimpleWorkflowException ex)
                {
                    if (ex.ErrorCode != null && ex.ErrorCode.Equals("AuthFailure"))
                    {
                        sr.WriteLine("The account you are using is not signed up for Amazon SWF.");
                        sr.WriteLine("You can sign up for Amazon SWF at http://aws.amazon.com/swf");
                    }
                    else
                    {
                        sr.WriteLine("Caught Exception: " + ex.Message);
                        sr.WriteLine("Response Status Code: " + ex.StatusCode);
                        sr.WriteLine("Error Code: " + ex.ErrorCode);
                        sr.WriteLine("Error Type: " + ex.ErrorType);
                        sr.WriteLine("Request ID: " + ex.RequestId);
                        sr.WriteLine("Data: " + ex.Data);
                        sr.WriteLine("Stacktrace: " + ex.StackTrace);
                    }
                }
                sr.WriteLine();
            }
            return sb.ToString();
        }
        public static void Main(string[] args)
        {
            // Define the workflows that we know of that event processor will be handling
            var workflows = new Dictionary<string, Type>
                {
                    {"CustomerOrderWorkflow", typeof (CustomerOrderWorkflow)},
                    {"VerifyCustomerWorkflow", typeof (VerifyCustomerWorkflow)}
                };


            // Stopwatch to see how well we are performing
            var stopwatch = new Stopwatch();

            // We will use this ID as our decision task ID and activity task ID to identify ourselves when polling for
            // decision and activity tasks.
            var workflowWorkerIdentity = Guid.NewGuid();
            
            // Print out our AWS SWF domains, workflows and activities
            Console.Write(GetServiceOutput());

            var loop = true;
            do
            {
                // Our super simple application menu
                Console.WriteLine("");
                Console.WriteLine("=============");
                Console.WriteLine("| Main Menu |");
                Console.WriteLine("=============");
                Console.WriteLine("[1] Submit a new workflow");
                Console.WriteLine("[2] Wait for decide using a decision task");
                Console.WriteLine("[3] Wait for and do some work for an activity task");
                Console.WriteLine("[4] Quit");

                Console.Write("\nChoice: ");
                var key = Console.ReadLine();

                if (String.IsNullOrEmpty(key))
                {
                    continue;
                }

                switch (key)
                {
                    // Initiate a workflow execution
                    case "1":
                        {
                            Console.WriteLine("Option [1] selected - Submit a new workflow");

                            // SWF client is disposable, so dispose it
                            using (var swfClient = new AmazonSimpleWorkflowClient(RegionEndpoint.USWest2))
                            {
                                // Our simple property bag: we just need to the email for the account
                                var propertyBag = new Dictionary<string, object> { { "SampleOrderNumber", "12345" } };

                                // Setup the workflow request
                                var workflowRequest = new StartWorkflowExecutionRequest
                                {
                                    Domain = "demo-domain",
                                    WorkflowId = Guid.NewGuid().ToString(),
                                    WorkflowType = new WorkflowType
                                    {
                                        Name = "CustomerOrderWorkflow",
                                        Version = "1.0"
                                    },
                                    Input = JsonConvert.SerializeObject(propertyBag)
                                };

                                try
                                {
                                    // Call AWS SWF and submit the workflow request
                                    swfClient.StartWorkflowExecution(workflowRequest);
                                }
                                catch (AmazonSimpleWorkflowException ex)
                                {
                                    Console.WriteLine("Caught Exception: " + ex.Message);
                                    Console.WriteLine("Response Status Code: " + ex.StatusCode);
                                    Console.WriteLine("Error Code: " + ex.ErrorCode);
                                    Console.WriteLine("Error Type: " + ex.ErrorType);
                                    Console.WriteLine("Request ID: " + ex.RequestId);
                                    Console.WriteLine("Data: " + ex.Data);
                                    Console.WriteLine("Stacktrace: " + ex.StackTrace);
                                }
                            }
                        }
                        break;

                    // Poll for decision task
                    case "2":
                        {
                            Console.WriteLine("Option [2] selected - Wait for decide using a decision task");
                            Console.WriteLine("Waiting...");

                            // SWF client is disposable, so dispose it
                            using (var swfClient = new AmazonSimpleWorkflowClient(RegionEndpoint.USWest2))
                            {
                                try
                                {
                                    // Setup the decision request
                                    var decisionTaskRequest = new PollForDecisionTaskRequest
                                    {
                                        Domain = "demo-domain",
                                        Identity = workflowWorkerIdentity.ToString(),
                                        TaskList = new TaskList { Name = "DeciderTaskList-Default" }
                                    };

                                    // Call AWS SWF and wait for (default timeout: 60 secs) a decision task
                                    var decisionTaskResponse = swfClient.PollForDecisionTask(decisionTaskRequest);

                                    // Task token being an empty string means there are no tasks available and 
                                    // we are past the 60 seconds that AWS holds a connection in case a task
                                    // becomes available. If this is the case, we simply retry.
                                    var taskToken =
                                        decisionTaskResponse.DecisionTask.TaskToken;
                                    if (!String.IsNullOrEmpty(taskToken))
                                    {
                                        // We have a valid task, do something...
                                        var decisionTask =
                                            decisionTaskResponse.DecisionTask;

                                        switch (decisionTask.WorkflowType.Name)
                                        {
                                            case "CustomerOrderWorkflow":
                                            case "VerifyCustomerWorkflow":
                                                {
                                                    Debug.Assert(decisionTask.WorkflowType.Version == "1.0");
                                                }
                                                break;

                                            default:
                                                Console.WriteLine("ERROR: Unknown workflow.");
                                                break;
                                        }

                                        // Define a new WorkflowEventsProcessor object and let it make the decision!
                                        stopwatch.Start();
                                        var workflowProcessor = new WorkflowEventsProcessor(decisionTask, workflows, decisionTaskRequest, swfClient);
                                        var decisionRequest = workflowProcessor.Decide();
                                        stopwatch.Stop();

                                        Console.WriteLine(">>> Decision(s) made in " + stopwatch.ElapsedMilliseconds + "ms");

                                        // We have our decision, send it away and do something 
                                        // more productive with the response
                                        swfClient.RespondDecisionTaskCompleted(decisionRequest);
                                    }
                                }
                                catch (AmazonSimpleWorkflowException ex)
                                {
                                    Console.WriteLine("Caught Exception: " + ex.Message);
                                    Console.WriteLine("Response Status Code: " + ex.StatusCode);
                                    Console.WriteLine("Error Code: " + ex.ErrorCode);
                                    Console.WriteLine("Error Type: " + ex.ErrorType);
                                    Console.WriteLine("Request ID: " + ex.RequestId);
                                    Console.WriteLine("Data: " + ex.Data);
                                    Console.WriteLine("Stacktrace: " + ex.StackTrace);
                                }
                            }
                        }
                        break;

                    // Poll for activity task
                    case "3":
                        {
                            Console.WriteLine("Option [3] selected - Wait for decide using a activity task");
                            Console.WriteLine("Waiting...");

                            // SWF client is disposable, so dispose it
                            using (var swfClient = new AmazonSimpleWorkflowClient(RegionEndpoint.USWest2))
                            {
                                try
                                {
                                    // Setup the activity request
                                    var activityTaskRequest = new PollForActivityTaskRequest
                                    {
                                        Domain = "demo-domain",
                                        Identity = workflowWorkerIdentity.ToString(),
                                        TaskList = new TaskList { Name = "ActivityTaskList-Default" }
                                    };

                                    // Call AWS SWF and wait for (default timeout: 60 secs) a activity task
                                    var activityTaskResponse = swfClient.PollForActivityTask(activityTaskRequest);

                                    // Task token being an empty string means there are no tasks available and 
                                    // we are past the 60 seconds that AWS holds a connection in case a task
                                    // becomes available. If this is the case, we simply retry.
                                    var taskToken =
                                        activityTaskResponse.ActivityTask.TaskToken;
                                    if (!String.IsNullOrEmpty(taskToken))
                                    {
                                        // We have a valid task, do something...
                                        var activityTask =
                                            activityTaskResponse.ActivityTask;

                                        Console.WriteLine("\n");
                                        Console.WriteLine(">>> Activity: " + activityTask.ActivityType.Name);

                                        // In the real world we would define the activity code in a separate object
                                        // and fire off a thread to actually work on it but in this case we are just
                                        // testing the workflow so this suffices
                                        switch (activityTask.ActivityType.Name)
                                        {
                                            // CustomerOrderWorkflow activities
                                            case "VerifyOrder":
                                            case "ShipOrder":
                                                {
                                                    Debug.Assert(activityTask.ActivityType.Version == "1.0");
                                                }
                                                break;

                                            // VerifyCustomerWorkflow activities
                                            case "VerifyCustomerAddress":
                                            case "CheckFraudDB":
                                            case "ChargeCreditCard":
                                                {
                                                    Debug.Assert(activityTask.ActivityType.Version == "1.0");
                                                }
                                                break;

                                            default:
                                                Console.WriteLine("ERROR: Unknown activity.");
                                                break;
                                        }

                                        var activityCompletedRequest = new RespondActivityTaskCompletedRequest
                                        {
                                            TaskToken = activityTask.TaskToken,
                                            Result = activityTask.Input
                                        };

                                        // Completion request setup complete, send it away. NOTE: Do something more
                                        // productive with the response
                                        swfClient.RespondActivityTaskCompleted(activityCompletedRequest);

                                        //var activityFailedRequest = new RespondActivityTaskFailedRequest
                                        //    {
                                        //        TaskToken = activityTask.TaskToken,
                                        //        Details = "Test failure."
                                        //    };
                                        //// Completion request setup complete, send it away. NOTE: Do something more
                                        //// productive with the response
                                        //swfClient.RespondActivityTaskFailed(activityFailedRequest);
                                    }
                                }
                                catch (AmazonSimpleWorkflowException ex)
                                {
                                    Console.WriteLine("Caught Exception: " + ex.Message);
                                    Console.WriteLine("Response Status Code: " + ex.StatusCode);
                                    Console.WriteLine("Error Code: " + ex.ErrorCode);
                                    Console.WriteLine("Error Type: " + ex.ErrorType);
                                    Console.WriteLine("Request ID: " + ex.RequestId);
                                    Console.WriteLine("Data: " + ex.Data);
                                    Console.WriteLine("Stacktrace: " + ex.StackTrace);
                                }
                            }
                        }
                        break;

                    case "4":
                        // Quit
                        loop = false;
                        break;

                    default:
                        Console.WriteLine("ERROR: Unknown command.");
                        break;
                }
            } while (loop);
        }
        /// <summary>
        /// This method starts the workflow execution.
        /// </summary>
        /// <param name="bucket"></param>
        /// <param name="filepath"></param>
        public void StartWorkflowExecution(int RequestId)
        {
            System.Threading.Tasks.Task.Run(() =>
            {
                try
                {
                    //IAmazonS3 s3Client = new AmazonS3Client();
                    IAmazonSimpleWorkflow swfClient = new AmazonSimpleWorkflowClient();

                    //this._console.WriteLine("Create bucket if it doesn't exist");
                    // Make sure bucket exists
                    //s3Client.PutBucket(new PutBucketRequest
                    //{
                    //    BucketName = bucket,
                    //    UseClientRegion = true
                    //});

                    //this._console.WriteLine("Uploading image to S3");
                    // Upload the image to S3 before starting the execution
                    //PutObjectRequest putRequest = new PutObjectRequest
                    //{
                    //    BucketName = bucket,
                    //    FilePath = filepath,
                    //    Key = Path.GetFileName(filepath)
                    //};

                    //// Add upload progress callback to print every increment of 10 percent uploaded to the console.
                    //int currentPercent = -1;
                    //putRequest.StreamTransferProgress = new EventHandler<Amazon.Runtime.StreamTransferProgressArgs>((x, args) =>
                    //{
                    //    if (args.PercentDone == currentPercent)
                    //        return;

                    //    currentPercent = args.PercentDone;
                    //    if (currentPercent % 10 == 0)
                    //    {
                    //        this._console.WriteLine(string.Format("... Uploaded {0} %", currentPercent));
                    //    }
                    //});

                    //s3Client.PutObject(putRequest);

                    // Setup the input for the workflow execution that tells the execution what bukcet and object to use.
                    Common.WorkflowExecutionStartedInput input = new Common.WorkflowExecutionStartedInput
                    {
                        RequestId = RequestId
                    };

                    Console.WriteLine("Start workflow execution");
                    // Start the workflow execution
                    swfClient.StartWorkflowExecution(new StartWorkflowExecutionRequest()
                    {
                        //Serialize input to a string
                        Input = Common.Utils.SerializeToJSON<Common.WorkflowExecutionStartedInput>(input),
                        //Unique identifier for the execution
                        WorkflowId = DateTime.Now.Ticks.ToString(),
                        Domain = Common.Constants.WFDomain,
                        WorkflowType = new WorkflowType()
                        {
                            Name = Shared.Constants.WFWorkflow,
                            Version = Shared.Constants.WFWorkflowVersion
                        }
                    });
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error starting workflow execution: " + e.Message);
                }
            });
        }