Skip to content
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

Fix for DI registration not completing as expected #1386

Merged
merged 11 commits into from
Nov 5, 2024
36 changes: 16 additions & 20 deletions src/Dapr.Workflow/DaprWorkflowClientBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,40 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

#nullable enable

namespace Dapr.Workflow;

/// <summary>
/// A factory for building a <see cref="DaprWorkflowClient"/>.
/// </summary>
internal sealed class DaprWorkflowClientBuilderFactory
{
private readonly IConfiguration _configuration;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServiceCollection _services;
private readonly IConfiguration? configuration;
private readonly IHttpClientFactory httpClientFactory;

/// <summary>
/// Constructor used to inject the required types into the factory.
/// </summary>
public DaprWorkflowClientBuilderFactory(IConfiguration configuration, IHttpClientFactory httpClientFactory, IServiceCollection services)
public DaprWorkflowClientBuilderFactory(IConfiguration? configuration, IHttpClientFactory httpClientFactory)
{
_configuration = configuration;
_httpClientFactory = httpClientFactory;
_services = services;
this.configuration = configuration;
this.httpClientFactory = httpClientFactory;
}

/// <summary>
/// Responsible for building the client itself.
/// </summary>
/// <returns></returns>
public void CreateClientBuilder(Action<WorkflowRuntimeOptions> configure)
public void CreateClientBuilder(IServiceCollection services, Action<WorkflowRuntimeOptions> configure)
WhitWaldo marked this conversation as resolved.
Show resolved Hide resolved
{
_services.AddDurableTaskClient(builder =>
services.AddDurableTaskClient(builder =>
{
WorkflowRuntimeOptions options = new();
configure?.Invoke(options);
configure.Invoke(options);

var apiToken = DaprDefaults.GetDefaultDaprApiToken(_configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(_configuration);
var apiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);

var httpClient = _httpClientFactory.CreateClient();
var httpClient = httpClientFactory.CreateClient();

if (!string.IsNullOrWhiteSpace(apiToken))
{
Expand All @@ -72,17 +68,17 @@ public void CreateClientBuilder(Action<WorkflowRuntimeOptions> configure)
builder.RegisterDirectly();
});

_services.AddDurableTaskWorker(builder =>
services.AddDurableTaskWorker(builder =>
{
WorkflowRuntimeOptions options = new();
configure?.Invoke(options);
configure.Invoke(options);

var apiToken = DaprDefaults.GetDefaultDaprApiToken(_configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(_configuration);
var apiToken = DaprDefaults.GetDefaultDaprApiToken(configuration);
var grpcEndpoint = DaprDefaults.GetDefaultGrpcEndpoint(configuration);

if (!string.IsNullOrEmpty(grpcEndpoint))
{
var httpClient = _httpClientFactory.CreateClient();
var httpClient = httpClientFactory.CreateClient();

if (!string.IsNullOrWhiteSpace(apiToken))
{
Expand Down
74 changes: 39 additions & 35 deletions src/Dapr.Workflow/WorkflowServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,51 +11,55 @@
// limitations under the License.
// ------------------------------------------------------------------------

namespace Dapr.Workflow
{
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Net.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace Dapr.Workflow;

/// <summary>
/// Contains extension methods for using Dapr Workflow with dependency injection.
/// </summary>
public static class WorkflowServiceCollectionExtensions
{
/// <summary>
/// Contains extension methods for using Dapr Workflow with dependency injection.
/// Adds Dapr Workflow support to the service collection.
/// </summary>
public static class WorkflowServiceCollectionExtensions
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">A delegate used to configure actor options and register workflow functions.</param>
public static IServiceCollection AddDaprWorkflow(
this IServiceCollection serviceCollection,
Action<WorkflowRuntimeOptions> configure)
{
/// <summary>
/// Adds Dapr Workflow support to the service collection.
/// </summary>
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
/// <param name="configure">A delegate used to configure actor options and register workflow functions.</param>
public static IServiceCollection AddDaprWorkflow(
this IServiceCollection serviceCollection,
Action<WorkflowRuntimeOptions> configure)
if (serviceCollection == null)
{
if (serviceCollection == null)
{
throw new ArgumentNullException(nameof(serviceCollection));
}
throw new ArgumentNullException(nameof(serviceCollection));
}

serviceCollection.TryAddSingleton<WorkflowRuntimeOptions>();
serviceCollection.AddHttpClient();
serviceCollection.TryAddSingleton<WorkflowRuntimeOptions>();
serviceCollection.AddHttpClient();

#pragma warning disable CS0618 // Type or member is obsolete - keeping around temporarily - replaced by DaprWorkflowClient
serviceCollection.TryAddSingleton<WorkflowEngineClient>();
serviceCollection.TryAddSingleton<WorkflowEngineClient>();
#pragma warning restore CS0618 // Type or member is obsolete
serviceCollection.AddHostedService<WorkflowLoggingService>();
serviceCollection.TryAddSingleton<DaprWorkflowClient>();
serviceCollection.AddDaprClient();
serviceCollection.AddHostedService<WorkflowLoggingService>();
serviceCollection.TryAddSingleton<DaprWorkflowClient>();
serviceCollection.AddDaprClient();

serviceCollection.AddOptions<WorkflowRuntimeOptions>().Configure(configure);

serviceCollection.AddSingleton(c =>
{
var factory = c.GetRequiredService<DaprWorkflowClientBuilderFactory>();
factory.CreateClientBuilder(configure);
return new object(); //Placeholder as actual registration is performed inside factory
});

return serviceCollection;
serviceCollection.AddOptions<WorkflowRuntimeOptions>().Configure(configure);
//Register the factory and force resolution so the Durable Task client and worker can be registered
using (var scope = serviceCollection.BuildServiceProvider().CreateScope())
{
var httpClientFactory = scope.ServiceProvider.GetRequiredService<IHttpClientFactory>();
var configuration = scope.ServiceProvider.GetService<IConfiguration>();
var factory = new DaprWorkflowClientBuilderFactory(configuration, httpClientFactory);
factory.CreateClientBuilder(serviceCollection, configure);
}

return serviceCollection;
}
}
Loading