Container for the parameters to the PollForActivityTask operation. Used by workers to get an ActivityTask from the specified activity taskList. This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available. The maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll will return an empty result. An empty result, in this context, means that an ActivityTask is returned, but that the value of taskToken is an empty string. If a task is returned, the worker should use its type to identify and process it correctly. Workers should set their client side socket timeout to at least 70 seconds (10 seconds higher than the maximum time service may hold the poll request).

Access Control

You can use IAM policies to control this action's access to Amazon SWF resources as follows:

  • Use a Resource element with the domain name to limit the action to only specified domains.
  • Use an Action element to allow or deny permission to call this action.
  • Constrain the taskList.name parameter by using a Condition element with the swf:taskList.name key to allow the action to access only certain task lists.

If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified constraints, the action fails. The associated event attribute's cause parameter will be set to OPERATION_NOT_PERMITTED. For details and example IAM policies, see Using IAM to Manage Access to Amazon SWF Workflows.

Inheritance: AmazonSimpleWorkflowRequest
 ActivityTask Poll()
 {
     Logger.LogMessage("Polling for {0} activity task ...", ActivityType);
     PollForActivityTaskRequest request = new PollForActivityTaskRequest()
     {
         Domain = Constants.SWF_DOMAIN,
         TaskList = new TaskList()
         {
             Name = this.ActivityTaskList
         }
     };
     PollForActivityTaskResponse response = this._swfClient.PollForActivityTaskAsync(request).Result;
     return response.ActivityTask;
 }
Exemple #2
0
 /// <summary>
 /// Initiates the asynchronous execution of the PollForActivityTask operation.
 /// <seealso cref="Amazon.SimpleWorkflow.AmazonSimpleWorkflow.PollForActivityTask"/>
 /// </summary>
 /// 
 /// <param name="pollForActivityTaskRequest">Container for the necessary parameters to execute the PollForActivityTask operation on
 ///          AmazonSimpleWorkflow.</param>
 /// <param name="callback">An AsyncCallback delegate that is invoked when the operation completes.</param>
 /// <param name="state">A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback
 ///          procedure using the AsyncState property.</param>
 /// 
 /// <returns>An IAsyncResult that can be used to poll or wait for results, or both; this value is also needed when invoking
 ///         EndPollForActivityTask operation.</returns>
 public IAsyncResult BeginPollForActivityTask(PollForActivityTaskRequest pollForActivityTaskRequest, AsyncCallback callback, object state)
 {
     return invokePollForActivityTask(pollForActivityTaskRequest, callback, state, false);
 }
Exemple #3
0
 IAsyncResult invokePollForActivityTask(PollForActivityTaskRequest pollForActivityTaskRequest, AsyncCallback callback, object state, bool synchronized)
 {
     IRequest irequest = new PollForActivityTaskRequestMarshaller().Marshall(pollForActivityTaskRequest);
     var unmarshaller = PollForActivityTaskResponseUnmarshaller.GetInstance();
     AsyncResult result = new AsyncResult(irequest, callback, state, synchronized, signer, unmarshaller);
     Invoke(result);
     return result;
 }
