diff --git a/src/Abstractions/OrchestrationOptions.cs b/src/Abstractions/OrchestrationOptions.cs
new file mode 100644
index 00000000..875760a1
--- /dev/null
+++ b/src/Abstractions/OrchestrationOptions.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.DurableTask;
+
+///
+/// Enum describing the runtime status of the orchestration.
+///
+public enum OrchestrationRuntimeStatus
+{
+ ///
+ /// The orchestration started running.
+ ///
+ Running,
+
+ ///
+ /// The orchestration completed normally.
+ ///
+ Completed,
+
+ ///
+ /// The orchestration is transitioning into a new instance.
+ ///
+ [Obsolete("The ContinuedAsNew status is obsolete and exists only for compatibility reasons.")]
+ ContinuedAsNew,
+
+ ///
+ /// The orchestration completed with an unhandled exception.
+ ///
+ Failed,
+
+ ///
+ /// The orchestration canceled gracefully.
+ ///
+ [Obsolete("The Canceled status is not currently used and exists only for compatibility reasons.")]
+ Canceled,
+
+ ///
+ /// The orchestration was abruptly terminated via a management API call.
+ ///
+ Terminated,
+
+ ///
+ /// The orchestration was scheduled but hasn't started running.
+ ///
+ Pending,
+
+ ///
+ /// The orchestration has been suspended.
+ ///
+ Suspended,
+}
diff --git a/src/Abstractions/TaskOptions.cs b/src/Abstractions/TaskOptions.cs
index 63f94382..b0d3cef8 100644
--- a/src/Abstractions/TaskOptions.cs
+++ b/src/Abstractions/TaskOptions.cs
@@ -100,4 +100,7 @@ public SubOrchestrationOptions(TaskOptions options, string? instanceId = null)
/// The time when the orchestration instance should start executing. If not specified or if a date-time in the past
/// is specified, the orchestration instance will be scheduled immediately.
///
-public record StartOrchestrationOptions(string? InstanceId = null, DateTimeOffset? StartAt = null);
+/// The orchestration reuse policy. This allows for the reuse of an instance ID
+/// if the instance ID referenced is in any of the states supplied in this parameter.
+public record StartOrchestrationOptions(string? InstanceId = null, DateTimeOffset? StartAt = null,
+ OrchestrationRuntimeStatus[]? OrchestrationIdReusePolicy = null);
diff --git a/src/Client/Grpc/GrpcDurableTaskClient.cs b/src/Client/Grpc/GrpcDurableTaskClient.cs
index f0d6e6e8..ecef704a 100644
--- a/src/Client/Grpc/GrpcDurableTaskClient.cs
+++ b/src/Client/Grpc/GrpcDurableTaskClient.cs
@@ -83,6 +83,7 @@ public override async Task ScheduleNewOrchestrationInstanceAsync(
Version = orchestratorName.Version,
InstanceId = options?.InstanceId ?? Guid.NewGuid().ToString("N"),
Input = this.DataConverter.Serialize(input),
+ OrchestrationIdReusePolicy = { },
};
DateTimeOffset? startAt = options?.StartAt;
diff --git a/src/Client/OrchestrationServiceClientShim/Client.OrchestrationServiceClientShim.csproj b/src/Client/OrchestrationServiceClientShim/Client.OrchestrationServiceClientShim.csproj
index b5389866..5a5be168 100644
--- a/src/Client/OrchestrationServiceClientShim/Client.OrchestrationServiceClientShim.csproj
+++ b/src/Client/OrchestrationServiceClientShim/Client.OrchestrationServiceClientShim.csproj
@@ -8,6 +8,11 @@ The client is responsible for interacting with orchestrations from outside the w
true
+
+
+
+
+
1.0.5
@@ -17,11 +22,13 @@ The client is responsible for interacting with orchestrations from outside the w
+
+
diff --git a/src/Client/OrchestrationServiceClientShim/ShimDurableTaskClient.cs b/src/Client/OrchestrationServiceClientShim/ShimDurableTaskClient.cs
index 3f3c5211..d31e8ee4 100644
--- a/src/Client/OrchestrationServiceClientShim/ShimDurableTaskClient.cs
+++ b/src/Client/OrchestrationServiceClientShim/ShimDurableTaskClient.cs
@@ -138,6 +138,18 @@ public override async Task ScheduleNewOrchestrationInstanceAsync(
{
cancellation.ThrowIfCancellationRequested();
string instanceId = options?.InstanceId ?? Guid.NewGuid().ToString("N");
+ OrchestrationStatus[] runtimeStates = Array.Empty();
+
+ // Convert from DurableTask.OrchestrationRuntimeStatus to DurableTask.Core.OrchestrationRuntimeStatus
+ if (options?.OrchestrationIdReusePolicy != null)
+ {
+ runtimeStates = new OrchestrationStatus[options.OrchestrationIdReusePolicy.Length];
+ for (int i = 0; i < options.OrchestrationIdReusePolicy.Length; i++)
+ {
+ runtimeStates[i] = ConvertState(options.OrchestrationIdReusePolicy[i]);
+ }
+ }
+
OrchestrationInstance instance = new()
{
InstanceId = instanceId,
@@ -157,7 +169,7 @@ public override async Task ScheduleNewOrchestrationInstanceAsync(
},
};
- await this.Client.CreateTaskOrchestrationAsync(message);
+ await this.Client.CreateTaskOrchestrationAsync(message, runtimeStates);
return instanceId;
}
@@ -219,6 +231,28 @@ public override async Task WaitForInstanceStartAsync(
}
}
+ // Converts from DurableTask.OrchestrationRuntimeStatus to OrchestrationStatus for policy reuse.
+ static OrchestrationStatus ConvertState(DurableTask.OrchestrationRuntimeStatus state)
+ {
+ switch (state)
+ {
+ case DurableTask.OrchestrationRuntimeStatus.Running:
+ return OrchestrationStatus.Running;
+ case DurableTask.OrchestrationRuntimeStatus.Completed:
+ return OrchestrationStatus.Completed;
+ case DurableTask.OrchestrationRuntimeStatus.Failed:
+ return OrchestrationStatus.Failed;
+ case DurableTask.OrchestrationRuntimeStatus.Terminated:
+ return OrchestrationStatus.Terminated;
+ case DurableTask.OrchestrationRuntimeStatus.Pending:
+ return OrchestrationStatus.Pending;
+ case DurableTask.OrchestrationRuntimeStatus.Suspended:
+ return OrchestrationStatus.Suspended;
+ default:
+ return OrchestrationStatus.Terminated;
+ }
+ }
+
[return: NotNullIfNotNull("state")]
OrchestrationMetadata? ToMetadata(Core.OrchestrationState? state, bool getInputsAndOutputs)
{