Skip to content

fix(reminders): reconcile stale-owner registrations - #10612

Merged
ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-fix-azure-reminder-test-race
Aug 17, 2026
Merged

ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-fix-azure-reminder-test-race

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Aug 15, 2026 •

Copy link
Copy Markdown
Member

Problem

Reminder registration requests can arrive on a silo which no longer owns the reminder's ring range. The service persisted the registration and also created a local schedule on that stale owner. The real owner only discovered the row during a later refresh, producing transient duplicate owners or leaving deterministic fake-time tests waiting for an owner transition which could not occur until time advanced.

This explains the recurring Azure suite pattern: missing local schedule-update diagnostics, tick-readiness waits timing out, and duplicate owner assertions after topology changes.

Solution

Only reconcile a newly persisted registration into the local schedule when the receiving reminder service currently owns the grain's ring range. Non-owner registrations remain durable and are loaded by the current owner during reconciliation.

Make the deterministic reminder tests explicitly refresh active reminder services before waiting for owner schedules or advancing fake time. Timeout diagnostics now include reminder identity, owner silos, tick count, and fake time.

Rationale

The runtime change restores the existing ownership invariant instead of masking the race with longer timeouts. The test barrier drives the same storage reconciliation used in production, removing the circular dependency between periodic refresh and fake-time advancement.

Fixes #10499

Microsoft Reviewers: Open in CodeFlow

Persist registrations received by stale owners without creating transient local schedules. Refresh active reminder services before deterministic test clock advances so owner readiness is explicitly observed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 15, 2026 16:50

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.

Pull request overview

This PR fixes a reminders ownership race in Orleans where a reminder registration/update could be persisted on a silo which no longer owns the grain’s ring range and incorrectly be reconciled into that stale owner’s local schedule. The change restores the invariant that only the current ring-range owner schedules and ticks reminders locally, and updates deterministic reminder tests to explicitly drive storage reconciliation before advancing fake time or asserting ownership.

Changes:

  • Gate LocalReminderService.RegisterOrUpdateReminder local reconciliation so it only schedules reminders when the service currently owns the grain’s ring range.
  • Update reminder test helpers to actively refresh reminder services and synchronize local schedules before/after fake-time advancement and before waiting on tick/counter progress.
  • Improve timeout diagnostics for schedule synchronization to include reminder identity, owners/silos, tick count, and current fake time.
Show a summary per file
File Description
test/Orleans.Reminders.Tests/TimerTests/ReminderTestsBase.cs Adds a refresh/synchronization barrier so deterministic reminder tests drive reconciliation explicitly and get better diagnostics on timeout.
src/Orleans.Reminders/ReminderService/LocalReminderService.cs Prevents stale ring-range owners from creating local schedules for newly persisted reminder registrations/updates.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

{
entry.ETag = newEtag;
ReconcileLocalReminder(entry, _timeProvider.GetUtcNow().UtcDateTime);
// A request can arrive on a stale owner. Persist it here, but let the current owner load it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It would be better to forward to the new owner, but that is a bigger change. We should open an issue for it - we could use the Virtual Synchrony approach, similar to the DistributedGrainDirectory

@ReubenBond
ReubenBond merged commit 2705575 into dotnet:main Aug 17, 2026
73 checks passed
@ReubenBond
ReubenBond deleted the rb-fix-azure-reminder-test-race branch August 17, 2026 20:25
This was referenced Aug 28, 2026
This was referenced Sep 7, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test: Azure reminder suite times out across multiple cases

2 participants