diff --git a/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClient.cs b/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClient.cs
index bd9f47498..5ec48ad6b 100644
--- a/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClient.cs
+++ b/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClient.cs
@@ -651,6 +651,11 @@ internal HttpManagementPayload CreateHttpManagementPayload(
string taskHubName,
string connectionName)
{
+ if (this.httpApiHandler == null)
+ {
+ throw new InvalidOperationException("IDurableClient.CreateHttpManagementPayload is not supported for IDurableClient instances created outside of a Durable Functions application.");
+ }
+
return this.httpApiHandler.CreateHttpManagementPayload(instanceId, taskHubName, connectionName);
}
@@ -807,6 +812,11 @@ internal HttpResponseMessage CreateCheckStatusResponse(
DurableClientAttribute attribute,
bool returnInternalServerErrorOnFailure = false)
{
+ if (this.httpApiHandler == null)
+ {
+ throw new InvalidOperationException("IDurableClient.CreateCheckStatusResponse is not supported for IDurableClient instances created outside of a Durable Functions application.");
+ }
+
return this.httpApiHandler.CreateCheckStatusResponse(request, instanceId, attribute, returnInternalServerErrorOnFailure);
}
diff --git a/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClientFactory.cs b/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClientFactory.cs
index cc22f68dd..29699caad 100644
--- a/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClientFactory.cs
+++ b/src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClientFactory.cs
@@ -76,19 +76,12 @@ public IDurableClient CreateClient(DurableClientOptions durableClientOptions)
DurableClientAttribute attribute = new DurableClientAttribute(durableClientOptions);
- HttpApiHandler httpApiHandler = this.cachedHttpListeners.GetOrAdd(
- attribute,
- attr =>
- {
- return new HttpApiHandler(null, null, this.durableTaskOptions, this.logger);
- });
-
DurableClient client = this.cachedClients.GetOrAdd(
attribute,
attr =>
{
DurabilityProvider innerClient = this.durabilityProviderFactory.GetDurabilityProvider(attribute);
- return new DurableClient(innerClient, httpApiHandler, attribute, this.MessageDataConverter, this.TraceHelper, this.durableTaskOptions);
+ return new DurableClient(innerClient, null, attribute, this.MessageDataConverter, this.TraceHelper, this.durableTaskOptions);
});
return client;
diff --git a/src/WebJobs.Extensions.DurableTask/DurableTaskJobHostConfigurationExtensions.cs b/src/WebJobs.Extensions.DurableTask/DurableTaskJobHostConfigurationExtensions.cs
index 2afdcc8fb..9e763c58a 100644
--- a/src/WebJobs.Extensions.DurableTask/DurableTaskJobHostConfigurationExtensions.cs
+++ b/src/WebJobs.Extensions.DurableTask/DurableTaskJobHostConfigurationExtensions.cs
@@ -55,7 +55,7 @@ public static IWebJobsBuilder AddDurableTask(this IWebJobsBuilder builder)
///
/// The to configure.
/// Returns the provided .
- public static IServiceCollection AddDurableTask(this IServiceCollection serviceCollection)
+ public static IServiceCollection AddDurableClientFactory(this IServiceCollection serviceCollection)
{
if (serviceCollection == null)
{
@@ -77,9 +77,9 @@ public static IServiceCollection AddDurableTask(this IServiceCollection serviceC
/// The to configure.
/// Populate default configurations of to create Durable Clients.
/// Returns the provided .
- public static IServiceCollection AddDurableTask(this IServiceCollection serviceCollection, Action optionsBuilder)
+ public static IServiceCollection AddDurableClientFactory(this IServiceCollection serviceCollection, Action optionsBuilder)
{
- AddDurableTask(serviceCollection);
+ AddDurableClientFactory(serviceCollection);
serviceCollection.Configure(optionsBuilder.Invoke);
return serviceCollection;
}
diff --git a/src/WebJobs.Extensions.DurableTask/Microsoft.Azure.WebJobs.Extensions.DurableTask.xml b/src/WebJobs.Extensions.DurableTask/Microsoft.Azure.WebJobs.Extensions.DurableTask.xml
index c2a3102dd..00840c440 100644
--- a/src/WebJobs.Extensions.DurableTask/Microsoft.Azure.WebJobs.Extensions.DurableTask.xml
+++ b/src/WebJobs.Extensions.DurableTask/Microsoft.Azure.WebJobs.Extensions.DurableTask.xml
@@ -2162,14 +2162,14 @@
The to configure.
Returns the provided .
-
+
Adds the Durable Task extension to the provided .
The to configure.
Returns the provided .
-
+
Adds the Durable Task extension to the provided .
diff --git a/test/Common/DurableClientBaseTests.cs b/test/Common/DurableClientBaseTests.cs
index 4d46b00db..0190a09de 100644
--- a/test/Common/DurableClientBaseTests.cs
+++ b/test/Common/DurableClientBaseTests.cs
@@ -11,12 +11,14 @@
#if !FUNCTIONS_V1
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Azure.WebJobs.Extensions.DurableTask.Options;
#endif
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Moq;
+using Newtonsoft.Json;
using Xunit;
using static Microsoft.Azure.WebJobs.Extensions.DurableTask.Tests.HttpApiHandlerTests;
@@ -142,6 +144,91 @@ public async Task TerminateAsync_NonRunningOrchestrator_ThrowsException()
}
#if !FUNCTIONS_V1
+ [Fact]
+ [Trait("Category", PlatformSpecificHelpers.TestCategory)]
+ public async Task DurableClient_ExternalApp_StartNewAsync_ReturnsInstanceId()
+ {
+ var orchestrationServiceClientMock = new Mock();
+ orchestrationServiceClientMock.Setup(x => x.GetOrchestrationStateAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync(GetInstanceState(OrchestrationStatus.Running));
+
+ var durableOrchestrationClient = this.GetDurableClient(orchestrationServiceClientMock.Object);
+
+ var response = await durableOrchestrationClient.StartNewAsync("orchestrationName", "testInstanceId");
+ Assert.Equal("testInstanceId", response);
+ }
+
+ [Fact]
+ [Trait("Category", PlatformSpecificHelpers.TestCategory)]
+ public async void DurableClient_ExternalApp_GetStatusAsync_ReturnsStatus()
+ {
+ var orchestrationServiceClientMock = new Mock();
+ orchestrationServiceClientMock.Setup(x => x.GetOrchestrationStateAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync(GetInstanceState(OrchestrationStatus.Running));
+
+ var durableOrchestrationClient = this.GetDurableClient(orchestrationServiceClientMock.Object);
+ var status = await durableOrchestrationClient.GetStatusAsync("testInstanceId");
+ Assert.Equal(OrchestrationRuntimeStatus.Running, status.RuntimeStatus);
+ }
+
+ [Fact]
+ [Trait("Category", PlatformSpecificHelpers.TestCategory)]
+ public async void DurableClient_ExternalApp_TerminateAsync_TerminateEventPlaced()
+ {
+ var orchestrationServiceClientMock = new Mock();
+ orchestrationServiceClientMock.Setup(x => x.GetOrchestrationStateAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync(GetInstanceState(OrchestrationStatus.Running));
+
+ var durableOrchestrationClient = this.GetDurableClient(orchestrationServiceClientMock.Object);
+ await durableOrchestrationClient.TerminateAsync("valid_instance_id", "any reason");
+ orchestrationServiceClientMock.Verify(x => x.ForceTerminateTaskOrchestrationAsync("valid_instance_id", "any reason"), Times.Once());
+ }
+
+ [Fact]
+ [Trait("Category", PlatformSpecificHelpers.TestCategory)]
+ public void DurableClient_ExternalApp_CreateCheckStatusResponse_ThrowsException()
+ {
+ var instanceId = Guid.NewGuid().ToString();
+
+ var orchestrationServiceClientMock = new Mock();
+ orchestrationServiceClientMock.Setup(x => x.GetOrchestrationStateAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync(GetInstanceState(OrchestrationStatus.Running));
+
+ var durableOrchestrationClient = this.GetDurableClient(orchestrationServiceClientMock.Object);
+ Assert.ThrowsAny(() => durableOrchestrationClient.CreateCheckStatusResponse(new HttpRequestMessage(), "testInstanceId"));
+ }
+
+ [Fact]
+ [Trait("Category", PlatformSpecificHelpers.TestCategory)]
+ public void DurableClient_ExternalApp_CreateHttpManagementPayload_ThrowsException()
+ {
+ var instanceId = Guid.NewGuid().ToString();
+
+ var orchestrationServiceClientMock = new Mock();
+ orchestrationServiceClientMock.Setup(x => x.GetOrchestrationStateAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync(GetInstanceState(OrchestrationStatus.Running));
+
+ var durableOrchestrationClient = this.GetDurableClient(orchestrationServiceClientMock.Object);
+ Assert.ThrowsAny(() => durableOrchestrationClient.CreateHttpManagementPayload("testInstanceId"));
+ }
+
+ private IDurableOrchestrationClient GetDurableClient(IOrchestrationServiceClient orchestrationServiceClientMockObject)
+ {
+ var storageProvider = new DurabilityProvider("test", new Mock().Object, orchestrationServiceClientMockObject, "test");
+ DurableClientOptions durableClientOptions = new DurableClientOptions
+ {
+ ConnectionName = "Storage",
+ TaskHub = "TestTaskHub",
+ };
+ DurableTaskOptions durableTaskOptions = new DurableTaskOptions();
+ DurableClientAttribute attribute = new DurableClientAttribute(durableClientOptions);
+ MessagePayloadDataConverter messagePayloadDataConverter = new MessagePayloadDataConverter(new JsonSerializerSettings(), true);
+ var traceHelper = new EndToEndTraceHelper(new NullLogger(), durableTaskOptions.Tracing.TraceReplayEvents);
+
+ var durableOrchestrationClient = (IDurableOrchestrationClient)new DurableClient(storageProvider, null, attribute, messagePayloadDataConverter, traceHelper, durableTaskOptions);
+ return durableOrchestrationClient;
+ }
+
[Fact]
[Trait("Category", PlatformSpecificHelpers.TestCategory)]
public async Task HttpRequest_HttpRequestMessage_ClientMethods_Identical()