Temporalio.Extensions.Hosting 1.3.1

Hosting and Dependency Injection Support

This extension adds support for worker Generic Hosts and activity Dependency Injection to the Temporal .NET SDK.

Quick Start

Add the Temporalio.Extensions.Hosting package from NuGet. For example, using the dotnet CLI:

dotnet add package Temporalio.Extensions.Hosting

To create a worker service, you can do the following:

using Temporalio.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);
// Add a hosted Temporal worker which returns a builder to add activities and workflows
builder.Services.
    AddHostedTemporalWorker(
        "my-temporal-host:7233",
        "my-namespace",
        "my-task-queue").
    AddScopedActivities<MyActivityClass>().
    AddWorkflow<MyWorkflow>();

var host = builder.Build();
// Make sure you use RunAsync and not Run, see https://github.com/temporalio/sdk-dotnet/issues/220
await host.RunAsync();

This creates a hosted Temporal worker which returns a builder. Then MyActivityClass is added to the service collection as scoped (via TryAddScoped) and registered on the worker. Also MyWorkflow is registered as a workflow on the worker.

Since we gave client parameters to the worker, the client connection is made as part of the worker. If desired, ITemporalClient can be created via the AddTemporalClient extension and it will be available as a singleton that can be used by other dependencies including the hosted worker service.

On the worker for every activity invocation, a new scope is created and the the activity is obtained via the service provider. So if it is registered as scoped the activity is created each time but if it registered as singleton it is created only once and reused. The activity's constructor can be used to accept injected dependencies.

Workflows are inherently self-contained, deterministic units of work and therefore should never call anything external. Therefore, there is no such thing as dependency injection for workflows, their construction and lifetime is managed by Temporal.

Clients

When this extension is depended upon, two overloads for AddTemporalClient are added as extension methods on IServiceCollection in the Microsoft.Extensions.DependencyInjection namespace which add ITemporalClient as a singleton if not already present. One overload accepts an optional client target/namespace and returns an option builder, and the other accepts an action to configure the options.

Worker Services

When this extension is depended upon, two overloads for AddHostedTemporalWorker are added as extension methods on IServiceCollection in the Microsoft.Extensions.DependencyInjection.

One overload of AddHostedTemporalWorker, used in the quick start sample above, accepts the client target host, the client namespace, and the worker task queue. This form will connect to a client for the worker. The other overload of AddHostedTemporalWorker only accepts the worker task queue. In the latter, an ITemporalClient can either be set on the services container and therefore reused across workers, or the resulting builder can have client options set.

When called, these register a TemporalWorkerServiceOptions options class with the container and return a ITemporalWorkerServiceOptionsBuilder for configuring the worker service options.

For adding activity classes to the service collection and registering activities with the worker, the following extension methods exist on the builder each accepting activity type:

  • AddSingletonActivities - TryAddSingleton + register activities on worker
  • AddScopedActivities - TryAddScoped + register activities on worker
  • AddTransientActivities - TryAddTransient + register activities on worker
  • AddStaticActivities - register activities on worker that all must be static
  • AddActivitiesInstance - register activities on worker via an existing instance

These all expect the activity methods to have the [Activity] attribute on them. If an activity type is already added to the service collection, ApplyTemporalActivities can be used to just register the activities on the worker.

For registering workflows on the worker, AddWorkflow extension method is available. This does nothing to the service collection because the construction and lifecycle of workflows is managed by Temporal. Dependency injection for workflows is intentionally not supported.

Other worker and client options can be configured on the builder via the ConfigureOptions extension method. With no parameters, this returns an OptionsBuilder<TemporalWorkerServiceOptions> to use. When provided an action, the options are available as parameters that can be configured. TemporalWorkerServiceOptions simply extends TemporalWorkerOptions with an added property for optional client options that can be set to connect a client on worker start instead of expecting a ITemporalClient to be present on the service collection.

⚠️WARNING: Make sure you use host RunAsync() and not Run() (see this issue)

Activity Dependency Injection without Worker Services

Some users may prefer to manually create the TemporalWorker without using host support, but still make their activities created via the service provider. CreateTemporalActivityDefinitions extension methods are present on IServiceProvider that will return a collection of ActivityDefinition instances for each activity on the type. These can be added to the TemporalWorkerOptions directly.

Worker Client Refresh

Some users may need to update the worker's connection to Temporal. It's desirable to do this without stopping the worker entirely, as that will evict the sticky workflow cache.

This can be done by using the IWorkerClientUpdater.

using Temporalio.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Register a worker client updater.
builder.Services.AddSingleton<TemporalWorkerClientUpdater>();

// Add a hosted Temporal worker which returns a builder to add activities and workflows, along with the worker client updater.
builder.Services.
    AddHostedTemporalWorker(
        "my-temporal-host:7233",
        "my-namespace",
        "my-task-queue").
    AddScopedActivities<MyActivityClass>().
    AddWorkflow<MyWorkflow>().
    ConfigureOptions().
    Configure<TemporalWorkerClientUpdater>((options, workerClientUpdater) => options.WorkerClientUpdater = workerClientUpdater);

var host = builder.Build();

// You can have a BackgroundService periodically refresh the worker client like this.
TemporalWorkerClientUpdater workerClientUpdater = host.Services.GetRequiredService<TemporalWorkerClientUpdater>();

// Can update the TLS options if you need.
TemporalClientConnectOptions clientConnectOptions = new("my-other-temporal-host:7233")
{
    Namespace = "default"
};

ITemporalClient updatedClient = await TemporalClient.ConnectAsync(clientConnectOptions).ConfigureAwait(false);

workerClientUpdater.UpdateClient(updatedClient);

// Make sure you use RunAsync and not Run, see https://github.com/temporalio/sdk-dotnet/issues/220
await host.RunAsync();

No packages depend on Temporalio.Extensions.Hosting.

.NET Framework 4.6.2

.NET 6.0

.NET Standard 2.0

Version Downloads Last updated
1.3.1 1 10/06/2024
1.3.0 0 08/14/2024
1.2.0 0 06/27/2024
1.1.2 0 06/05/2024
1.1.1 0 05/10/2024
1.1.0 0 05/07/2024
1.0.0 0 12/05/2023
0.1.0-beta2 0 10/30/2023
0.1.0-beta1 0 07/24/2023
0.1.0-alpha6 0 07/17/2023