From 5baf36fa66ef8da695107593267a3dc1b1e0499e Mon Sep 17 00:00:00 2001
From: peterstone2017 <12449837+YunchuWang@users.noreply.github.com>
Date: Mon, 10 Nov 2025 11:04:55 -0800
Subject: [PATCH] Support custom priority on orchestration scheduling
---
.../OrchestrationPriorityLevel.cs | 41 +++++++++++++++++++
src/Abstractions/TaskOptions.cs | 10 +++++
src/Client/Grpc/GrpcDurableTaskClient.cs | 11 +++++
src/Client/Grpc/ProtoUtils.cs | 17 ++++++++
src/Grpc/orchestrator_service.proto | 12 ++++++
5 files changed, 91 insertions(+)
create mode 100644 src/Abstractions/OrchestrationPriorityLevel.cs
diff --git a/src/Abstractions/OrchestrationPriorityLevel.cs b/src/Abstractions/OrchestrationPriorityLevel.cs
new file mode 100644
index 00000000..80f7a0a1
--- /dev/null
+++ b/src/Abstractions/OrchestrationPriorityLevel.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.DurableTask;
+
+///
+/// Priority level enum for intuitive priority specification.
+///
+public enum OrchestrationPriorityLevel
+{
+ ///
+ /// Unspecified priority. Uses instance key (normal priority, FIFO).
+ ///
+ Unspecified = 0,
+
+ ///
+ /// Highest priority (priority value 0).
+ ///
+ Urgent = 1,
+
+ ///
+ /// High priority (priority value 1000).
+ ///
+ High = 2,
+
+ ///
+ /// Normal priority (uses instance key, FIFO).
+ ///
+ Normal = 3,
+
+ ///
+ /// Low priority (instance key + 1,000,000).
+ ///
+ Low = 4,
+
+ ///
+ /// Background priority (instance key + 10,000,000).
+ ///
+ Background = 5,
+}
+
diff --git a/src/Abstractions/TaskOptions.cs b/src/Abstractions/TaskOptions.cs
index f8e527fe..7c54eacf 100644
--- a/src/Abstractions/TaskOptions.cs
+++ b/src/Abstractions/TaskOptions.cs
@@ -134,4 +134,14 @@ public record StartOrchestrationOptions(string? InstanceId = null, DateTimeOffse
/// Gets the version to associate with the orchestration instance.
///
public TaskVersion? Version { get; init; }
+
+ ///
+ /// Gets the optional custom numeric priority. Lower numbers are processed more urgently. Takes precedence over PriorityLevel.
+ ///
+ public long? Priority { get; init; }
+
+ ///
+ /// Gets the optional priority level for intuitive priority specification. Ignored if Priority is set.
+ ///
+ public OrchestrationPriorityLevel? PriorityLevel { get; init; }
}
diff --git a/src/Client/Grpc/GrpcDurableTaskClient.cs b/src/Client/Grpc/GrpcDurableTaskClient.cs
index efc6d765..ef60e101 100644
--- a/src/Client/Grpc/GrpcDurableTaskClient.cs
+++ b/src/Client/Grpc/GrpcDurableTaskClient.cs
@@ -121,6 +121,17 @@ public override async Task ScheduleNewOrchestrationInstanceAsync(
request.ScheduledStartTimestamp = Timestamp.FromDateTimeOffset(startAt.Value.ToUniversalTime());
}
+ // Set priority if specified (takes precedence over priorityLevel)
+ if (options?.Priority.HasValue == true)
+ {
+ request.Priority = options.Priority.Value;
+ }
+ // Set priorityLevel if specified and priority is not set
+ else if (options?.PriorityLevel.HasValue == true)
+ {
+ request.PriorityLevel = options.PriorityLevel.Value.ToGrpcPriorityLevel();
+ }
+
using Activity? newActivity = TraceHelper.StartActivityForNewOrchestration(request);
P.CreateInstanceResponse? result = await this.sidecarClient.StartInstanceAsync(
diff --git a/src/Client/Grpc/ProtoUtils.cs b/src/Client/Grpc/ProtoUtils.cs
index f5bc750d..11063ebd 100644
--- a/src/Client/Grpc/ProtoUtils.cs
+++ b/src/Client/Grpc/ProtoUtils.cs
@@ -30,4 +30,21 @@ internal static P.OrchestrationStatus ToGrpcStatus(this OrchestrationRuntimeStat
_ => throw new ArgumentOutOfRangeException(nameof(status), "Unexpected value"),
};
#pragma warning restore 0618 // Referencing Obsolete member.
+
+ ///
+ /// Converts to .
+ ///
+ /// The priority level.
+ /// A .
+ internal static P.OrchestrationPriorityLevel ToGrpcPriorityLevel(this OrchestrationPriorityLevel priorityLevel)
+ => priorityLevel switch
+ {
+ OrchestrationPriorityLevel.Unspecified => P.OrchestrationPriorityLevel.Unspecified,
+ OrchestrationPriorityLevel.Urgent => P.OrchestrationPriorityLevel.Urgent,
+ OrchestrationPriorityLevel.High => P.OrchestrationPriorityLevel.High,
+ OrchestrationPriorityLevel.Normal => P.OrchestrationPriorityLevel.Normal,
+ OrchestrationPriorityLevel.Low => P.OrchestrationPriorityLevel.Low,
+ OrchestrationPriorityLevel.Background => P.OrchestrationPriorityLevel.Background,
+ _ => throw new ArgumentOutOfRangeException(nameof(priorityLevel), "Unexpected value"),
+ };
}
diff --git a/src/Grpc/orchestrator_service.proto b/src/Grpc/orchestrator_service.proto
index d59bca3c..f099ffe4 100644
--- a/src/Grpc/orchestrator_service.proto
+++ b/src/Grpc/orchestrator_service.proto
@@ -358,6 +358,16 @@ message OrchestratorResponse {
bool requiresHistory = 7;
}
+// Priority level enum for intuitive priority specification
+enum OrchestrationPriorityLevel {
+ ORCHESTRATION_PRIORITY_LEVEL_UNSPECIFIED = 0; // Uses instance key (normal priority, FIFO)
+ ORCHESTRATION_PRIORITY_LEVEL_URGENT = 1; // Highest priority (priority value 0)
+ ORCHESTRATION_PRIORITY_LEVEL_HIGH = 2; // High priority (priority value 1000)
+ ORCHESTRATION_PRIORITY_LEVEL_NORMAL = 3; // Normal priority (uses instance key, FIFO)
+ ORCHESTRATION_PRIORITY_LEVEL_LOW = 4; // Low priority (instance key + 1,000,000)
+ ORCHESTRATION_PRIORITY_LEVEL_BACKGROUND = 5; // Background priority (instance key + 10,000,000)
+}
+
message CreateInstanceRequest {
string instanceId = 1;
string name = 2;
@@ -369,6 +379,8 @@ message CreateInstanceRequest {
map tags = 8;
TraceContext parentTraceContext = 9;
google.protobuf.Timestamp requestTime = 10;
+ google.protobuf.Int64Value priority = 11; // Optional custom numeric priority. Lower numbers are processed more urgently. Takes precedence over priorityLevel.
+ OrchestrationPriorityLevel priorityLevel = 12; // Optional priority level for intuitive priority specification. Ignored if priority is set.
}
message OrchestrationIdReusePolicy {