'Calling Two Durable Entity Methods in same Orchestration causes orchestration to hang and use up all memory

I have an orchestration which creates multiple tasks within a third-party system. So I want to initialise their status in a durable entity and then as they complete within the third-party system (via callback into my orchestration), update their status and then once all tasks are complete, finish my orchestration. Therefore, within one orchestration I want to update the status of a third-party task in my entity and then check whether all tasks are complete (according to my entity). If I try to execute both methods within the same orchestration my orchestration hangs and slowly uses up all memory and crashes.

My Entity

public class OrchestrationData : IOrchestrationData
{
    [JsonProperty("taskStatuses")]
    public List<TaskStatus> TaskStatuses { get; set; }  = new List<TaskStatus>();

    [FunctionName(nameof(OrchestrationData))]
    public static Task Run([EntityTrigger] IDurableEntityContext context)
        => context.DispatchAsync<OrchestrationData>();

    public Task<bool> AllTasksCompleteAsync()
    {
        return Task.FromResult(TaskStatuses.All(ts => ts.WorkflowStep == WfStep.Complete));
    }
    
    public Task SetTaskStatusAsync(TaskStatus status)
    {
        return Task.Run(() =>
        {
            if (TaskStatuses.SingleOrDefault(ts => ts.LanguageCode.Equals(status.LanguageCode)) == null)
            {
                TaskStatuses.Add(status);
            }
            else
            {
                TaskStatuses.Single(ts => ts.LanguageCode.Equals(status.LanguageCode))
                    .WorkflowStep = status.WorkflowStep;
            }
        });
    }
}

My Orchestrator

...
EntityId entityId = new EntityId(nameof(OrchestrationData), TaskIdentifier.ToString());
IOrchestrationData proxy = context.CreateEntityProxy<IOrchestrationData>(entityId);

// Having this
await proxy.SetTaskStatus(new TaskStatus(LanguageCode(), WfStep.Complete));

// OR this
bool areAllTasksComplete = await proxy.AllTaskCompleteAsync();

// executes okay - if both then orchestration goes crazy
if (areAllTasksComplete)
{
    // do stuff
}
...

I would expect this to be fine particularly as they are both awaited.

Update

After crashing if I look at the state of the durable entity it has a "Buffered": property so I guess there's a concurrency problem although I thought durable entities guaranteed processing of messages one at a time.

If I move the SetTaskStatus() call to another new Activity function then it appears to work.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source