forked from temporalio/features
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dotnet Update Features (temporalio#418)
- Loading branch information
1 parent
42a71ad
commit 69ca251
Showing
14 changed files
with
745 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
namespace update.basic; | ||
|
||
using Temporalio.Exceptions; | ||
using Temporalio.Client; | ||
using Temporalio.Features.Harness; | ||
using Temporalio.Worker; | ||
using Temporalio.Workflows; | ||
|
||
class Feature : IFeature | ||
{ | ||
[Workflow] | ||
class MyWorkflow | ||
{ | ||
private bool shutdown; | ||
|
||
[WorkflowRun] | ||
public Task RunAsync() => Workflow.WaitConditionAsync(() => shutdown); | ||
|
||
[WorkflowUpdate] | ||
public async Task<string> MyUpdate(string _) | ||
{ | ||
shutdown = true; | ||
return "hi"; | ||
} | ||
|
||
[WorkflowUpdateValidator(nameof(MyUpdate))] | ||
public void ValidateMyUpdate(string arg) | ||
{ | ||
if (arg == "invalid") | ||
{ | ||
throw new ApplicationFailureException("invalid"); | ||
} | ||
} | ||
} | ||
|
||
public void ConfigureWorker(Runner runner, TemporalWorkerOptions options) => | ||
options.AddWorkflow<MyWorkflow>(); | ||
|
||
public async Task<WorkflowHandle?> ExecuteAsync(Runner runner) | ||
{ | ||
await runner.SkipIfUpdateNotSupportedAsync(); | ||
|
||
var handle = await runner.Client.StartWorkflowAsync( | ||
(MyWorkflow wf) => wf.RunAsync(), | ||
runner.NewWorkflowOptions()); | ||
|
||
try | ||
{ | ||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate("invalid")); | ||
throw new Exception("Expected to fail"); | ||
} | ||
catch (WorkflowUpdateFailedException) | ||
{ | ||
// Expected | ||
} | ||
|
||
Assert.Equal("hi", await handle.ExecuteUpdateAsync(wf => wf.MyUpdate("valid"))); | ||
return handle; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
namespace update.basic_async; | ||
|
||
using Temporalio.Exceptions; | ||
using Temporalio.Client; | ||
using Temporalio.Features.Harness; | ||
using Temporalio.Worker; | ||
using Temporalio.Workflows; | ||
|
||
class Feature : IFeature | ||
{ | ||
[Workflow] | ||
class MyWorkflow | ||
{ | ||
private bool shutdown; | ||
|
||
[WorkflowRun] | ||
public Task RunAsync() => Workflow.WaitConditionAsync(() => shutdown); | ||
|
||
[WorkflowUpdate] | ||
public async Task<string> MyUpdate(string _) | ||
{ | ||
shutdown = true; | ||
return "hi"; | ||
} | ||
|
||
[WorkflowUpdateValidator(nameof(MyUpdate))] | ||
public void ValidateMyUpdate(string arg) | ||
{ | ||
if (arg == "invalid") | ||
{ | ||
throw new ApplicationFailureException("invalid"); | ||
} | ||
} | ||
} | ||
|
||
public void ConfigureWorker(Runner runner, TemporalWorkerOptions options) => | ||
options.AddWorkflow<MyWorkflow>(); | ||
|
||
public async Task<WorkflowHandle?> ExecuteAsync(Runner runner) | ||
{ | ||
await runner.SkipIfUpdateNotSupportedAsync(); | ||
|
||
var handle = await runner.Client.StartWorkflowAsync( | ||
(MyWorkflow wf) => wf.RunAsync(), | ||
runner.NewWorkflowOptions()); | ||
|
||
var badUpdateHandle = await handle.StartUpdateAsync(wf => wf.MyUpdate("invalid")); | ||
|
||
try | ||
{ | ||
await badUpdateHandle.GetResultAsync(); | ||
throw new Exception("Expected to fail"); | ||
} | ||
catch (WorkflowUpdateFailedException) | ||
{ | ||
// Expected | ||
} | ||
|
||
var goodUpdateHandle = await handle.StartUpdateAsync(wf => wf.MyUpdate("valid")); | ||
Assert.Equal("hi", await goodUpdateHandle.GetResultAsync()); | ||
|
||
return handle; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
namespace update.client_interceptor; | ||
|
||
using Temporalio.Client.Interceptors; | ||
using Temporalio.Client; | ||
using Temporalio.Features.Harness; | ||
using Temporalio.Worker; | ||
using Temporalio.Workflows; | ||
|
||
class MyOutboundClientInterceptor : IClientInterceptor | ||
{ | ||
public ClientOutboundInterceptor InterceptClient( | ||
ClientOutboundInterceptor nextInterceptor) => | ||
new ClientOutbound(nextInterceptor); | ||
|
||
private sealed class ClientOutbound : ClientOutboundInterceptor | ||
{ | ||
public ClientOutbound(ClientOutboundInterceptor next) : base(next) | ||
{ | ||
} | ||
|
||
public override Task<WorkflowUpdateHandle<TResult>> StartWorkflowUpdateAsync<TResult>( | ||
StartWorkflowUpdateInput input) | ||
{ | ||
var newInput = input with { Args = new object[] { "intercepted" } }; | ||
return base.StartWorkflowUpdateAsync<TResult>(newInput); | ||
} | ||
} | ||
} | ||
|
||
class Feature : IFeature | ||
{ | ||
[Workflow] | ||
class MyWorkflow | ||
{ | ||
private bool shutdown; | ||
|
||
[WorkflowRun] | ||
public Task RunAsync() => Workflow.WaitConditionAsync(() => shutdown); | ||
|
||
[WorkflowUpdate] | ||
public async Task<string> MyUpdate(string arg) | ||
{ | ||
shutdown = true; | ||
return arg; | ||
} | ||
} | ||
|
||
public void ConfigureClient(Runner runner, TemporalClientConnectOptions options) | ||
{ | ||
options.Interceptors = new[] { new MyOutboundClientInterceptor() }; | ||
} | ||
|
||
public void ConfigureWorker(Runner runner, TemporalWorkerOptions options) | ||
{ | ||
options.AddWorkflow<MyWorkflow>(); | ||
} | ||
|
||
public async Task<WorkflowHandle?> ExecuteAsync(Runner runner) | ||
{ | ||
await runner.SkipIfUpdateNotSupportedAsync(); | ||
|
||
var handle = await runner.Client.StartWorkflowAsync( | ||
(MyWorkflow wf) => wf.RunAsync(), | ||
runner.NewWorkflowOptions()); | ||
|
||
Assert.Equal("intercepted", await handle.ExecuteUpdateAsync(wf => wf.MyUpdate("Enchicat"))); | ||
|
||
return handle; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
namespace update.deduplication; | ||
|
||
using Temporalio.Client; | ||
using Temporalio.Features.Harness; | ||
using Temporalio.Worker; | ||
using Temporalio.Workflows; | ||
|
||
class Feature : IFeature | ||
{ | ||
[Workflow] | ||
class MyWorkflow | ||
{ | ||
private bool shutdown; | ||
|
||
[WorkflowRun] | ||
public Task RunAsync() => Workflow.WaitConditionAsync(() => shutdown); | ||
|
||
[WorkflowUpdate] | ||
public async Task<int> MyUpdate(bool exit) | ||
{ | ||
shutdown = exit; | ||
Count++; | ||
return Count; | ||
} | ||
|
||
[WorkflowQuery] | ||
public int Count { get; set; } | ||
} | ||
|
||
public void ConfigureWorker(Runner runner, TemporalWorkerOptions options) | ||
{ | ||
options.AddWorkflow<MyWorkflow>(); | ||
} | ||
|
||
public async Task<WorkflowHandle?> ExecuteAsync(Runner runner) | ||
{ | ||
await runner.SkipIfUpdateNotSupportedAsync(); | ||
|
||
var handle = await runner.Client.StartWorkflowAsync( | ||
(MyWorkflow wf) => wf.RunAsync(), | ||
runner.NewWorkflowOptions()); | ||
|
||
var updateId = "myid"; | ||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate(false), new() {UpdateID = updateId}); | ||
Assert.Equal(1, await handle.QueryAsync(wf => wf.Count)); | ||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate(false), new() {UpdateID = updateId}); | ||
Assert.Equal(1, await handle.QueryAsync(wf => wf.Count)); | ||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate(true)); | ||
|
||
return handle; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
using Temporalio.Api.Enums.V1; | ||
|
||
namespace update.non_durable_reject; | ||
|
||
using Temporalio.Exceptions; | ||
using Temporalio.Client; | ||
using Temporalio.Features.Harness; | ||
using Temporalio.Worker; | ||
using Temporalio.Workflows; | ||
|
||
class Feature : IFeature | ||
{ | ||
[Workflow] | ||
class MyWorkflow | ||
{ | ||
private bool shutdown; | ||
|
||
[WorkflowRun] | ||
public Task RunAsync() => Workflow.WaitConditionAsync(() => shutdown); | ||
|
||
[WorkflowUpdate] | ||
public async Task<string> MyUpdate(string _) | ||
{ | ||
shutdown = true; | ||
return "hi"; | ||
} | ||
|
||
[WorkflowUpdateValidator(nameof(MyUpdate))] | ||
public void ValidateMyUpdate(string arg) | ||
{ | ||
if (arg == "invalid") | ||
{ | ||
throw new ApplicationFailureException("invalid"); | ||
} | ||
} | ||
} | ||
|
||
public void ConfigureWorker(Runner runner, TemporalWorkerOptions options) => | ||
options.AddWorkflow<MyWorkflow>(); | ||
|
||
public async Task<WorkflowHandle?> ExecuteAsync(Runner runner) | ||
{ | ||
await runner.SkipIfUpdateNotSupportedAsync(); | ||
|
||
var handle = await runner.Client.StartWorkflowAsync( | ||
(MyWorkflow wf) => wf.RunAsync(), | ||
runner.NewWorkflowOptions()); | ||
|
||
for (var i = 0; i < 5; i++) | ||
{ | ||
try | ||
{ | ||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate("invalid")); | ||
} | ||
catch (WorkflowUpdateFailedException) | ||
{ | ||
// Expected | ||
} | ||
} | ||
|
||
await handle.ExecuteUpdateAsync(wf => wf.MyUpdate("valid")); | ||
await handle.GetResultAsync(); | ||
|
||
// Verify there are no rejections written to history | ||
var history = await handle.FetchHistoryAsync(); | ||
Assert.DoesNotContain(history.Events, | ||
e => e.EventType == EventType.WorkflowExecutionUpdateRejected); | ||
|
||
return handle; | ||
} | ||
} |
Oops, something went wrong.