Exemple #4
0
 /// <summary>
 /// <para> Used by workers to get an ActivityTask from the specified activity <c>taskList</c> .
 /// This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available. The
 /// maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll will
 /// return an empty result. An empty result, in this context, means that an ActivityTask is returned, but that the value of taskToken is an
 /// empty string. If a task is returned, the worker should use its type to identify and process it correctly. </para> <para><b>IMPORTANT:</b>
 /// Workers should set their client side socket timeout to at least 70 seconds (10 seconds higher than the maximum time service may hold the
 /// poll request). </para>
 /// </summary>
 /// 
 /// <param name="pollForActivityTaskRequest">Container for the necessary parameters to execute the PollForActivityTask service method on
 ///          AmazonSimpleWorkflow.</param>
 /// 
 /// <returns>The response from the PollForActivityTask service method, as returned by AmazonSimpleWorkflow.</returns>
 /// 
 /// <exception cref="OperationNotPermittedException"/>
 /// <exception cref="UnknownResourceException"/>
 public PollForActivityTaskResponse PollForActivityTask(PollForActivityTaskRequest pollForActivityTaskRequest)
 {
     IAsyncResult asyncResult = invokePollForActivityTask(pollForActivityTaskRequest, null, null, true);
     return EndPollForActivityTask(asyncResult);
 }
        /// <summary>
        /// <para> Used by workers to get an ActivityTask from the specified activity <c>taskList</c> .
        /// This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available. The
        /// maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll will
        /// return an empty result. An empty result, in this context, means that an ActivityTask is returned, but that the value of taskToken is an
        /// empty string. If a task is returned, the worker should use its type to identify and process it correctly. </para> <para><b>IMPORTANT:</b>
        /// Workers should set their client side socket timeout to at least 70 seconds (10 seconds higher than the maximum time service may hold the
        /// poll request). </para> <para> <b>Access Control</b> </para> <para>You can use IAM policies to control this action's access to Amazon SWF
        /// resources as follows:</para>
        /// <ul>
        /// <li>Use a <c>Resource</c> element with the domain name to limit the action to only specified domains.</li>
        /// <li>Use an <c>Action</c> element to allow or deny permission to call this action.</li>
        /// <li>Constrain the <c>taskList.name</c> parameter by using a <b>Condition</b> element with the <c>swf:taskList.name</c> key to allow the
        /// action to access only certain task lists.</li>
        /// 
        /// </ul>
        /// <para>If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified
        /// constraints, the action fails by throwing <c>OperationNotPermitted</c> . For details and example IAM policies, see <a href="http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dev-iam.html">Using IAM to Manage Access to Amazon SWF Workflows</a>
        /// .</para>
        /// </summary>
        /// 
        /// <param name="pollForActivityTaskRequest">Container for the necessary parameters to execute the PollForActivityTask service method on
        /// AmazonSimpleWorkflow.</param>
        /// 
        /// <returns>The response from the PollForActivityTask service method, as returned by AmazonSimpleWorkflow.</returns>
        /// 
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.OperationNotPermittedException" />
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.UnknownResourceException" />
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.LimitExceededException" />
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
		public Task<PollForActivityTaskResponse> PollForActivityTaskAsync(PollForActivityTaskRequest pollForActivityTaskRequest, CancellationToken cancellationToken = default(CancellationToken))
        {
            var marshaller = new PollForActivityTaskRequestMarshaller();
            var unmarshaller = PollForActivityTaskResponseUnmarshaller.GetInstance();
            return Invoke<IRequest, PollForActivityTaskRequest, PollForActivityTaskResponse>(pollForActivityTaskRequest, marshaller, unmarshaller, signer, cancellationToken);
        }
		internal PollForActivityTaskResponse PollForActivityTask(PollForActivityTaskRequest request)
        {
            var task = PollForActivityTaskAsync(request);
            try
            {
                return task.Result;
            }
            catch(AggregateException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();
                return null;
            }
        }
        /// <summary>
        /// Initiates the asynchronous execution of the PollForActivityTask operation.
        /// <seealso cref="Amazon.SimpleWorkflow.IAmazonSimpleWorkflow"/>
        /// </summary>
        /// 
        /// <param name="request">Container for the necessary parameters to execute the PollForActivityTask operation.</param>
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public Task<PollForActivityTaskResponse> PollForActivityTaskAsync(PollForActivityTaskRequest request, System.Threading.CancellationToken cancellationToken = default(CancellationToken))
        {
            var marshaller = new PollForActivityTaskRequestMarshaller();
            var unmarshaller = PollForActivityTaskResponseUnmarshaller.Instance;

            return InvokeAsync<PollForActivityTaskRequest,PollForActivityTaskResponse>(request, marshaller, 
                unmarshaller, cancellationToken);
        }
        /// <summary>
        /// Used by workers to get an <a>ActivityTask</a> from the specified activity <code>taskList</code>.
        /// This initiates a long poll, where the service holds the HTTP connection open and responds
        /// as soon as a task becomes available. The maximum time the service holds on to the
        /// request before responding is 60 seconds. If no task is available within 60 seconds,
        /// the poll will return an empty result. An empty result, in this context, means that
        /// an ActivityTask is returned, but that the value of taskToken is an empty string. If
        /// a task is returned, the worker should use its type to identify and process it correctly.
        /// 
        /// 
        ///  <important> Workers should set their client side socket timeout to at least 70 seconds
        /// (10 seconds higher than the maximum time service may hold the poll request). </important>
        /// 
        /// <para>
        /// <b>Access Control</b>
        /// </para>
        ///  
        /// <para>
        /// You can use IAM policies to control this action's access to Amazon SWF resources as
        /// follows:
        /// </para>
        ///  <ul> <li>Use a <code>Resource</code> element with the domain name to limit the action
        /// to only specified domains.</li> <li>Use an <code>Action</code> element to allow or
        /// deny permission to call this action.</li> <li>Constrain the <code>taskList.name</code>
        /// parameter by using a <b>Condition</b> element with the <code>swf:taskList.name</code>
        /// key to allow the action to access only certain task lists.</li> </ul> 
        /// <para>
        /// If the caller does not have sufficient permissions to invoke the action, or the parameter
        /// values fall outside the specified constraints, the action fails by throwing <code>OperationNotPermitted</code>.
        /// For details and example IAM policies, see <a href="http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dev-iam.html">Using
        /// IAM to Manage Access to Amazon SWF Workflows</a>.
        /// </para>
        /// </summary>
        /// <param name="request">Container for the necessary parameters to execute the PollForActivityTask service method.</param>
        /// 
        /// <returns>The response from the PollForActivityTask service method, as returned by SimpleWorkflow.</returns>
        /// <exception cref="LimitExceededException">
        /// Returned by any operation if a system imposed limitation has been reached. To address
        /// this fault you should either clean up unused resources or increase the limit by contacting
        /// AWS.
        /// </exception>
        /// <exception cref="OperationNotPermittedException">
        /// Returned when the caller does not have sufficient permissions to invoke the action.
        /// </exception>
        /// <exception cref="UnknownResourceException">
        /// Returned when the named resource cannot be found with in the scope of this operation
        /// (region or domain). This could happen if the named resource was never created or is
        /// no longer available for this operation.
        /// </exception>
        public PollForActivityTaskResponse PollForActivityTask(PollForActivityTaskRequest request)
        {
            var marshaller = new PollForActivityTaskRequestMarshaller();
            var unmarshaller = PollForActivityTaskResponseUnmarshaller.Instance;

            return Invoke<PollForActivityTaskRequest,PollForActivityTaskResponse>(request, marshaller, unmarshaller);
        }
        /// <summary>
        /// Initiates the asynchronous execution of the PollForActivityTask operation.
        /// </summary>
        /// 
        /// <param name="request">Container for the necessary parameters to execute the PollForActivityTask operation on AmazonSimpleWorkflowClient.</param>
        /// <param name="callback">An AsyncCallback delegate that is invoked when the operation completes.</param>
        /// <param name="state">A user-defined state object that is passed to the callback procedure. Retrieve this object from within the callback
        ///          procedure using the AsyncState property.</param>
        /// 
        /// <returns>An IAsyncResult that can be used to poll or wait for results, or both; this value is also needed when invoking EndPollForActivityTask
        ///         operation.</returns>
        public IAsyncResult BeginPollForActivityTask(PollForActivityTaskRequest request, AsyncCallback callback, object state)
        {
            var marshaller = new PollForActivityTaskRequestMarshaller();
            var unmarshaller = PollForActivityTaskResponseUnmarshaller.Instance;

            return BeginInvoke<PollForActivityTaskRequest>(request, marshaller, unmarshaller,
                callback, state);
        }
        /// <summary>
        /// <para> Used by workers to get an ActivityTask from the specified activity <c>taskList</c> .
        /// This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available. The
        /// maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll will
        /// return an empty result. An empty result, in this context, means that an ActivityTask is returned, but that the value of taskToken is an
        /// empty string. If a task is returned, the worker should use its type to identify and process it correctly. </para> <para><b>IMPORTANT:</b>
        /// Workers should set their client side socket timeout to at least 70 seconds (10 seconds higher than the maximum time service may hold the
        /// poll request). </para> <para> <b>Access Control</b> </para> <para>You can use IAM policies to control this action's access to Amazon SWF
        /// resources as follows:</para>
        /// <ul>
        /// <li>Use a <c>Resource</c> element with the domain name to limit the action to only specified domains.</li>
        /// <li>Use an <c>Action</c> element to allow or deny permission to call this action.</li>
        /// <li>Constrain the <c>taskList.name</c> parameter by using a <b>Condition</b> element with the <c>swf:taskList.name</c> key to allow the
        /// action to access only certain task lists.</li>
        /// 
        /// </ul>
        /// <para>If the caller does not have sufficient permissions to invoke the action, or the parameter values fall outside the specified
        /// constraints, the action fails by throwing <c>OperationNotPermitted</c> . For details and example IAM policies, see <a href="http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dev-iam.html">Using IAM to Manage Access to Amazon SWF Workflows</a>
        /// .</para>
        /// </summary>
        /// 
        /// <param name="pollForActivityTaskRequest">Container for the necessary parameters to execute the PollForActivityTask service method on
        /// AmazonSimpleWorkflow.</param>
        /// 
        /// <returns>The response from the PollForActivityTask service method, as returned by AmazonSimpleWorkflow.</returns>
        /// 
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.OperationNotPermittedException" />
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.UnknownResourceException" />
        /// <exception cref="T:Amazon.SimpleWorkflow.Model.LimitExceededException" />
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
		public async Task<PollForActivityTaskResponse> PollForActivityTaskAsync(PollForActivityTaskRequest pollForActivityTaskRequest, CancellationToken cancellationToken = default(CancellationToken))
        {
            var marshaller = new PollForActivityTaskRequestMarshaller();
            var unmarshaller = PollForActivityTaskResponseUnmarshaller.GetInstance();
            var response = await Invoke<IRequest, PollForActivityTaskRequest, PollForActivityTaskResponse>(pollForActivityTaskRequest, marshaller, unmarshaller, signer, cancellationToken)
                .ConfigureAwait(continueOnCapturedContext: false);
            return response;
        }
		internal PollForActivityTaskResponse PollForActivityTask(PollForActivityTaskRequest request)
        {
            var task = PollForActivityTaskAsync(request);
            try
            {
                return task.Result;
            }
            catch(AggregateException e)
            {
                throw e.InnerException;
            }
        }
