diff --git a/Directory.Packages.props b/Directory.Packages.props index f8a422af..5ab0ff95 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,7 +31,7 @@ - + diff --git a/src/Worker/Core/Shims/TaskOrchestrationContextWrapper.cs b/src/Worker/Core/Shims/TaskOrchestrationContextWrapper.cs index 945d6ac5..98ba2721 100644 --- a/src/Worker/Core/Shims/TaskOrchestrationContextWrapper.cs +++ b/src/Worker/Core/Shims/TaskOrchestrationContextWrapper.cs @@ -226,7 +226,8 @@ public override async Task CallSubOrchestratorAsync( version, instanceId, policy.ToDurableTaskCoreRetryOptions(), - input); + input, + options.Tags); } else if (options?.Retry?.Handler is AsyncRetryHandler handler) { diff --git a/test/Grpc.IntegrationTests/OrchestrationPatterns.cs b/test/Grpc.IntegrationTests/OrchestrationPatterns.cs index d52c271c..1114029b 100644 --- a/test/Grpc.IntegrationTests/OrchestrationPatterns.cs +++ b/test/Grpc.IntegrationTests/OrchestrationPatterns.cs @@ -59,7 +59,6 @@ public async Task ScheduleOrchestrationWithTags() instanceId, this.TimeoutToken); Assert.NotNull(metadata); - Assert.Equal(instanceId, metadata.InstanceId); Assert.Equal(OrchestrationRuntimeStatus.Completed, metadata.RuntimeStatus); Assert.NotNull(metadata.Tags); Assert.Equal(2, metadata.Tags.Count); @@ -105,7 +104,6 @@ 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); @@ -113,6 +111,66 @@ public async Task ScheduleSubOrchestrationWithTags() 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 + { + { "tag1", "value1" }, + { "tag2", "value2" } + }, + Retry = new RetryPolicy(maxNumberOfAttempts: 2, firstRetryInterval: TimeSpan.FromMilliseconds(500)) + }; + + int failCounter = 0; + int invocationCounter = 0; + await using HostTestLifetime server = await this.StartWorkerAsync(b => + { + b.AddTasks(tasks => tasks.AddOrchestratorFunc(orchestratorName, async (ctx, input) => + { + if (!ctx.IsReplaying) + { + invocationCounter++; + } + 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(orchestratorName, input: input + 1, subOrchestrationOptions); + } + + return result; + })); + }); + + await server.Client.ScheduleNewOrchestrationInstanceAsync(orchestratorName, input: 1); + + // Confirm the orchestration eventually succeeded after some delay for the retry to complete + await Task.Delay(TimeSpan.FromSeconds(3)); + OrchestrationMetadata metadata = await server.Client.WaitForInstanceCompletionAsync( + subOrchestrationOptions.InstanceId, this.TimeoutToken); + Assert.NotNull(metadata); + 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"]); + // 3 invocations - one for the parent orchestration, one for the first suborchestration attempt, one for the final suborchestration attempt + Assert.Equal(3, invocationCounter); + } + [Fact] public async Task SingleTimer() {