diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbf11e269..57f6be992 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
## vNext
+- Added new preview packages, `Microsoft.DurableTask.Client.AzureManaged` and `Microsoft.DurableTask.Worker.AzureManaged`
+
### Microsoft.DurableTask.Client
- Add new `IDurableTaskClientBuilder AddDurableTaskClient(IServiceCollection, string?)` API
diff --git a/src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs b/src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs
index a3fa583f9..b11f450a6 100644
--- a/src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs
+++ b/src/Client/AzureManaged/DurableTaskSchedulerClientExtensions.cs
@@ -59,6 +59,7 @@ public static void UseDurableTaskScheduler(
options.EndpointAddress = connectionOptions.EndpointAddress;
options.TaskHubName = connectionOptions.TaskHubName;
options.Credential = connectionOptions.Credential;
+ options.AllowInsecureCredentials = connectionOptions.AllowInsecureCredentials;
},
configure);
}
diff --git a/src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs b/src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs
index 172332cda..9f6829fca 100644
--- a/src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs
+++ b/src/Client/AzureManaged/DurableTaskSchedulerClientOptions.cs
@@ -59,12 +59,17 @@ public static DurableTaskSchedulerClientOptions FromConnectionString(string conn
/// The connection string to parse.
/// A new instance of .
internal static DurableTaskSchedulerClientOptions FromConnectionString(
- DurableTaskSchedulerConnectionString connectionString) => new()
+ DurableTaskSchedulerConnectionString connectionString)
+ {
+ TokenCredential? credential = GetCredentialFromConnectionString(connectionString);
+ return new DurableTaskSchedulerClientOptions()
{
EndpointAddress = connectionString.Endpoint,
TaskHubName = connectionString.TaskHubName,
- Credential = GetCredentialFromConnectionString(connectionString),
+ Credential = credential,
+ AllowInsecureCredentials = credential is null,
};
+ }
///
/// Creates a gRPC channel for communicating with the Durable Task Scheduler service.
diff --git a/src/Worker/AzureManaged/DurableTaskSchedulerWorkerExtensions.cs b/src/Worker/AzureManaged/DurableTaskSchedulerWorkerExtensions.cs
index 63d19fa00..7a3baa414 100644
--- a/src/Worker/AzureManaged/DurableTaskSchedulerWorkerExtensions.cs
+++ b/src/Worker/AzureManaged/DurableTaskSchedulerWorkerExtensions.cs
@@ -60,6 +60,7 @@ public static void UseDurableTaskScheduler(
options.EndpointAddress = connectionOptions.EndpointAddress;
options.TaskHubName = connectionOptions.TaskHubName;
options.Credential = connectionOptions.Credential;
+ options.AllowInsecureCredentials = connectionOptions.AllowInsecureCredentials;
},
configure);
}
diff --git a/src/Worker/AzureManaged/DurableTaskSchedulerWorkerOptions.cs b/src/Worker/AzureManaged/DurableTaskSchedulerWorkerOptions.cs
index 67da8cb7a..4a92d91dc 100644
--- a/src/Worker/AzureManaged/DurableTaskSchedulerWorkerOptions.cs
+++ b/src/Worker/AzureManaged/DurableTaskSchedulerWorkerOptions.cs
@@ -65,12 +65,17 @@ public static DurableTaskSchedulerWorkerOptions FromConnectionString(string conn
/// The connection string to parse.
/// A new instance of .
internal static DurableTaskSchedulerWorkerOptions FromConnectionString(
- DurableTaskSchedulerConnectionString connectionString) => new()
+ DurableTaskSchedulerConnectionString connectionString)
+ {
+ TokenCredential? credential = GetCredentialFromConnectionString(connectionString);
+ return new DurableTaskSchedulerWorkerOptions()
{
EndpointAddress = connectionString.Endpoint,
TaskHubName = connectionString.TaskHubName,
- Credential = GetCredentialFromConnectionString(connectionString),
+ Credential = credential,
+ AllowInsecureCredentials = credential is null,
};
+ }
///
/// Creates a gRPC channel for communicating with the Durable Task Scheduler service.
diff --git a/src/Worker/Grpc/GrpcDurableTaskWorker.cs b/src/Worker/Grpc/GrpcDurableTaskWorker.cs
index d685a4fe1..cb11054d1 100644
--- a/src/Worker/Grpc/GrpcDurableTaskWorker.cs
+++ b/src/Worker/Grpc/GrpcDurableTaskWorker.cs
@@ -46,8 +46,8 @@ public GrpcDurableTaskWorker(
///
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
- await using AsyncDisposable disposable = this.GetCallInvoker(out CallInvoker callInvoker);
- this.logger.StartingTaskHubWorker();
+ await using AsyncDisposable disposable = this.GetCallInvoker(out CallInvoker callInvoker, out string address);
+ this.logger.StartingTaskHubWorker(address);
await new Processor(this, new(callInvoker)).ExecuteAsync(stoppingToken);
}
@@ -75,22 +75,25 @@ static GrpcChannel GetChannel(string? address)
}
#endif
- AsyncDisposable GetCallInvoker(out CallInvoker callInvoker)
+ AsyncDisposable GetCallInvoker(out CallInvoker callInvoker, out string address)
{
if (this.grpcOptions.Channel is GrpcChannel c)
{
callInvoker = c.CreateCallInvoker();
+ address = c.Target;
return default;
}
if (this.grpcOptions.CallInvoker is CallInvoker invoker)
{
callInvoker = invoker;
+ address = "(unspecified)";
return default;
}
c = GetChannel(this.grpcOptions.Address);
callInvoker = c.CreateCallInvoker();
+ address = c.Target;
return new AsyncDisposable(() => new(c.ShutdownAsync()));
}
}
diff --git a/src/Worker/Grpc/Logs.cs b/src/Worker/Grpc/Logs.cs
index d6c978fe3..2ff8d40ec 100644
--- a/src/Worker/Grpc/Logs.cs
+++ b/src/Worker/Grpc/Logs.cs
@@ -13,8 +13,8 @@ namespace Microsoft.DurableTask.Worker.Grpc
///
static partial class Logs
{
- [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Durable Task gRPC worker starting.")]
- public static partial void StartingTaskHubWorker(this ILogger logger);
+ [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Durable Task gRPC worker starting and connecting to {endpoint}.")]
+ public static partial void StartingTaskHubWorker(this ILogger logger, string endpoint);
[LoggerMessage(EventId = 2, Level = LogLevel.Information, Message = "Durable Task gRPC worker has disconnected from gRPC server.")]
public static partial void SidecarDisconnected(this ILogger logger);
diff --git a/test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs b/test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs
index 599fa1c7b..d625703ca 100644
--- a/test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs
+++ b/test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs
@@ -65,6 +65,32 @@ public void UseDurableTaskScheduler_WithConnectionString_ShouldConfigureCorrectl
clientOptions.Credential.Should().BeOfType();
}
+ [Fact]
+ public void UseDurableTaskScheduler_WithLocalhostConnectionString_ShouldConfigureCorrectly()
+ {
+ // Arrange
+ ServiceCollection services = new();
+ Mock mockBuilder = new();
+ mockBuilder.Setup(b => b.Services).Returns(services);
+ string connectionString = $"Endpoint=http://localhost;Authentication=None;TaskHub={ValidTaskHub}";
+
+ // Act
+ mockBuilder.Object.UseDurableTaskScheduler(connectionString);
+
+ // Assert
+ ServiceProvider provider = services.BuildServiceProvider();
+ IOptions? options = provider.GetService>();
+ options.Should().NotBeNull();
+
+ // Validate the configured options
+ var workerOptions = provider.GetRequiredService>().Value;
+ workerOptions.EndpointAddress.Should().Be("http://localhost");
+ workerOptions.TaskHubName.Should().Be(ValidTaskHub);
+ workerOptions.Credential.Should().BeNull();
+ workerOptions.ResourceId.Should().Be("https://durabletask.io");
+ workerOptions.AllowInsecureCredentials.Should().BeTrue();
+ }
+
[Theory]
[InlineData(null, "testhub")]
[InlineData("myaccount.westus3.durabletask.io", null)]
@@ -124,7 +150,7 @@ public void UseDurableTaskScheduler_WithInvalidConnectionString_ShouldThrowArgum
// Assert
action.Should().Throw()
- .WithMessage("Value cannot be null. (Parameter 'Endpoint')");
+ .WithMessage("Value cannot be null. (Parameter '*')");
}
[Theory]
diff --git a/test/Worker/AzureManaged.Tests/DurableTaskSchedulerWorkerExtensionsTests.cs b/test/Worker/AzureManaged.Tests/DurableTaskSchedulerWorkerExtensionsTests.cs
index bec5a962a..49e8df4e3 100644
--- a/test/Worker/AzureManaged.Tests/DurableTaskSchedulerWorkerExtensionsTests.cs
+++ b/test/Worker/AzureManaged.Tests/DurableTaskSchedulerWorkerExtensionsTests.cs
@@ -69,6 +69,32 @@ public void UseDurableTaskScheduler_WithConnectionString_ShouldConfigureCorrectl
workerOptions.AllowInsecureCredentials.Should().BeFalse();
}
+ [Fact]
+ public void UseDurableTaskScheduler_WithLocalhostConnectionString_ShouldConfigureCorrectly()
+ {
+ // Arrange
+ ServiceCollection services = new();
+ Mock mockBuilder = new();
+ mockBuilder.Setup(b => b.Services).Returns(services);
+ string connectionString = $"Endpoint=http://localhost;Authentication=None;TaskHub={ValidTaskHub}";
+
+ // Act
+ mockBuilder.Object.UseDurableTaskScheduler(connectionString);
+
+ // Assert
+ ServiceProvider provider = services.BuildServiceProvider();
+ IOptions? options = provider.GetService>();
+ options.Should().NotBeNull();
+
+ // Validate the configured options
+ var workerOptions = provider.GetRequiredService>().Value;
+ workerOptions.EndpointAddress.Should().Be("http://localhost");
+ workerOptions.TaskHubName.Should().Be(ValidTaskHub);
+ workerOptions.Credential.Should().BeNull();
+ workerOptions.ResourceId.Should().Be("https://durabletask.io");
+ workerOptions.AllowInsecureCredentials.Should().BeTrue();
+ }
+
[Theory]
[InlineData(null, "testhub")]
[InlineData("myaccount.westus3.durabletask.io", null)]
@@ -129,7 +155,7 @@ public void UseDurableTaskScheduler_WithInvalidConnectionString_ShouldThrowArgum
// Assert
action.Should().Throw()
- .WithMessage("Value cannot be null. (Parameter 'Endpoint')");
+ .WithMessage("Value cannot be null. (Parameter '*')");
}
[Theory]