From d94d415023685113c32027d67687a251cb88696a Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 24 Oct 2023 14:06:34 -0500 Subject: [PATCH 1/3] Support workflow start delay --- .../Client/TemporalClient.Workflow.cs | 4 ++++ src/Temporalio/Client/WorkflowOptions.cs | 5 +++++ .../Client/TemporalClientWorkflowTests.cs | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/Temporalio/Client/TemporalClient.Workflow.cs b/src/Temporalio/Client/TemporalClient.Workflow.cs index 0cfad9ed..142cee1d 100644 --- a/src/Temporalio/Client/TemporalClient.Workflow.cs +++ b/src/Temporalio/Client/TemporalClient.Workflow.cs @@ -439,6 +439,10 @@ private async Task> StartWorkflowInternalAsyn { req.SearchAttributes = input.Options.TypedSearchAttributes.ToProto(); } + if (input.Options.StartDelay is { } startDelay) + { + req.WorkflowStartDelay = Duration.FromTimeSpan(startDelay); + } if (input.Headers != null) { req.Header = new(); diff --git a/src/Temporalio/Client/WorkflowOptions.cs b/src/Temporalio/Client/WorkflowOptions.cs index 3b89c6ba..1f228c70 100644 --- a/src/Temporalio/Client/WorkflowOptions.cs +++ b/src/Temporalio/Client/WorkflowOptions.cs @@ -80,6 +80,11 @@ public WorkflowOptions(string id, string taskQueue) /// public SearchAttributeCollection? TypedSearchAttributes { get; set; } + /// + /// Gets or sets the amount of time to wait before starting the workflow. + /// + public TimeSpan? StartDelay { get; set; } + /// /// Gets or sets the start signal for the workflow. If this is non-null, a signal-with-start /// is used instead of a traditional workflow start. This means the workflow will only be diff --git a/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs b/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs index 6bc327b3..f8822d83 100644 --- a/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs +++ b/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs @@ -83,6 +83,25 @@ await Client.StartWorkflowAsync( }); } + [Fact] + public async Task StartWorkflowAsync_StartDelay_WaitsProperly() + { + var arg = new KSWorkflowParams(new KSAction(Result: new(Value: "Some String"))); + var handle = await Client.StartWorkflowAsync( + (IKitchenSinkWorkflowWithUnknownReturn wf) => wf.RunAsync(arg), + new(id: $"workflow-{Guid.NewGuid()}", taskQueue: Env.KitchenSinkWorkerTaskQueue) + { + StartDelay = TimeSpan.FromMinutes(45), + }); + // Check that first event has start delay + await using var enumerator = handle.FetchHistoryEventsAsync().GetAsyncEnumerator(); + Assert.True(await enumerator.MoveNextAsync()); + var attrs = enumerator.Current.WorkflowExecutionStartedEventAttributes; + Assert.Equal( + TimeSpan.FromMinutes(45), + enumerator.Current.WorkflowExecutionStartedEventAttributes.FirstWorkflowTaskBackoff.ToTimeSpan()); + } + [Fact] public async Task StartWorkflowAsync_StartSignal_Succeeds() { From 0be0ff4404e6d66048110dd2dcec52fe83c7d143 Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 24 Oct 2023 14:22:08 -0500 Subject: [PATCH 2/3] CI fix --- tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs b/tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs index 41873f28..3bb60884 100644 --- a/tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs +++ b/tests/Temporalio.Tests/Testing/WorkflowEnvironmentTests.cs @@ -156,9 +156,8 @@ await worker.ExecuteAsync(async () => new(id: $"workflow-{Guid.NewGuid()}", taskQueue: worker.Options.TaskQueue!))); // Check causes too var actExc = Assert.IsType(exc.InnerException); - var toExc1 = Assert.IsType(actExc.InnerException); - var toExc2 = Assert.IsType(toExc1.InnerException); - Assert.Equal(TimeoutType.Heartbeat, toExc2.TimeoutType); + var toExc = Assert.IsType(actExc.InnerException); + Assert.Equal(TimeoutType.Heartbeat, toExc.TimeoutType); }); } From 5cf563f4f5c7367ab63ceb1141bc0d119f273ca6 Mon Sep 17 00:00:00 2001 From: Chad Retz Date: Tue, 24 Oct 2023 15:59:30 -0500 Subject: [PATCH 3/3] PR fixes --- .../Client/TemporalClient.Workflow.cs | 1 + src/Temporalio/Client/WorkflowOptions.cs | 2 ++ .../Client/TemporalClientWorkflowTests.cs | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/Temporalio/Client/TemporalClient.Workflow.cs b/src/Temporalio/Client/TemporalClient.Workflow.cs index 142cee1d..ca04427b 100644 --- a/src/Temporalio/Client/TemporalClient.Workflow.cs +++ b/src/Temporalio/Client/TemporalClient.Workflow.cs @@ -493,6 +493,7 @@ private async Task> StartWorkflowInternalAsyn Memo = req.Memo, SearchAttributes = req.SearchAttributes, Header = req.Header, + WorkflowStartDelay = req.WorkflowStartDelay, SignalName = input.Options.StartSignal, }; if (input.Options.StartSignalArgs != null && input.Options.StartSignalArgs.Count > 0) diff --git a/src/Temporalio/Client/WorkflowOptions.cs b/src/Temporalio/Client/WorkflowOptions.cs index 1f228c70..2d10b28f 100644 --- a/src/Temporalio/Client/WorkflowOptions.cs +++ b/src/Temporalio/Client/WorkflowOptions.cs @@ -83,6 +83,8 @@ public WorkflowOptions(string id, string taskQueue) /// /// Gets or sets the amount of time to wait before starting the workflow. /// + /// Start delay does not work with . + /// WARNING: Start delay is experimental. public TimeSpan? StartDelay { get; set; } /// diff --git a/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs b/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs index f8822d83..36f907de 100644 --- a/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs +++ b/tests/Temporalio.Tests/Client/TemporalClientWorkflowTests.cs @@ -102,6 +102,26 @@ public async Task StartWorkflowAsync_StartDelay_WaitsProperly() enumerator.Current.WorkflowExecutionStartedEventAttributes.FirstWorkflowTaskBackoff.ToTimeSpan()); } + [Fact] + public async Task StartWorkflowAsync_SignalWithStartDelay_WaitsProperly() + { + var arg = new KSWorkflowParams(new KSAction(Result: new(Value: "Some String"))); + var handle = await Client.StartWorkflowAsync( + (IKitchenSinkWorkflowWithUnknownReturn wf) => wf.RunAsync(arg), + new(id: $"workflow-{Guid.NewGuid()}", taskQueue: Env.KitchenSinkWorkerTaskQueue) + { + StartDelay = TimeSpan.FromMinutes(45), + StartSignal = "some-signal", + }); + // Check that first event has start delay + await using var enumerator = handle.FetchHistoryEventsAsync().GetAsyncEnumerator(); + Assert.True(await enumerator.MoveNextAsync()); + var attrs = enumerator.Current.WorkflowExecutionStartedEventAttributes; + Assert.Equal( + TimeSpan.FromMinutes(45), + enumerator.Current.WorkflowExecutionStartedEventAttributes.FirstWorkflowTaskBackoff.ToTimeSpan()); + } + [Fact] public async Task StartWorkflowAsync_StartSignal_Succeeds() {