Exemple #12
0
 /// <summary>
 /// Poll the image processing activity task list to see if work needs to be done.
 /// </summary>
 /// <returns></returns>
 ActivityTask Poll()
 {
     Console.WriteLine("Polling for activity task ...");
     PollForActivityTaskRequest request = new PollForActivityTaskRequest()
     {
         Domain = Common.Constants.WFDomain,
         TaskList = new TaskList()
         {
             Name = Shared.Constants.WFTaskList
         }
     };
     PollForActivityTaskResponse response = swfClient.PollForActivityTask(request);
     return response.ActivityTask;
 }
Exemple #13
0
        static void Worker(string tasklistName)
        {
            string prefix = string.Format("Worker{0}:{1:x} ", tasklistName,
                            System.Threading.Thread.CurrentThread.ManagedThreadId);
              while (true)
              {
            Console.WriteLine(prefix + ": Polling for activity task ...");
            PollForActivityTaskRequest pollForActivityTaskRequest =
            new PollForActivityTaskRequest() {
                                      Domain = domainName,
                                      TaskList = new TaskList()
                                      {
                                          // Poll only the tasks assigned to me
                                        Name = tasklistName
                                      }
                                };
            PollForActivityTaskResponse pollForActivityTaskResponse =
                        swfClient.PollForActivityTask(pollForActivityTaskRequest);

            RespondActivityTaskCompletedRequest respondActivityTaskCompletedRequest =
                    new RespondActivityTaskCompletedRequest() {
                              Result = "{\"activityResult1\":\"Result Value1\"}",
                              TaskToken = pollForActivityTaskResponse.ActivityTask.TaskToken
                            };
            if (pollForActivityTaskResponse.ActivityTask.ActivityId == null)
            {
              Console.WriteLine(prefix + ": NULL");
            }
            else
            {
              RespondActivityTaskCompletedResponse respondActivityTaskCompletedResponse =
              swfClient.RespondActivityTaskCompleted(respondActivityTaskCompletedRequest);
              Console.WriteLine(prefix + ": Activity task completed. ActivityId - " +
              pollForActivityTaskResponse.ActivityTask.ActivityId);
            }
              }
        }
 /// <summary>
 /// <para> Used by workers to get an ActivityTask from the specified activity <c>taskList</c> .
 /// This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available. The
 /// maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll will
 /// return an empty result. An empty result, in this context, means that an ActivityTask is returned, but that the value of taskToken is an
 /// empty string. If a task is returned, the worker should use its type to identify and process it correctly. </para> <para><b>IMPORTANT:</b>
 /// Workers should set their client side socket timeout to at least 70 seconds (10 seconds higher than the maximum time service may hold the
 /// poll request). </para>
 /// </summary>
 /// 
 /// <param name="pollForActivityTaskRequest">Container for the necessary parameters to execute the PollForActivityTask service method on
 ///           AmazonSimpleWorkflow.</param>
 /// 
 /// <returns>The response from the PollForActivityTask service method, as returned by AmazonSimpleWorkflow.</returns>
 /// 
 /// <exception cref="OperationNotPermittedException"/>
 /// <exception cref="UnknownResourceException"/>
 public PollForActivityTaskResponse PollForActivityTask(PollForActivityTaskRequest pollForActivityTaskRequest)
 {
     IRequest<PollForActivityTaskRequest> request = new PollForActivityTaskRequestMarshaller().Marshall(pollForActivityTaskRequest);
     PollForActivityTaskResponse response = Invoke<PollForActivityTaskRequest, PollForActivityTaskResponse> (request, this.signer, PollForActivityTaskResponseUnmarshaller.GetInstance());
     return response;
 }
        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);
        }