Skip to content
Merged
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

<!-- DurableTask Packages -->
<ItemGroup>
<PackageVersion Include="Microsoft.Azure.DurableTask.Core" Version="3.6.0" />
<PackageVersion Include="Microsoft.Azure.DurableTask.Core" Version="3.7.0" />
<PackageVersion Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.12.1" />
</ItemGroup>

Expand Down
3 changes: 2 additions & 1 deletion src/Worker/Core/Shims/TaskOrchestrationContextWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ public override async Task<TResult> CallSubOrchestratorAsync<TResult>(
version,
instanceId,
policy.ToDurableTaskCoreRetryOptions(),
input);
input,
options.Tags);
}
else if (options?.Retry?.Handler is AsyncRetryHandler handler)
{
Expand Down
65 changes: 64 additions & 1 deletion test/Grpc.IntegrationTests/OrchestrationPatterns.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.DurableTask.Client;
Expand Down Expand Up @@ -105,7 +106,69 @@ public async Task ScheduleSubOrchestrationWithTags()
subOrchestrationOptions.InstanceId, this.TimeoutToken);

Assert.NotNull(metadata);
Assert.Equal(subOrchestrationOptions.InstanceId, metadata.InstanceId);
Assert.Equal(OrchestrationRuntimeStatus.Completed, metadata.RuntimeStatus);
Assert.NotNull(metadata.Tags);
Assert.Equal(2, metadata.Tags.Count);
Assert.Equal("value1", metadata.Tags["tag1"]);
Assert.Equal("value2", metadata.Tags["tag2"]);
}

[Fact]
public async Task ScheduleSubOrchestrationWithTagsAndRetryPolicy()
{
TaskName orchestratorName = nameof(ScheduleSubOrchestrationWithTagsAndRetryPolicy);

// Schedule a new orchestration instance with tags and a retry policy
SubOrchestrationOptions subOrchestrationOptions = new()
{
InstanceId = "instance_id",
Tags = new Dictionary<string, string>
{
{ "tag1", "value1" },
{ "tag2", "value2" }
},
Retry = new RetryPolicy(maxNumberOfAttempts: 2, firstRetryInterval: TimeSpan.FromSeconds(15))
};

int failCounter = 0;
await using HostTestLifetime server = await this.StartWorkerAsync(b =>
{
b.AddTasks(tasks => tasks.AddOrchestratorFunc<int, int>(orchestratorName, async (ctx, input) =>
{
if (failCounter < 1 && input == 2)
{
failCounter++;
throw new Exception("Simulated failure");
}

int result = 1;
if (input < 2)
{
// recursively call this same orchestrator
result += await ctx.CallSubOrchestratorAsync<int>(orchestratorName, input: input + 1, subOrchestrationOptions);
}

return result;
}));
});
using CancellationTokenSource timeoutTokenSource = new(TimeSpan.FromMinutes(1));

// Confirm the first attempt failed
await server.Client.ScheduleNewOrchestrationInstanceAsync(orchestratorName, input: 1);
OrchestrationMetadata metadata = await server.Client.WaitForInstanceCompletionAsync(
subOrchestrationOptions.InstanceId, timeoutTokenSource.Token);
Assert.NotNull(metadata);
Assert.Equal(OrchestrationRuntimeStatus.Failed, metadata.RuntimeStatus);

// Wait for the retry to happen
while (metadata.RuntimeStatus != OrchestrationRuntimeStatus.Completed && !timeoutTokenSource.Token.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1), timeoutTokenSource.Token);
metadata = await server.Client.WaitForInstanceCompletionAsync(
subOrchestrationOptions.InstanceId, timeoutTokenSource.Token);
}

// Confirm the second attempt succeeded
Assert.Equal(OrchestrationRuntimeStatus.Completed, metadata.RuntimeStatus);
Assert.NotNull(metadata.Tags);
Assert.Equal(2, metadata.Tags.Count);
Expand Down
Loading