Skip to content
Closed
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
139 changes: 139 additions & 0 deletions Test/DurableTask.Core.Tests/TaskOrchestrationGetStatusAsyncTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// ----------------------------------------------------------------------------------
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

namespace DurableTask.Core.Tests
{
using System;
using System.Threading.Tasks;
using DurableTask.Core.Serializing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class TaskOrchestrationGetStatusAsyncTests
{
[TestMethod]
public async Task GetStatusAsync_ReturnsSerializedStatus_FromTypedOrchestration()
{
var orchestration = new SampleTypedOrchestration();

string syncStatus = orchestration.GetStatus();
string asyncStatus = await orchestration.GetStatusAsync();

Assert.AreEqual(syncStatus, asyncStatus, "Async status should equal sync status");

var deserialized = (Status)orchestration.DataConverter.Deserialize(asyncStatus, typeof(Status));
Assert.AreEqual("running", deserialized.State);
Assert.AreEqual(42, deserialized.Progress);
}

[TestMethod]
public async Task GetStatusAsync_ReturnsNull_WhenTypedOnGetStatusReturnsNull()
{
var orchestration = new NullStatusTypedOrchestration();

string syncStatus = orchestration.GetStatus();
string asyncStatus = await orchestration.GetStatusAsync();

Assert.IsNull(syncStatus, "Sync status should be null when OnGetStatus returns null");
Assert.IsNull(asyncStatus, "Async status should be null when OnGetStatus returns null");
}

[TestMethod]
public async Task GetStatusAsync_ReturnsSameAsGetStatus_ForNonGenericOrchestration()
{
var orchestration = new NonGenericOrchestration();

string syncStatus = orchestration.GetStatus();
string asyncStatus = await orchestration.GetStatusAsync();

Assert.AreEqual("OK", syncStatus);
Assert.AreEqual(syncStatus, asyncStatus);
}

[TestMethod]
public async Task GetStatusAsync_PropagatesException_WhenGetStatusThrows()
{
var orchestration = new ThrowingStatusOrchestration();

await Assert.ThrowsExceptionAsync<InvalidOperationException>(async () => await orchestration.GetStatusAsync());
}

class SampleTypedOrchestration : TaskOrchestration<string, string, string, Status>
{
public override Task<string> RunTask(OrchestrationContext context, string input)
{
return Task.FromResult("done");
}

public override Status OnGetStatus()
{
return new Status { State = "running", Progress = 42 };
}
}

class NullStatusTypedOrchestration : TaskOrchestration<string, string, string, Status>
{
public override Task<string> RunTask(OrchestrationContext context, string input)
{
return Task.FromResult("done");
}

public override Status OnGetStatus()
{
return null;
}
}

class NonGenericOrchestration : TaskOrchestration
{
public override Task<string> Execute(OrchestrationContext context, string input)
{
return Task.FromResult("done");
}

public override void RaiseEvent(OrchestrationContext context, string name, string input)
{
}

public override string GetStatus()
{
return "OK";
}
}

class ThrowingStatusOrchestration : TaskOrchestration
{
public override Task<string> Execute(OrchestrationContext context, string input)
{
return Task.FromResult("done");
}

public override void RaiseEvent(OrchestrationContext context, string name, string input)
{
}

public override string GetStatus()
{
throw new InvalidOperationException("boom");
}
}

class Status
{
public string State { get; set; }

public int Progress { get; set; }
}
}
}

29 changes: 26 additions & 3 deletions src/DurableTask.Core/TaskOrchestration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

#nullable enable
namespace DurableTask.Core
{
using System;
Expand Down Expand Up @@ -48,6 +49,28 @@ public abstract class TaskOrchestration
/// </summary>
/// <returns>The status</returns>
public abstract string GetStatus();

/// <summary>
/// Gets the current status of the orchestration
/// </summary>
/// <returns>The status</returns>
public virtual async Task<string?> GetStatusAsync()
{
return await Task.FromResult(GetStatus());
}

/// <summary>
/// Raises an event in the orchestration asynchronously
/// </summary>
/// <param name="context">The orchestration context</param>
/// <param name="name">Name for this event to be passed to the OnEvent handler</param>
/// <param name="input">The serialized input</param>
/// <returns>A task representing the asynchronous operation.</returns>
public virtual Task RaiseEventAsync(OrchestrationContext context, string name, string input)
{
RaiseEvent(context, name, input);
return Task.CompletedTask;
}
}

/// <summary>
Expand Down Expand Up @@ -97,8 +120,8 @@ public override async Task<string> Execute(OrchestrationContext context, string
}
catch (Exception e) when (!Utils.IsFatal(e) && !Utils.IsExecutionAborting(e))
{
string details = null;
FailureDetails failureDetails = null;
string? details = null;
FailureDetails? failureDetails = null;
if (context.ErrorPropagationMode == ErrorPropagationMode.SerializeExceptions)
{
details = Utils.SerializeCause(e, DataConverter);
Expand Down Expand Up @@ -164,7 +187,7 @@ public virtual void OnEvent(OrchestrationContext context, string name, TEvent in
/// <returns>The typed status</returns>
public virtual TStatus OnGetStatus()
{
return default(TStatus);
return default!;
}
}
}
Loading