镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Fix ControlQueue buffer cleanup after batch failures - #1434

Merged
sophiatev merged 8 commits into
mainfrom
stevosyan/fix-failed-messages-in-buffers
Nov 12, 2026
Merged

sophiatev merged 8 commits into
mainfrom
stevosyan/fix-failed-messages-in-buffers

Conversation

@sophiatev

@sophiatev sophiatev commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Roll back buffer IDs newly reserved by a ControlQueue batch if the batch fails before handoff.
  • Preserve reservations from earlier batches, including duplicates.

Regression coverage

One mocked test verifies new reservations are removed, an existing duplicate reservation survives, and receiving can continue after the failed batch.

Validation

  • The regression fails without the fix.
  • Passes on .NET 8 and .NET Framework 4.8.
  • No Azure Storage or experiment resources used.

This PR is limited to ControlQueue.cs and its focused test in MessageManagerTests.cs. Session management, work-item preparation, prefetch retry, shutdown, rewind, and completion behavior are unchanged.

Release failed dequeue and deduplication buffer slots, retry storage timeouts, and abandon sessions that never handed off a work item without disturbing deferred or replacement-session ownership.

Add focused regressions for these failure paths.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 00:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The failure cleanup can remove an already-buffered duplicate’s reservation while its original message remains live, undercounting buffered messages and allowing receives to exceed ControlQueueBufferThreshold.

1 open issue
What changed in this PR

This PR improves Azure Storage failure recovery by cleaning up message-buffer reservations and sessions when processing fails before work is handed off.

Changes:

  • Adds cleanup for failed dequeue batches, execution-start deduplication, and work-item preparation.
  • Retries storage-request cancellations when the listener itself has not been canceled.
  • Adds seven mocked regression cases covering failures, deferred messages, and replacement-session ownership.
File Description
test/​DurableTask.AzureStorage.Tests/​TestHelpers.cs Adds shared mock queue settings.
test/​DurableTask.AzureStorage.Tests/​OrchestrationStatePrefetchTests.cs Tests retries after history and instance-status timeouts.
test/​DurableTask.AzureStorage.Tests/​MessageManagerTests.cs Tests buffer cleanup after dequeue and deduplication failures.
test/​DurableTask.AzureStorage.Tests/​AzureStorageScenarioTests.cs Tests preparation failures and deferred/replacement-session cleanup.
src/​DurableTask.AzureStorage/​OrchestrationSessionManager.cs Adds deduplication-failure cleanup and distinguishes shutdown from request cancellation.
src/​DurableTask.AzureStorage/​Messaging/​ControlQueue.cs Releases newly reserved buffer entries after batch failures.
src/​DurableTask.AzureStorage/​AzureStorageOrchestrationService.cs Abandons failed sessions while preserving deferred messages and replacement ownership.

Review effort: Balanced

Carry only newly reserved message IDs through execution-start status checks so failures do not remove buffer entries owned by earlier copies of duplicates.

Cover duplicates whose original messages remain in pending batches or active sessions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 05:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

A pending duplicate can be requeued after preparation failure without restoring its buffer reservation, causing it to escape ControlQueueBufferThreshold accounting.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Restore buffer reservation when requeuing pending duplicate

src/​DurableTask.AzureStorage/​AzureStorageOrchestrationService.cs:909

If a duplicate of a current message arrives while work-item preparation awaits storage, it enters session.PendingMessages without reserving another buffer slot. This abandonment removes the shared message ID from PendingOrchestratorMessages, but session release requeues the pending copy without restoring its reservation, so it no longer counts against ControlQueueBufferThreshold. Preserve or restore reservations for retained pending copies during the session handoff, and add a preparation-failure regression test for this case.

1 resolved since last review

Review effort: Balanced

Re-establish buffer entries for pending and deferred messages at the locked session handoff. This preserves a reservation when abandonment of a current message removes the entry shared with a pending duplicate.

Add a deterministic preparation-failure regression that injects the duplicate while storage validation is awaiting completion.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 06:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Critical reservation-ownership bugs can leave reservations unreleased after forced shutdown or remove reservations for retained duplicates, blocking dequeuing or leaving buffered messages uncounted against the threshold.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

High severity Forced shutdown leaks buffer reservations for aborted sessions

src/​DurableTask.AzureStorage/​AzureStorageOrchestrationService.cs:1153

Forced shutdown calls AbortAllSessions(), which clears the active registry without releasing buffer reservations, so this guard skips cleanup if an in-flight preparation request subsequently cancels or times out. Restarting the same service reuses those reservations and can block dequeuing once ControlQueueBufferThreshold is reached. Distinguish aborted sessions from already-cleaned sessions, or release their reservations during abort, while preserving replacement-session ownership.

High severity Rollback can remove reservations retained by duplicate sessions

src/​DurableTask.AzureStorage/​Messaging/​ControlQueue.cs:184

After abandonment removes a reservation, this dequeue can reserve the same ID while an earlier duplicate remains pending; if TryReleaseSession requeues that duplicate before this batch fails, its TryAdd does not establish a separate reservation. This rollback then removes the retained duplicate's reservation, leaving buffered messages uncounted against ControlQueueBufferThreshold; the same issue occurs in OrchestrationSessionManager.cs:167–169. Coordinate reservation ownership between acquisition, session retention, and both rollback paths rather than removing entries solely by saved ID.

Review effort: Balanced

Remove reservations for messages owned by aborted sessions while preserving IDs still held by independent pending batches. Keep late cleanup from touching replacement sessions.

Cover delayed preparation cancellation and failure, all session message collections, resumed receiving, and shared pending reservations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 06:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

During forced shutdown, concurrent collection mutations can make session enumeration throw before active sessions are cleared, interrupting shutdown before the lease manager stops.

1 open issue

Review effort: Balanced

Restore the existing AbortAllSessions behavior rather than enumerate message collections without synchronization shared with processing code. Remove the dedicated cleanup tests and their now-unneeded test adaptation.

Keep the earlier failed-dequeue, deduplication, and work-item-preparation fixes unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 07:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are recorded for the Azure Storage failure-recovery changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 12, 2026 18:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Reservation cleanup can leave duplicate ExecutionStarted messages buffered but uncounted toward ControlQueueBufferThreshold, requiring recovery fixes and regression coverage for both arrival timings.

1 open issue

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 12, 2026 20:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues block approval of the failure-recovery changes.

1 open issue

Review effort: Balanced

Keep only rollback of buffer IDs newly inserted by a failed ControlQueue receive batch and a focused mocked regression test.

Remove session management, work-item preparation, prefetch retry and handoff changes along with their tests and shared helper additions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 12, 2026 21:10
@sophiatev sophiatev changed the title Fix failed-message buffer cleanup in Azure Storage Fix ControlQueue buffer cleanup after batch failures Nov 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the failed-batch buffer cleanup changes.

1 open issue

Review effort: Balanced

@YunchuWang wangbill (YunchuWang) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the narrowed patch at 71e83fd. The earlier session-management, work-item-preparation and prefetch changes have been removed, so the associated findings no longer apply to this diff. The remaining ControlQueue change rolls back only IDs newly reserved by a failed batch, after all batch tasks complete, preserving earlier duplicate reservations. The focused regression passed on net8.0 and net48. No remaining blocking findings in this scope. Upstream CI is still running.

@sophiatev
sophiatev merged commit 4768363 into main Nov 12, 2026
48 checks passed
@sophiatev
sophiatev deleted the stevosyan/fix-failed-messages-in-buffers branch November 12, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants