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

Dependency injection sample #30

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Prerequisites:
* [ActivityWorker](src/ActivityWorker) - Use .NET activities from a workflow in another language.
* [AspNet](src/AspNet) - Demonstration of a generic host worker and an ASP.NET workflow starter.
* [ClientMtls](src/ClientMtls) - How to use client certificate authentication, e.g. for Temporal Cloud.
* [DependencyInjection](src/DependencyInjection) - How to inject dependencies in activities and use generic hosts for workers
* [Encryption](src/Encryption) - End-to-end encryption with Temporal payload codecs.
* [Polling](src/Polling) - Recommended implementation of an activity that needs to periodically poll an external resource waiting its successful completion.
* [Schedules](src/Schedules) - How to schedule workflows to be run at specific times in the future.
Expand Down
7 changes: 7 additions & 0 deletions TemporalioSamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemporalioSamples.Polling.I
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemporalioSamples.Polling.PeriodicSequence", "src\Polling\PeriodicSequence\TemporalioSamples.Polling.PeriodicSequence.csproj", "{11A5854B-EE6E-4752-9C46-F466503D853B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TemporalioSamples.DependencyInjection", "src\DependencyInjection\TemporalioSamples.DependencyInjection.csproj", "{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -116,6 +118,10 @@ Global
{11A5854B-EE6E-4752-9C46-F466503D853B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11A5854B-EE6E-4752-9C46-F466503D853B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11A5854B-EE6E-4752-9C46-F466503D853B}.Release|Any CPU.Build.0 = Release|Any CPU
{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7AECC7C6-9A21-4B8A-84D9-AFC4F5840CAF} = {1A647B41-53D0-4638-AE5A-6630BAAE45FC}
Expand All @@ -136,5 +142,6 @@ Global
{6935B8AC-160F-463D-BE03-AD6FF31585A3} = {AE21E7F4-B114-4761-81B1-8FA63E9F6BB8}
{DD2DE0CF-C127-461B-B4F1-D4E13BDD3B5D} = {AE21E7F4-B114-4761-81B1-8FA63E9F6BB8}
{11A5854B-EE6E-4752-9C46-F466503D853B} = {AE21E7F4-B114-4761-81B1-8FA63E9F6BB8}
{10E6F7C9-7F6C-4A8E-94A1-99C10F46BBA4} = {1A647B41-53D0-4638-AE5A-6630BAAE45FC}
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions src/DependencyInjection/IMyDatabaseClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TemporalioSamples.DependencyInjection;

public interface IMyDatabaseClient
{
Task<string> SelectValueAsync(string table);
}
14 changes: 14 additions & 0 deletions src/DependencyInjection/MyActivities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace TemporalioSamples.DependencyInjection;

using Temporalio.Activities;

public class MyActivities
{
private readonly IMyDatabaseClient databaseClient;

public MyActivities(IMyDatabaseClient databaseClient) => this.databaseClient = databaseClient;

[Activity]
public Task<string> SelectFromDatabaseAsync(string table) =>
databaseClient.SelectValueAsync(table);
}
7 changes: 7 additions & 0 deletions src/DependencyInjection/MyDatabaseClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TemporalioSamples.DependencyInjection;

public class MyDatabaseClient : IMyDatabaseClient
{
public Task<string> SelectValueAsync(string table) =>
Task.FromResult($"some-db-value from table {table}");
}
18 changes: 18 additions & 0 deletions src/DependencyInjection/MyWorkflow.workflow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace TemporalioSamples.DependencyInjection;

using Temporalio.Workflows;

[Workflow]
public class MyWorkflow
{
[WorkflowRun]
public async Task<string> RunAsync()
{
return await Workflow.ExecuteActivityAsync(
(MyActivities act) => act.SelectFromDatabaseAsync("some-db-table"),
new()
{
StartToCloseTimeout = TimeSpan.FromMinutes(5),
});
}
}
54 changes: 54 additions & 0 deletions src/DependencyInjection/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using Temporalio.Client;
using Temporalio.Extensions.Hosting;
using TemporalioSamples.DependencyInjection;

async Task RunWorkerAsync()
{
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureLogging(ctx =>
ctx.AddSimpleConsole().SetMinimumLevel(LogLevel.Information))
.ConfigureServices(ctx =>
ctx.
// Add the database client at the scoped level
AddScoped<IMyDatabaseClient, MyDatabaseClient>().
Comment on lines +12 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat. Ez.

// Add the worker
AddHostedTemporalWorker(
clientTargetHost: "localhost:7233",
clientNamespace: "default",
taskQueue: "dependency-injection-sample").
// Add the activities class at the scoped level
AddScopedActivities<MyActivities>().
AddWorkflow<MyWorkflow>())
.Build();
await host.RunAsync();
}

async Task ExecuteWorkflowAsync()
{
var client = await TemporalClient.ConnectAsync(new("localhost:7233")
{
LoggerFactory = LoggerFactory.Create(builder =>
builder.
AddSimpleConsole(options => options.TimestampFormat = "[HH:mm:ss] ").
SetMinimumLevel(LogLevel.Information)),
});

Console.WriteLine("Executing workflow");
var result = await client.ExecuteWorkflowAsync(
(MyWorkflow wf) => wf.RunAsync(),
new(id: "dependency-injection-workflow-id", taskQueue: "dependency-injection-sample"));

Console.WriteLine("Workflow result: {0}", result);
}

switch (args.ElementAtOrDefault(0))
{
case "worker":
await RunWorkerAsync();
break;
case "workflow":
await ExecuteWorkflowAsync();
break;
default:
throw new ArgumentException("Must pass 'worker' or 'workflow' as the single argument");
}
14 changes: 14 additions & 0 deletions src/DependencyInjection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Dependency Injection

This sample shows an activity having a dependency injected and a worker running as a generic host.

To run, first see [README.md](../../README.md) for prerequisites. Then, run the following from this directory
in a separate terminal to start the worker:

dotnet run worker

Then in another terminal, run the workflow from this directory:

dotnet run workflow

This will show logs in the worker window of the workflow running.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
</ItemGroup>
</Project>
Loading