Clear persisted output during Azure Storage rewind - #1397
Draft
wangbill (YunchuWang) wants to merge 1 commit into
Draft
Clear persisted output during Azure Storage rewind#1397wangbill (YunchuWang) wants to merge 1 commit into
wangbill (YunchuWang) wants to merge 1 commit into
Conversation
Replace the complete Azure Table instance row with its current ETag so rewind removes the terminal Output property without clobbering concurrent fields. Add unit and Azurite coverage for persisted state, retries, terminal rewrites, instance reuse, and shared large-output blobs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The core behavior change is narrowly scoped, uses ETag-guarded replaces to avoid concurrency clobbering, and is backed by targeted unit and Azurite scenario coverage.
Pull request overview
This PR fixes Azure Storage rewind persistence by ensuring the Instances-table Output property is physically removed when rewinding a terminal orchestration back to Pending, using an ETag-guarded full-entity Replace to avoid clobbering concurrent updates and to preserve unrelated properties.
Changes:
- Update
AzureTableTrackingStore.UpdateStatusForRewindAsyncto read the full Instances row, removeOutput, andReplaceusing the current ETag (instead ofMerge). - Add raw-storage unit coverage for output deletion, idempotency when output is missing, and ETag conflict propagation.
- Add Azurite scenario coverage for large-output rewinds to ensure the instance
Outputis removed while the history-referenced blob remains available.
File summaries
| File | Description |
|---|---|
src/DurableTask.AzureStorage/Tracking/AzureTableTrackingStore.cs |
Switch rewind status update from Merge to ETag-guarded Replace and remove persisted Output property. |
test/DurableTask.AzureStorage.Tests/RewindOutputTrackingStoreTests.cs |
Add raw Azurite tests validating Output removal, idempotency, terminal rewrites, and instance ID reuse behavior. |
test/DurableTask.AzureStorage.Tests/AzureTableTrackingStoreTest.cs |
Add mock-based unit tests asserting full-entity Replace with current ETag and 412 propagation behavior. |
test/DurableTask.AzureStorage.Tests/AzureStorageScenarioTests.cs |
Add end-to-end coverage for large-output rewind: instance Output cleared while shared history blob remains. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| @@ -0,0 +1,179 @@ | |||
| // ---------------------------------------------------------------------------------- | |||
Comment on lines
+124
to
+127
| bool created = await this.trackingStore.SetNewExecutionAsync( | ||
| CreateExecutionStartedEvent(instanceId, "execution-2"), | ||
| new ETag(existing.ETag.ToString()), | ||
| inputPayloadOverride: null); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Outputproperty when Azure Storage rewinds a failed orchestration toPending.Replace, preserving unrelated and unknown properties while rejecting concurrent changes with 412 instead of clobbering them.Persisted behavior
This is deletion at the provider persistence source, not API-layer hiding. Before this change,
UpdateStatusForRewindAsyncusedMerge, which could updateRuntimeStatusbut could not remove the existingOutputproperty. After this change, the Instances row has noOutputproperty while the rewound orchestration is pending. A later Completed or Failed checkpoint writes its new output normally.No host, client, serializer, or API projection suppression is added.
Large-output blobs
The large-output blob is not deleted by this change. The Instances-table URL is deleted, but the exact gzip blob remains because the rewound
ExecutionCompletedhistory row still storesResultBlobName, and history loading eagerly dereferences that property before deserializing the rewrittenGenericEvent.Deleting that blob without first coordinating removal of every history reference can break replay/history reads. Azure Table and Blob updates are not transactional, so crash- and retry-safe reclamation needs a durable cleanup ledger plus execution/write fencing (or a broader history-storage design change). The focused regression verifies that the exact history-referenced blob remains available. Existing purge behavior still removes all blobs for the instance.
Existing instance ID reuse
Current main already handles an accepted new execution safely:
SetNewExecutionAsyncbuilds a fresh row and ETag-replaces the old row, which removes the previousOutput. A raw Azurite regression now protects that invariant; no additional production change was needed for this path.Tests
dotnet test Test\DurableTask.AzureStorage.Tests\DurableTask.AzureStorage.Tests.csproj -f net8.0 --filter "Name~Rewind" --no-restore -p:NoWarn=NU1605dotnet test Test\DurableTask.AzureStorage.Tests\DurableTask.AzureStorage.Tests.csproj -f net48 --filter "Name~Rewind" --no-restore -p:NoWarn=NU1605dotnet test Test\DurableTask.AzureStorage.Tests\DurableTask.AzureStorage.Tests.csproj -f net8.0 --filter "FullyQualifiedName~RewindOutputTrackingStoreTests" --no-restore -p:NoWarn=NU1605dotnet test Test\DurableTask.AzureStorage.Tests\DurableTask.AzureStorage.Tests.csproj -f net48 --filter "FullyQualifiedName~RewindOutputTrackingStoreTests" --no-restore -p:NoWarn=NU1605Consumption
After this change ships in a new
Microsoft.Azure.DurableTask.AzureStoragepackage, Azure/azure-functions-durable-extension must update its provider dependency from 2.9.1 to that released version to consume the fix.Related: Azure/azure-functions-durable-extension#968