-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
durable task scheduler auth extension support #362
base: main
Are you sure you want to change the base?
Conversation
save initial
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! I added some comments.
@jviau would you mind taking a look at this as well? The main feedback I'm interested in from you is the package name/organization. The idea behind this PR is to introduce a mechanism for configuring the gRPC channels to work with the Durable Task Scheduler (DTS). This includes setting up the appropriate auth and some other service-specific headers (like the task hub name). I figured this might be the right time to introduce an "Extensions" concept and make "Azure" the extension consumers should use for talking to DTS. There could be others in the future. WDYT? |
This reverts commit 131c575.
I wonder if we want a name other that Extensions for backends? I am worried this may get confused with a backend vs helpers for Azure / a specific Azure service. Say we wanted to port an AzureStorage backend hook to durable - where would that go? Or if we wanted to introduce helpers (not backends) for interacting with Azure services (Compute, Storage, CosmosDB, etc). Where would those go? There is the This also brings up the point of keeping a separate Worker and Client package. While it is more setup work on our end, the benefit is customers can bring in just the clients for their API projects and not need the entire worker. |
This reverts commit 14b94eb.
any advice on jacob's comment @cgillum ? |
@jviau thanks for all the comments! i updated the pr and its ready for another review, added more tests and tested it manually with sample and working |
@jviau this makes sense to me. How about this - there will be two new nuget packages:
I prefer "AzureManaged" over "Azure" because "Azure" becomes ambiguous if we ever wanted to introduce "AzureStorage" or something similar as a backend option for this SDK in the future. @YunchuWang in terms of project structure, how about this?
The |
split into separate packages and split tests, also add @cgillum 's sample to here using split packages and tested working |
@@ -0,0 +1,25 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should not be a shared project. Rather, we should important the code directly into the both the client and worker projects. The other directories under /src/Shared
as examples.
The reason for this is that we don't want to have to publish and maintain a "Shared" nuget package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct - move these files to src/Shared/AzureManaged
, then include them via:
<SharedSection Include="AzureManaged" />
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some public types in the AzureManaged shared files right now, which we want to avoid. Options are:
- Introduce another package
Microsoft.DurableTask.Abstractions.AzureManaged
to contain the common files.- this makes 3 packages for 1 feature. Once set up it isn't that hard to maintain, but I would understand if there is pushback on it being cumbersome to need 3 packages per backend.
- Consolidate all the packages into 1,
Microsoft.DurableTask.Backend.AzureManaged
orMicrosoft.DurableTask.AzureManaged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like number 2, 3 packages seem a bit cumbersome, basically we do a rename and go back to original approach before/ @cgillum for advice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as discussed with Chris offline, he suggested to keep two packages and use differently named option types to separate shared ones
@@ -0,0 +1,25 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some public types in the AzureManaged shared files right now, which we want to avoid. Options are:
- Introduce another package
Microsoft.DurableTask.Abstractions.AzureManaged
to contain the common files.- this makes 3 packages for 1 feature. Once set up it isn't that hard to maintain, but I would understand if there is pushback on it being cumbersome to need 3 packages per backend.
- Consolidate all the packages into 1,
Microsoft.DurableTask.Backend.AzureManaged
orMicrosoft.DurableTask.AzureManaged
test/Client/AzureManaged.Tests/DurableTaskSchedulerClientExtensionsTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Jacob Viau <javia@microsoft.com>
821acdd
to
c697fbc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor things.
- name: Setup .NET 6.0 | ||
uses: actions/setup-dotnet@v3 | ||
with: | ||
dotnet-version: '6.0.x' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this step needed? I would expect that the step below would take care of everything?
/// using the provided Durable Task Scheduler options. | ||
/// </summary> | ||
/// <param name="schedulerOptions">Monitor for accessing the current scheduler options configuration.</param> | ||
internal class ConfigureGrpcChannel(IOptionsMonitor<DurableTaskSchedulerClientOptions> schedulerOptions) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a private class?
internal class ConfigureGrpcChannel(IOptionsMonitor<DurableTaskSchedulerClientOptions> schedulerOptions) : | |
class ConfigureGrpcChannel(IOptionsMonitor<DurableTaskSchedulerClientOptions> schedulerOptions) : |
/// Gets or sets the worker ID used to identify the worker instance. | ||
/// The default value is a string containing the machine name, process ID, and a unique identifier. | ||
/// </summary> | ||
public string WorkerId { get; set; } = $"{Environment.MachineName},{Environment.ProcessId},{Guid.NewGuid():N}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Client options don't need a worker ID. We only need this for Worker options.
|
||
/// <summary> | ||
/// Gets or sets a value indicating whether to allow insecure channel credentials. | ||
/// This should only be set to true in development/testing scenarios. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// This should only be set to true in development/testing scenarios. | |
/// This should only be set to true in local development/testing scenarios. |
string authType = connectionString.Authentication; | ||
|
||
// Parse the supported auth types, in a case-insensitive way and without spaces | ||
switch (authType.ToLower(CultureInfo.InvariantCulture).Replace(" ", string.Empty)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not allow spaces. I'd like to reduce the test matrix that we have to worry about for all language SDKs. Also, I think it's more natural to use .ToLowerInvariant()
instead of .ToLower(CultureInfo.Invariant)
switch (authType.ToLower(CultureInfo.InvariantCulture).Replace(" ", string.Empty)) | |
switch (authType.ToLowerInvariant) |
|
||
public class DurableTaskSchedulerClientExtensionsTests | ||
{ | ||
private const string ValidEndpoint = "myaccount.westus3.durabletask.io"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: please update the code in these files to match the C# style used by this repo. Your editor should be getting hints about this because of the .editorconfig
file that exists in this repo. In particular, we don't use default visibility modifiers (like private
here) and we generally don't use var
.
// Assert | ||
var provider = services.BuildServiceProvider(); | ||
var options = provider.GetService<IOptions<GrpcDurableTaskClientOptions>>(); | ||
options.Should().NotBeNull(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why we don't validate the properties on the options in this test?
|
||
// Assert | ||
action.Should().Throw<ArgumentNullException>() | ||
.WithMessage("Value cannot be null. (Parameter 'The connection string is missing the required 'Endpoint' property.')"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look correct. It should be Parameter '{parameterName}'
but here you have it showing the message. Are we constructing exceptions incorrectly in the validation code?
|
||
// Act & Assert | ||
var action = () => mockBuilder.Object.UseDurableTaskScheduler(connectionString); | ||
action.Should().Throw<ArgumentException>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The correct exception to throw in this case is ArgumentNullException
.
}; | ||
|
||
// Act | ||
var channel = options.CreateChannel(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we dispose this channel to avoid leaking resources?
This pull request introduces several significant changes, primarily focusing on the setup of new projects and the integration of Azure Managed extensions for the Durable Task Framework client. The most important changes include the addition of new projects to the solution, updates to the build configuration, and the implementation of new client extensions and options for Azure Managed services.
New Projects and Build Configuration:
Worker.AzureManaged
,Client.AzureManaged
,Shared.AzureManaged.Tests
,Client.AzureManaged.Tests
, andWorker.AzureManaged.Tests
to the solution fileMicrosoft.DurableTask.sln
.Microsoft.DurableTask.sln
to include the newly added projects. [1] [2].github/workflows/validate-build.yml
.Azure Managed Client Implementation:
Client.AzureManaged.csproj
project file with necessary package references and project dependencies.DurableTaskSchedulerClientExtensions
to provide extension methods for configuring Durable Task clients to use the Azure Durable Task Scheduler service.DurableTaskSchedulerClientOptions
to configure the Durable Task Scheduler, including methods for creating gRPC channels and handling connection strings.AccessTokenCache
to manage and refresh Azure access tokens.DurableTaskSchedulerConnectionString
to parse and handle connection strings for the Durable Task Scheduler service.