diff --git a/src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs b/src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs index c30a79288..c21d6d1b7 100644 --- a/src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs +++ b/src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs @@ -1065,7 +1065,11 @@ async Task IsExecutableInstance(OrchestrationRuntimeState runtimeState, TaskMessage executionTerminatedEventMessage = newMessages.LastOrDefault(msg => msg.Event is ExecutionTerminatedEvent); if (executionTerminatedEventMessage is not null) { - await this.trackingStore.UpdateStatusForTerminationAsync(instanceId, ((ExecutionTerminatedEvent)executionTerminatedEventMessage.Event).Input); + var executionTerminatedEvent = (ExecutionTerminatedEvent)executionTerminatedEventMessage.Event; + await this.trackingStore.UpdateStatusForTerminationAsync( + instanceId, + executionTerminatedEvent.Input, + executionTerminatedEvent.Timestamp); return $"Instance is {OrchestrationStatus.Terminated}"; } diff --git a/src/DurableTask.AzureStorage/Tracking/AzureTableTrackingStore.cs b/src/DurableTask.AzureStorage/Tracking/AzureTableTrackingStore.cs index d48ef21bf..cb5c2bfb5 100644 --- a/src/DurableTask.AzureStorage/Tracking/AzureTableTrackingStore.cs +++ b/src/DurableTask.AzureStorage/Tracking/AzureTableTrackingStore.cs @@ -796,13 +796,18 @@ public override async Task UpdateStatusForRewindAsync(string instanceId, Cancell } /// - public override async Task UpdateStatusForTerminationAsync(string instanceId, string output, CancellationToken cancellationToken = default) + public override async Task UpdateStatusForTerminationAsync( + string instanceId, + string output, + DateTime lastUpdatedTime, + CancellationToken cancellationToken = default) { string sanitizedInstanceId = KeySanitation.EscapePartitionKey(instanceId); TableEntity entity = new TableEntity(sanitizedInstanceId, "") { ["RuntimeStatus"] = OrchestrationStatus.Terminated.ToString("G"), - ["LastUpdatedTime"] = DateTime.UtcNow, + ["LastUpdatedTime"] = lastUpdatedTime, + ["CompletedTime"] = DateTime.UtcNow, [OutputProperty] = output }; diff --git a/src/DurableTask.AzureStorage/Tracking/ITrackingStore.cs b/src/DurableTask.AzureStorage/Tracking/ITrackingStore.cs index 3ce82cf37..19dccd35c 100644 --- a/src/DurableTask.AzureStorage/Tracking/ITrackingStore.cs +++ b/src/DurableTask.AzureStorage/Tracking/ITrackingStore.cs @@ -157,8 +157,9 @@ interface ITrackingStore /// /// The instance being terminated /// The output of the orchestration + /// The last updated time of the orchestration (the time the termination request was created) /// The token to monitor for cancellation requests. The default value is . - Task UpdateStatusForTerminationAsync(string instanceId, string output, CancellationToken cancellationToken = default); + Task UpdateStatusForTerminationAsync(string instanceId, string output, DateTime lastUpdatedTime, CancellationToken cancellationToken = default); /// /// Purge The History and state which is older than thresholdDateTimeUtc based on the timestamp type specified by timeRangeFilterType diff --git a/src/DurableTask.AzureStorage/Tracking/InstanceStoreBackedTrackingStore.cs b/src/DurableTask.AzureStorage/Tracking/InstanceStoreBackedTrackingStore.cs index 53c133e7b..0548bfeeb 100644 --- a/src/DurableTask.AzureStorage/Tracking/InstanceStoreBackedTrackingStore.cs +++ b/src/DurableTask.AzureStorage/Tracking/InstanceStoreBackedTrackingStore.cs @@ -177,12 +177,17 @@ await instanceStore.WriteEntitiesAsync(new InstanceEntityBase[] return null; } - public override async Task UpdateStatusForTerminationAsync(string instanceId, string output, CancellationToken cancellationToken = default) + public override async Task UpdateStatusForTerminationAsync( + string instanceId, + string output, + DateTime lastUpdatedTime, + CancellationToken cancellationToken = default) { // Get the most recent execution and update its status to terminated IEnumerable instanceEntity = await this.instanceStore.GetOrchestrationStateAsync(instanceId, allInstances: false); instanceEntity.Single().State.OrchestrationStatus = OrchestrationStatus.Terminated; - instanceEntity.Single().State.LastUpdatedTime = DateTime.UtcNow; + instanceEntity.Single().State.LastUpdatedTime = lastUpdatedTime; + instanceEntity.Single().State.CompletedTime = DateTime.UtcNow; instanceEntity.Single().State.Output = output; await this.instanceStore.WriteEntitiesAsync(instanceEntity); } diff --git a/src/DurableTask.AzureStorage/Tracking/TrackingStoreBase.cs b/src/DurableTask.AzureStorage/Tracking/TrackingStoreBase.cs index 4317e42f0..ee8e2012c 100644 --- a/src/DurableTask.AzureStorage/Tracking/TrackingStoreBase.cs +++ b/src/DurableTask.AzureStorage/Tracking/TrackingStoreBase.cs @@ -101,7 +101,7 @@ public virtual Task UpdateStatusForRewindAsync(string instanceId, CancellationTo } /// - public abstract Task UpdateStatusForTerminationAsync(string instanceId, string output, CancellationToken cancellationToken = default); + public abstract Task UpdateStatusForTerminationAsync(string instanceId, string output, DateTime lastUpdatedTime, CancellationToken cancellationToken = default); /// public abstract Task StartAsync(CancellationToken cancellationToken = default);