mirror of https://github.com/dapr/dotnet-sdk.git
185 lines
7.5 KiB
C#
185 lines
7.5 KiB
C#
// ------------------------------------------------------------------------
|
|
// Copyright 2022 The Dapr Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ------------------------------------------------------------------------
|
|
|
|
namespace Dapr.Workflow
|
|
{
|
|
using System;
|
|
using Grpc.Net.Client;
|
|
using Microsoft.DurableTask.Client;
|
|
using Microsoft.DurableTask.Worker;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using System.Net.Http;
|
|
using Dapr;
|
|
|
|
/// <summary>
|
|
/// Contains extension methods for using Dapr Workflow with dependency injection.
|
|
/// </summary>
|
|
public static class WorkflowServiceCollectionExtensions
|
|
{
|
|
|
|
/// <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)
|
|
{
|
|
throw new ArgumentNullException(nameof(serviceCollection));
|
|
}
|
|
|
|
serviceCollection.TryAddSingleton<WorkflowRuntimeOptions>();
|
|
|
|
#pragma warning disable CS0618 // Type or member is obsolete - keeping around temporarily - replaced by DaprWorkflowClient
|
|
serviceCollection.TryAddSingleton<WorkflowEngineClient>();
|
|
#pragma warning restore CS0618 // Type or member is obsolete
|
|
serviceCollection.AddHostedService<WorkflowLoggingService>();
|
|
serviceCollection.TryAddSingleton<DaprWorkflowClient>();
|
|
serviceCollection.AddDaprClient();
|
|
serviceCollection.AddDaprWorkflowClient();
|
|
|
|
serviceCollection.AddOptions<WorkflowRuntimeOptions>().Configure(configure);
|
|
|
|
serviceCollection.AddDurableTaskWorker(builder =>
|
|
{
|
|
WorkflowRuntimeOptions options = new();
|
|
configure?.Invoke(options);
|
|
|
|
if (TryGetGrpcAddress(out string address))
|
|
{
|
|
var daprApiToken = DaprDefaults.GetDefaultDaprApiToken();
|
|
if (!string.IsNullOrEmpty(daprApiToken))
|
|
{
|
|
var client = new HttpClient();
|
|
client.DefaultRequestHeaders.Add("Dapr-Api-Token", daprApiToken);
|
|
builder.UseGrpc(CreateChannel(address, client));
|
|
}
|
|
else
|
|
{
|
|
builder.UseGrpc(address);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
builder.UseGrpc();
|
|
}
|
|
|
|
builder.AddTasks(registry => options.AddWorkflowsAndActivitiesToRegistry(registry));
|
|
});
|
|
|
|
return serviceCollection;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds Dapr Workflow client support to the service collection.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Use this extension method if you want to use <see cref="DaprWorkflowClient"/> in your app
|
|
/// but don't wish to define any workflows or activities.
|
|
/// </remarks>
|
|
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
|
|
public static IServiceCollection AddDaprWorkflowClient(this IServiceCollection services)
|
|
{
|
|
services.TryAddSingleton<DaprWorkflowClient>();
|
|
services.AddDurableTaskClient(builder =>
|
|
{
|
|
if (TryGetGrpcAddress(out string address))
|
|
{
|
|
var daprApiToken = DaprDefaults.GetDefaultDaprApiToken();
|
|
if (!string.IsNullOrEmpty(daprApiToken))
|
|
{
|
|
var client = new HttpClient();
|
|
client.DefaultRequestHeaders.Add("Dapr-Api-Token", daprApiToken);
|
|
builder.UseGrpc(CreateChannel(address, client));
|
|
}
|
|
else
|
|
{
|
|
builder.UseGrpc(address);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
builder.UseGrpc();
|
|
}
|
|
|
|
builder.RegisterDirectly();
|
|
});
|
|
|
|
return services;
|
|
}
|
|
|
|
static bool TryGetGrpcAddress(out string address)
|
|
{
|
|
// TODO: Ideally we should be using DaprDefaults.cs for this. However, there are two blockers:
|
|
// 1. DaprDefaults.cs uses 127.0.0.1 instead of localhost, which prevents testing with Dapr on WSL2 and the app on Windows
|
|
// 2. DaprDefaults.cs doesn't compile when the project has C# nullable reference types enabled.
|
|
// If the above issues are fixed (ensuring we don't regress anything) we should switch to using the logic in DaprDefaults.cs.
|
|
var daprEndpoint = DaprDefaults.GetDefaultGrpcEndpoint();
|
|
if (!String.IsNullOrEmpty(daprEndpoint)) {
|
|
address = daprEndpoint;
|
|
return true;
|
|
}
|
|
|
|
var daprPortStr = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT");
|
|
if (int.TryParse(daprPortStr, out int daprGrpcPort))
|
|
{
|
|
// There is a bug in the Durable Task SDK that requires us to change the format of the address
|
|
// depending on the version of .NET that we're targeting. For now, we work around this manually.
|
|
#if NET6_0_OR_GREATER
|
|
address = $"http://localhost:{daprGrpcPort}";
|
|
#else
|
|
address = $"localhost:{daprGrpcPort}";
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
address = string.Empty;
|
|
return false;
|
|
}
|
|
|
|
static GrpcChannel CreateChannel(string address, HttpClient client)
|
|
{
|
|
|
|
GrpcChannelOptions options = new() { HttpClient = client};
|
|
var daprEndpoint = DaprDefaults.GetDefaultGrpcEndpoint();
|
|
if (!String.IsNullOrEmpty(daprEndpoint)) {
|
|
return GrpcChannel.ForAddress(daprEndpoint, options);
|
|
}
|
|
|
|
var daprPortStr = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT");
|
|
if (int.TryParse(daprPortStr, out int daprGrpcPort))
|
|
{
|
|
// If there is no address passed in, we default to localhost
|
|
if (String.IsNullOrEmpty(address))
|
|
{
|
|
// There is a bug in the Durable Task SDK that requires us to change the format of the address
|
|
// depending on the version of .NET that we're targeting. For now, we work around this manually.
|
|
#if NET6_0_OR_GREATER
|
|
address = $"http://localhost:{daprGrpcPort}";
|
|
#else
|
|
address = $"localhost:{daprGrpcPort}";
|
|
#endif
|
|
}
|
|
|
|
}
|
|
return GrpcChannel.ForAddress(address, options);
|
|
}
|
|
}
|
|
}
|