diff --git a/src/Abstractions/Entities/CallEntityOptions.cs b/src/Abstractions/Entities/CallEntityOptions.cs
index b9462b5b..abd9cfac 100644
--- a/src/Abstractions/Entities/CallEntityOptions.cs
+++ b/src/Abstractions/Entities/CallEntityOptions.cs
@@ -8,21 +8,8 @@ namespace Microsoft.DurableTask.Entities;
///
public record CallEntityOptions
{
- ///
- /// Gets options indicating whether to signal the entity or not.
- ///
- ///
- /// Setting this to non-null will signal the entity without waiting for a response.
- ///
- ///
- /// Signal without start time:
- /// new CallEntityOptions { Signal = true };
- ///
- ///
- /// Signal with start time:
- /// new CallEntityOptions { Signal = DateTimeOffset };
- ///
- public SignalEntityOptions? Signal { get; init; }
+ // No call options at the moment. Keeping this class so we can ship with options in the API. This will
+ // allow us to easily add them later without adjusting API surface.
}
///
diff --git a/src/Abstractions/Entities/TaskOrchestrationEntityFeature.cs b/src/Abstractions/Entities/TaskOrchestrationEntityFeature.cs
new file mode 100644
index 00000000..30df27b6
--- /dev/null
+++ b/src/Abstractions/Entities/TaskOrchestrationEntityFeature.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace Microsoft.DurableTask.Entities;
+
+///
+/// Feature for interacting with durable entities from an orchestration.
+///
+public abstract class TaskOrchestrationEntityFeature
+{
+ ///
+ /// Calls an operation on an entity and waits for it to complete.
+ ///
+ /// The result type of the entity operation.
+ /// The target entity.
+ /// The name of the operation.
+ /// The operation input.
+ /// The call options.
+ /// The result of the entity operation.
+ public abstract Task CallEntityAsync(
+ EntityInstanceId id, string operationName, object? input = null, CallEntityOptions? options = null);
+
+ ///
+ /// Calls an operation on an entity and waits for it to complete.
+ ///
+ /// The result type of the entity operation.
+ /// The target entity.
+ /// The name of the operation.
+ /// The call options.
+ /// The result of the entity operation.
+ public virtual Task CallEntityAsync(
+ EntityInstanceId id, string operationName, CallEntityOptions? options)
+ => this.CallEntityAsync(id, operationName, null, options);
+
+ ///
+ /// Calls an operation on an entity and waits for it to complete.
+ ///
+ /// The target entity.
+ /// The name of the operation.
+ /// The operation input.
+ /// The call options.
+ /// A task that completes when the operation has been completed.
+ public abstract Task CallEntityAsync(
+ EntityInstanceId id, string operationName, object? input = null, CallEntityOptions? options = null);
+
+ ///
+ /// Calls an operation on an entity and waits for it to complete.
+ ///
+ /// The target entity.
+ /// The name of the operation.
+ /// The call options.
+ /// A task that completes when the operation has been completed.
+ public virtual Task CallEntityAsync(EntityInstanceId id, string operationName, CallEntityOptions? options)
+ => this.CallEntityAsync(id, operationName, null, options);
+
+ ///
+ /// Calls an operation on an entity, but does not wait for completion.
+ ///
+ /// The target entity.
+ /// The name of the operation.
+ /// The operation input.
+ /// The signal options.
+ ///
+ /// A task that represents scheduling of the signal operation. Dependening on implementation, this may complete
+ /// either when the operation has been signalled, or when the signal action has been enqueued by the context.
+ ///
+ public abstract Task SignalEntityAsync(
+ EntityInstanceId id, string operationName, object? input = null, SignalEntityOptions? options = null);
+
+ ///
+ /// Calls an operation on an entity, but does not wait for completion.
+ ///
+ /// The target entity.
+ /// The name of the operation.
+ /// The signal options.
+ ///
+ /// A task that represents scheduling of the signal operation. Dependening on implementation, this may complete
+ /// either when the operation has been signalled, or when the signal action has been enqueued by the context.
+ ///
+ public virtual Task SignalEntityAsync(
+ EntityInstanceId id, string operationName, SignalEntityOptions? options)
+ => this.SignalEntityAsync(id, operationName, null, options);
+
+ ///
+ /// Acquires one or more entity locks.
+ ///
+ /// The entity IDs to lock.
+ /// An async-disposable which can be disposed to release the lock.
+ public abstract Task LockEntitiesAsync(IEnumerable entityIds);
+
+ ///
+ /// Acquires one or more entity locks.
+ ///
+ /// The entity IDs to lock.
+ /// An async-disposable which can be disposed to release the lock.
+ public virtual Task LockEntitiesAsync(params EntityInstanceId[] entityIds)
+ => this.LockEntitiesAsync((IEnumerable)entityIds); // let the implementation decide how to handle nulls.
+
+ ///
+ /// Gets a value indicating whether this orchestration is in a critical section, and if true, any entity locks are
+ /// owned by this instance.
+ ///
+ /// The list of locked entities.
+ /// True if any locks are owned, false otherwise.
+ public abstract bool InCriticalSection([NotNullWhen(true)] out IReadOnlyList? entityIds);
+
+ ///
+ /// Gets a value indicating whether this orchestration is in a critical section.
+ ///
+ /// True if any locks are owned, false otherwise.
+ public virtual bool InCriticalSection() => this.InCriticalSection(out _);
+}
diff --git a/src/Abstractions/TaskOrchestrationContext.cs b/src/Abstractions/TaskOrchestrationContext.cs
index b3f139dc..15ba1ddc 100644
--- a/src/Abstractions/TaskOrchestrationContext.cs
+++ b/src/Abstractions/TaskOrchestrationContext.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using Microsoft.DurableTask.Entities;
using Microsoft.Extensions.Logging;
namespace Microsoft.DurableTask;
@@ -58,6 +59,12 @@ public abstract class TaskOrchestrationContext
///
public abstract bool IsReplaying { get; }
+ ///
+ /// Gets the entity feature, for interacting with entities.
+ ///
+ public virtual TaskOrchestrationEntityFeature Entities =>
+ throw new NotSupportedException($"Durable entities are not supported by {this.GetType()}.");
+
///
/// Gets the logger factory for this context.
///