Thanks for the response but something is still unclear to me.
Many of my dependencies are Scoped Services. I’m not sure that simply injecting these to the activity class will retain their scope.
I’ll try to clarify (hopefully) with an example:
My original implementation without temporal is similar to this:
// Original flow without temporal
//.....
using (var scope = serviceProvider.CreateScope())
{
var happyService = scope.ServiceProvider.GetRequiredService<IMyHappyService>();
var funService = await scope.ServiceProvider.GetRequiredService<IMyFunService>();
await happyService.BeHappyAsync(tenantId);
var jollyService = scope.ServiceProvider.GetRequiredService<IMyJollyService>();
await jollyService.DoJollyThingsAsync();
await funService.HaveFunAsync();
}
Now I would like to transform this flow to work with Temporal, where the 3 awaited statements would be the activities of this flow. From my understanding the new implementation would be something like the following (some part omitted for brevity):
// New Temporal-supported flow
//.....
using (var scope = serviceProvider.CreateScope())
{
await temporalClient.ExecuteWorkflowAsync(MyWorkflow.Ref.RunAsync,
new List<string>(),
new WorkflowOptions($"Some Id", "Some Queue Name"));
}
//...
[Workflow("Some Workflow Name")]
public class MyWorkflow
{
// Understand the reason for this pattern
public static MyWorkflow Ref = WorkflowRefs.Create<MyWorkflow>();
private readonly ActivityOptions _options = new()
{
// ...
};
[WorkflowRun]
public async Task RunAsync()
{
await Workflow.ExecuteActivityAsync(
"Be Happy Activity",
new List<object>(),
_options);
await Workflow.ExecuteActivityAsync(
"Do Jolly Things Activity",
new List<object>(),
_options);
await workflow.ExecuteActivityAsync(
"Have Fun Activity",
new List<object>(),
_options);
}
}
// Need to inject scoped services here
public class TenantCreationActivities
{
private readonly IMyHappyService _happyService;
private readonly IMyFunService _funService;
private readonly IMyJollyService _jollyService;
public TenantCreationActivities(
IMyHappyService happyService,
IMyFunService funService,
IMyJollyService jollyService
)
{
_happyService = happyService;
_funService = funService;
_jollyService = jollyService;
}
[Activity("Be Happy Activity")]
public async Task HappyActivity()
{
await happyService.BeHappyAsync();
}
[Activity("Do Jolly Things Activity")]
public async Task JollyActivity()
{
await jollyService.DoJollyThingsAsync();
}
[Activity("Have Fun Activity")]
public async Task FunActivity()
{
await funService.HaveFunAsync();
}
}
Is this indeed the expected way to use scoped dependencies when building a Temporal workflow?
If not any guidance will be appreciated.
You cannot use dependency injection into workflows (nor can you blindly convert all existing code to workflows because workflows have logic/determinism constraints). But you can use dependency injection in activities. See this extension and this sample.