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);
}