Good day,
My question is mostly about best practices for using the Activity and Orchestrator functions. Haven't found the answer here - Microsoft docs
In short - I have a simple orchestrator that:
- retrieves some list of objects from an API (using Activity)
- processes these items (filters and sorts) (directly in Orchestrator)
- sends processed items to another API (using Activity)
Question: both API calls in Orchestrator (await context.CallActivityAsync()) is asynchronous and takes some time to execute. Functions framework unloads orchestrator (I'm on consumption plan) from memory and replays from the beginning (which is expected).
Every replay orchestrator gets saved (if executed already) state on vars from context.CallActivityAsync() calls, BUT not from local vars (e.g. objectsStartWithA, objectsStartWithB and filteredObjects from example below). It doesn't break anything but does the same things on every replay (if any) over and over again.
Do I need to extract all business logic to Activities and call them using await context.CallActivityAsync()?
namespace Demo.Functions
{
public class FunctionClass
{
public const string FunctionName = "Function1";
private readonly ILogger<FunctionClass> _logger;
public FunctionClass(
ILogger<FunctionClass> logger)
{
_logger = logger;
}
[FunctionName(FunctionName)]
public async Task ExecuteAsync([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var logger = context.CreateReplaySafeLogger(_logger);
logger.LogInformation("Process started");
var someObjects =
(await context.CallActivityAsync<IEnumerable<ApiObject>>("GetApiObjectsAsync", null)).ToList();
var objectsStartWithA =
someObjects
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith("a", StringComparison.OrdinalIgnoreCase))
.OrderBy(x => x.Name)
.ToList();
var objectsStartWithB =
someObjects
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith("b", StringComparison.OrdinalIgnoreCase))
.OrderBy(x => x.Name)
.ToList();
var objectsToCompare = objectsStartWithA.Union(objectsStartWithB);
//Long-running api request
var someOtherObjects =
(await context.CallActivityAsync<IEnumerable<ApiObject>>("GetOtherApiObjectsAsync", null)).ToList();
var filteredObjects =
someOtherObjects
.Where(x => objectsToCompare.All(z => z.Id != z.Id))
.OrderBy(x => x.Id)
.ToList();
//Saving
await context.CallActivityAsync("SaveObjects", filteredObjects);
logger.LogInformation("Process finished");
}
}
public class ApiObject
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Thank you!