Temporalio.Extensions.Hosting 1.3.1

Prefix Reserved
dotnet add package Temporalio.Extensions.Hosting --version 1.3.1                
NuGet\Install-Package Temporalio.Extensions.Hosting -Version 1.3.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Temporalio.Extensions.Hosting" Version="1.3.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Temporalio.Extensions.Hosting --version 1.3.1                
#r "nuget: Temporalio.Extensions.Hosting, 1.3.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Temporalio.Extensions.Hosting as a Cake Addin
#addin nuget:?package=Temporalio.Extensions.Hosting&version=1.3.1

// Install Temporalio.Extensions.Hosting as a Cake Tool
#tool nuget:?package=Temporalio.Extensions.Hosting&version=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();
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Temporalio.Extensions.Hosting:

Package Downloads
OlegShilo.Temporalio.Graphs

Graph builder for Temporal Workflows

InfinityFlow.Temporal.Migrator

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.1 35,395 9/11/2024
1.3.0 19,171 8/14/2024
1.2.0 27,287 6/27/2024
1.1.2 8,668 6/5/2024
1.1.1 9,393 5/10/2024
1.1.0 851 5/7/2024
1.0.0 120,811 12/5/2023
0.1.0-beta2 14,836 10/30/2023
0.1.0-beta1 11,118 7/24/2023
0.1.0-alpha6 238 7/17/2023