Azure / durabletask

Durable Task Framework allows users to write long running persistent workflows in C# using the async/await capabilities.
Apache License 2.0
1.51k stars 290 forks source link

Orchestration will wait for all tasks to finish even Task.WhenAny is used #415

Open t-bzhan opened 4 years ago

t-bzhan commented 4 years ago

I found that Task.WhenAny did not work with orchestration properly, the status of orchestration only become completed where all the scheduled tasks are finished.

My orchestration goes like:

    public enum OperationState
    {
        Successful,

        Failed,

        InProgess,

        Timeout
    }

    public class DummyOrchestration : TaskOrchestration<OperationState, string>
    {
        public override async Task<OperationState> RunTask(OrchestrationContext context, string input)
        {
            using (var timeoutCts = new CancellationTokenSource())
            {
                Task<OperationState> user = context.ScheduleTask<OperationState>(typeof(DummyActivity), input);
                Task<OperationState> timer = context.CreateTimer(context.CurrentUtcDateTime.AddSeconds(60), OperationState.Timeout, timeoutCts.Token);

                var resultTask = await Task.WhenAny(user, timer);
                if(resultTask == user)
                {
                    timeoutCts.Cancel();
                }

                Console.WriteLine($"{DateTimeOffset.Now}: Orchestration finished with {resultTask.Result}");
                return resultTask.Result;
            }
        }
    }

And my activity goes like:

    public sealed class DummyActivity : AsyncTaskActivity<string, OperationState>
    {
        protected override async Task<OperationState> ExecuteAsync(TaskContext context, string input)
        {            
            Console.WriteLine($"{DateTimeOffset.Now}: Dummy {input} recevied, will finished in one day!");

            // Simulate some long running actions
            await Task.Delay(TimeSpan.FromDays(1));

            return OperationState.Successful;
        }
    }

From the console log, I could see that the orchestration RunTask code actually finished, but it behaves like the long running DummyActivity prevent its status to becoming completed and I could see there are 1 message in the workitem queue.

7/5/2020 7:22:38 PM +08:00: Dummy input1 recevied, will finished in one day! 7/5/2020 7:24:00 PM +08:00: Orchestration finished with Timeout

image

From the issue, I know for timer task, I could use an cancellation token to cancel any pending timers, but how can I cancel a long running TaskActivity?

Package information:

<PackageReference Include="Microsoft.Azure.DurableTask.AzureStorage" Version="1.7.7" />
<PackageReference Include="Microsoft.Azure.DurableTask.Core" Version="2.3.0" />
<PackageReference Include="Microsoft.Azure.DurableTask.ServiceBus" Version="2.3.0" />
cgillum commented 4 years ago

This is a known behavior of the core framework and unfortunately there is no way to cancel a long-running activity function. I'll leave this open as a feature request.