Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Abstractions/TaskActivityContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ public abstract class TaskActivityContext
/// Gets the unique ID of the current orchestration instance.
/// </summary>
public abstract string InstanceId { get; }

/// <summary>
/// Gets the version that the activity was scheduled with, or <see cref="string.Empty"/> if the activity is
/// unversioned.
/// </summary>
public virtual string Version => string.Empty;
}
2 changes: 2 additions & 0 deletions src/Worker/Core/Shims/TaskActivityShim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,7 @@ public TaskActivityContextWrapper(TaskContext taskContext, TaskName name)
public override TaskName Name => this.name;

public override string InstanceId => this.innerContext.OrchestrationInstance.InstanceId;

public override string Version => this.innerContext.Version ?? string.Empty;
}
}
4 changes: 2 additions & 2 deletions src/Worker/Grpc/GrpcDurableTaskWorker.Processor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -884,10 +884,10 @@ async Task OnRunActivityAsync(P.ActivityRequest request, string completionToken,
this.Logger.ReceivedActivityRequest(request.Name, request.TaskId, instance.InstanceId, inputSize);

P.TaskFailureDetails? failureDetails = null;
TaskContext innerContext = new(instance);
TaskName name = new(request.Name);
TaskContext innerContext = new(instance, request.Name, request.Version ?? string.Empty, request.TaskId);
innerContext.ExceptionPropertiesProvider = this.exceptionPropertiesProvider;

TaskName name = new(request.Name);
string? output = null;

failureDetails = EvaluateOrchestrationVersioning(this.worker.workerOptions.Versioning, request.Version, out bool versioningFailed);
Expand Down
28 changes: 28 additions & 0 deletions test/Grpc.IntegrationTests/OrchestrationPatterns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,34 @@ public async Task OrchestrationVersionPassedThroughContext()
Assert.Equal(output, $"Orchestration version: {version}");
}

[Fact]
public async Task ActivityVersionPassedThroughContext()
{
var version = "0.1";
await using HostTestLifetime server = await this.StartWorkerAsync(b =>
{
b.AddTasks(tasks => tasks
.AddOrchestratorFunc<string, string>("Versioned_Orchestration", (ctx, input) =>
{
return ctx.CallActivityAsync<string>("Versioned_Activity", input);
})
.AddActivityFunc<string, string>("Versioned_Activity", (ctx, input) =>
{
return $"Activity version: {ctx.Version}";
}));
}, c =>
{
c.UseDefaultVersion(version);
});

var instanceId = await server.Client.ScheduleNewOrchestrationInstanceAsync("Versioned_Orchestration", input: string.Empty);
var result = await server.Client.WaitForInstanceCompletionAsync(instanceId, getInputsAndOutputs: true, this.TimeoutToken);
var output = result.ReadOutputAs<string>();

Assert.NotNull(output);
Assert.Equal(output, $"Activity version: {version}");
}

[Fact]
public async Task OrchestrationVersioning_MatchTypeNotSpecified_NoVersionFailure()
{
Expand Down
68 changes: 68 additions & 0 deletions test/Worker/Core.Tests/Shims/TaskActivityShimTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using DurableTask.Core;
using Microsoft.DurableTask.Converters;
using Microsoft.Extensions.Logging.Abstractions;

namespace Microsoft.DurableTask.Worker.Shims;

public class TaskActivityShimTests
{
[Fact]
public async Task RunAsync_ScheduledWithVersion_ExposesVersionOnContext()
{
// Arrange
CapturingActivity activity = new();
TaskActivityShim shim = new(
NullLoggerFactory.Instance,
new JsonDataConverter(),
"TestActivity",
activity);
TaskContext coreContext = new(
new OrchestrationInstance { InstanceId = Guid.NewGuid().ToString() },
"TestActivity",
"v2",
taskId: 1);

// Act
await shim.RunAsync(coreContext, "null");

// Assert
activity.CapturedVersion.Should().Be("v2");
}

[Fact]
public async Task RunAsync_ScheduledWithoutVersion_ExposesEmptyVersionOnContext()
{
// Arrange
CapturingActivity activity = new();
TaskActivityShim shim = new(
NullLoggerFactory.Instance,
new JsonDataConverter(),
"TestActivity",
activity);
TaskContext coreContext = new(
new OrchestrationInstance { InstanceId = Guid.NewGuid().ToString() },
"TestActivity",
version: null,
taskId: 1);

// Act
await shim.RunAsync(coreContext, "null");

// Assert
activity.CapturedVersion.Should().Be(string.Empty);
}

sealed class CapturingActivity : TaskActivity<object?, object?>
{
public string? CapturedVersion { get; private set; }

public override Task<object?> RunAsync(TaskActivityContext context, object? input)
{
this.CapturedVersion = context.Version;
return Task.FromResult<object?>(null);
}
}
}
Loading