diff --git a/all.sln b/all.sln index 1dd0ab3c5..86e808c8d 100644 --- a/all.sln +++ b/all.sln @@ -97,6 +97,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BulkPublishEventExample", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowUnitTest", "examples\Workflow\WorkflowUnitTest\WorkflowUnitTest.csproj", "{8CA09061-2BEF-4506-A763-07062D2BD6AC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowMonitor", "examples\Workflow\WorkflowMonitor\WorkflowMonitor.csproj", "{0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GeneratedActor", "GeneratedActor", "{7592AFA4-426B-42F3-AE82-957C86814482}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActorClient", "examples\GeneratedActor\ActorClient\ActorClient.csproj", "{61C24126-F39D-4BEA-96DC-FC87BA730554}" @@ -263,6 +265,10 @@ Global {DDC41278-FB60-403A-B969-2AEBD7C2D83C}.Release|Any CPU.Build.0 = Release|Any CPU {8CA09061-2BEF-4506-A763-07062D2BD6AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CA09061-2BEF-4506-A763-07062D2BD6AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64}.Release|Any CPU.Build.0 = Release|Any CPU {61C24126-F39D-4BEA-96DC-FC87BA730554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {61C24126-F39D-4BEA-96DC-FC87BA730554}.Debug|Any CPU.Build.0 = Debug|Any CPU {61C24126-F39D-4BEA-96DC-FC87BA730554}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -348,6 +354,7 @@ Global {4A175C27-EAFE-47E7-90F6-873B37863656} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6} {DDC41278-FB60-403A-B969-2AEBD7C2D83C} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6} {8CA09061-2BEF-4506-A763-07062D2BD6AC} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9} + {0E3D4544-31FA-458D-8B1C-2F4E4B6D9E64} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9} {7592AFA4-426B-42F3-AE82-957C86814482} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78} {61C24126-F39D-4BEA-96DC-FC87BA730554} = {7592AFA4-426B-42F3-AE82-957C86814482} {CB903D21-4869-42EF-BDD6-5B1CFF674337} = {7592AFA4-426B-42F3-AE82-957C86814482} diff --git a/examples/Workflow/WorkflowMonitor/Activities/CheckStatus.cs b/examples/Workflow/WorkflowMonitor/Activities/CheckStatus.cs new file mode 100755 index 000000000..6f2eaf367 --- /dev/null +++ b/examples/Workflow/WorkflowMonitor/Activities/CheckStatus.cs @@ -0,0 +1,14 @@ +using Dapr.Workflow; + +namespace WorkflowMonitor.Activities +{ + public class CheckStatus : WorkflowActivity + { + static List status = new List() { "healthy", "unhealthy" }; + Random random = new Random(); + public override Task RunAsync(WorkflowActivityContext context, bool input) + { + return Task.FromResult(status[random.Next(status.Count)]); + } + } +} diff --git a/examples/Workflow/WorkflowMonitor/Program.cs b/examples/Workflow/WorkflowMonitor/Program.cs new file mode 100755 index 000000000..167cc6f05 --- /dev/null +++ b/examples/Workflow/WorkflowMonitor/Program.cs @@ -0,0 +1,57 @@ +using Dapr.Client; +using Dapr.Workflow; +using WorkflowMonitor.Activities; +using WorkflowMonitor.Workflows; +using Microsoft.Extensions.Hosting; + +const string DaprWorkflowComponent = "dapr"; + +// The workflow host is a background service that connects to the sidecar over gRPC +var builder = Host.CreateDefaultBuilder(args).ConfigureServices(services => +{ + services.AddDaprWorkflow(options => + { + options.RegisterWorkflow(); + options.RegisterActivity(); + }); +}); + +// Dapr uses a random port for gRPC by default. If we don't know what that port +// is (because this app was started separate from dapr), then assume 4001. +if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DAPR_GRPC_PORT"))) +{ + Environment.SetEnvironmentVariable("DAPR_GRPC_PORT", "4001"); +} + +// Start the app - this is the point where we connect to the Dapr sidecar to +// listen for workflow work-items to execute. +using var host = builder.Build(); +host.Start(); + + +DaprClient daprClient = new DaprClientBuilder().Build(); + +while (!await daprClient.CheckHealthAsync()) +{ + Thread.Sleep(TimeSpan.FromSeconds(5)); +} + +using (daprClient) +{ + Console.WriteLine($"Workflow Started."); + await daprClient.WaitForSidecarAsync(); + + string instanceId = $"demo-workflow-{Guid.NewGuid().ToString()[..8]}"; + + bool isHealthy = true; + await daprClient.StartWorkflowAsync( + workflowComponent: DaprWorkflowComponent, + workflowName: nameof(DemoWorkflow), + instanceId: instanceId, + input: isHealthy); + + + await daprClient.WaitForWorkflowCompletionAsync( + workflowComponent: DaprWorkflowComponent, + instanceId: instanceId); +} \ No newline at end of file diff --git a/examples/Workflow/WorkflowMonitor/WorkflowMonitor.csproj b/examples/Workflow/WorkflowMonitor/WorkflowMonitor.csproj new file mode 100755 index 000000000..9acf06b47 --- /dev/null +++ b/examples/Workflow/WorkflowMonitor/WorkflowMonitor.csproj @@ -0,0 +1,14 @@ + + + + + + + + Exe + net6 + enable + 612,618 + + + diff --git a/examples/Workflow/WorkflowMonitor/Workflows/DemoWorkflow.cs b/examples/Workflow/WorkflowMonitor/Workflows/DemoWorkflow.cs new file mode 100755 index 000000000..88f173d6c --- /dev/null +++ b/examples/Workflow/WorkflowMonitor/Workflows/DemoWorkflow.cs @@ -0,0 +1,39 @@ +using Dapr.Workflow; +using WorkflowMonitor.Activities; + +namespace WorkflowMonitor.Workflows +{ + public class DemoWorkflow : Workflow + { + public override async Task RunAsync(WorkflowContext context, bool isHealthy) + { + string status = await context.CallActivityAsync(nameof(CheckStatus), true); + int next_sleep_interval; + if (!context.IsReplaying) + { + Console.WriteLine($"This job is {status}"); + } + + if (status == "healthy") + { + isHealthy = true; + next_sleep_interval = 30; + } + else + { + if (isHealthy) + { + isHealthy = false; + } + Console.WriteLine($"Status is unhealthy. Set check interval to 1s"); + next_sleep_interval = 5; + } + + await context.CreateTimer(TimeSpan.FromSeconds(next_sleep_interval)); + context.ContinueAsNew(isHealthy); + + // This workflow will never complete. + return true; + } + } +}