Skip to content

Reminders v2#9903

Open
KSemenenko wants to merge 22 commits intodotnet:mainfrom
KSemenenko:remainders-v2
Open

Reminders v2#9903
KSemenenko wants to merge 22 commits intodotnet:mainfrom
KSemenenko:remainders-v2

Conversation

@KSemenenko
Copy link
Copy Markdown

@KSemenenko KSemenenko commented Feb 7, 2026

Adaptive Reminder Service - Proposal #9586

Microsoft Reviewers: Open in CodeFlow

Reminders v2: split legacy reminders from the new AdvancedReminders stack

Summary

This PR restores the legacy Orleans.Reminders* stack to its baseline-compatible shape and moves the new reminders work into a separate package family: Microsoft.Orleans.AdvancedReminders*.

The new stack lives alongside legacy reminders instead of replacing them in-place.

What changed

  • Restored the existing Orleans.Reminders* packages to the legacy reminder model for compatibility.
  • Added a new Microsoft.Orleans.AdvancedReminders core package in Orleans.AdvancedReminders.
  • Added provider packages for the new stack:
    • Microsoft.Orleans.AdvancedReminders.AzureStorage
    • Microsoft.Orleans.AdvancedReminders.Cosmos
    • Microsoft.Orleans.AdvancedReminders.DynamoDB
    • Microsoft.Orleans.AdvancedReminders.Redis
    • Microsoft.Orleans.AdvancedReminders.AdoNet
  • Added a schedule-based reminders API for the new stack, including:
    • interval schedules
    • absolute UTC due-time schedules
    • cron schedules
  • Added cron helpers and parsing/building support in Orleans.AdvancedReminders.Cron, including:
    • TimeOnly / TimeSpan builder overloads
    • second-precision helper overloads where needed
    • strongly typed TimeZoneInfo overloads alongside InTimeZone(...)
    • timezone-aware occurrence evaluation across DST and non-DST zones
  • Added grain-level ReminderSchedule overloads so grain code can use the same schedule abstraction as the registry/service APIs.
  • Simplified missed reminder handling so Skip and Notify share the same non-fire path, while preserving FireImmediately behavior.
  • Hardened CronParser list parsing to avoid recursive stack growth on very large comma-separated expressions.
  • Added advanced reminder metadata and management APIs, including paging/filtering/iterator support.
  • Added attribute-based reminder registration for the new stack.
  • Implemented the new reminder delivery path on top of Orleans.DurableJobs.
  • Renamed the earlier DurableReminders work to AdvancedReminders across packages, namespaces, tests, docs, and checked-in API surface files.
  • Updated README samples and regenerated checked-in src/api/* files so the public API matches the compiled assemblies.

Public API shape

The new stack uses Orleans.AdvancedReminders namespaces and AddAdvancedReminders() / Use*AdvancedReminderService(...) entry points.

Legacy reminders remain available via the existing Orleans.Reminders namespaces and AddReminders() / Use*ReminderService(...) entry points.

Testing

Added and updated focused coverage for the new stack, including:

  • registration and schedule validation
  • cron parsing, builder ergonomics, and parser hardening
  • timezone behavior across DST and non-DST zones
  • reminder management and iterator flows
  • missed reminder behavior
  • provider serialization / table behavior
  • provider builder regression coverage

Validated with:

  • dotnet build src/Orleans.AdvancedReminders/Orleans.AdvancedReminders.csproj
  • dotnet test test/Orleans.Core.Tests/Orleans.Core.Tests.csproj --filter "FullyQualifiedName~UnitTests.AdvancedReminders"
    • passed: 188/188 on net8.0
    • passed: 188/188 on net10.0

Copilot AI review requested due to automatic review settings February 7, 2026 12:14
@KSemenenko
Copy link
Copy Markdown
Author

@benjaminpetit

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 advances the “Adaptive Reminder Service” proposal by extending Orleans reminders with cron-based scheduling and adaptive metadata (next-due, last-fire, priority/action), adding management/paging APIs and iterators, and updating multiple storage providers plus tests to round-trip the new fields.

Changes:

  • Add cron scheduling support and adaptive reminder metadata (CronExpression, NextDueUtc, LastFireUtc, Priority, Action) across reminder contracts and storage providers.
  • Introduce reminder management paging/filtering APIs plus iterator/extension helpers and new validation/registration conveniences (including [RegisterReminder] activation registration).
  • Update timer infrastructure and expand test coverage across NonSilo + provider-specific reminder table tests, plus add SQL migrations.

Reviewed changes

Copilot reviewed 86 out of 86 changed files in this pull request and generated 22 comments.

Show a summary per file
File Description
test/TesterInternal/RemindersTest/ReminderTableTestsBase.cs Adds round-trip tests for cron + adaptive fields in reminder table providers.
test/NonSilo.Tests/Reminders/SiloBuilderReminderExtensionsTests.cs Verifies DI registrations for legacy vs adaptive reminder services and options wiring.
test/NonSilo.Tests/Reminders/ReminderStressTests.cs Adds high-load paging/iterator stress coverage for reminder management APIs.
test/NonSilo.Tests/Reminders/ReminderRegistryValidationTests.cs Adds validation tests for new registry overloads (cron/absolute/priority/action).
test/NonSilo.Tests/Reminders/ReminderRegistrationExtensionsTests.cs Tests typed cron builder/expression extension overloads for registry/service/grain.
test/NonSilo.Tests/Reminders/ReminderOptionsValidatorTests.cs Adds validation coverage for new adaptive reminder options.
test/NonSilo.Tests/Reminders/ReminderManagementGrainExtensionsTests.cs Tests paging enumeration extension helpers and iterator factory.
test/NonSilo.Tests/Reminders/ReminderIteratorTests.cs Tests ReminderIterator paging behavior and large-streaming scenario.
test/NonSilo.Tests/Reminders/RegisterReminderAttributeTests.cs Tests [RegisterReminder] attribute ctor behavior and validation.
test/NonSilo.Tests/Reminders/RegisterReminderActivationConfiguratorProviderTests.cs Tests activation-time reminder registration behavior using lifecycle hooks.
test/NonSilo.Tests/NonSilo.Tests.csproj Adds project reference to Orleans.Reminders for new reminder APIs/tests.
test/Grains/TestGrainInterfaces/IReminderTestGrain2.cs Extends test grain interface to exercise new reminder options/cron/raw upserts.
test/Extensions/TesterAzureUtils/AzureRemindersTableTests.cs Adds Azure reminder table round-trip tests for cron + adaptive fields.
test/Extensions/TesterAdoNet/StorageTests/DbExtensionsInt32ConversionTests.cs Adds coverage for widened GetInt32 conversions and overflow behavior.
test/Extensions/TesterAdoNet/Reminders/SqlServerRemindersTableTests.cs Adds SQL Server reminder table round-trip tests for new fields.
test/Extensions/TesterAdoNet/Reminders/PostgreSqlRemindersTableTests.cs Adds PostgreSQL reminder table round-trip tests for new fields.
test/Extensions/TesterAdoNet/Reminders/MySqlRemindersTableTests.cs Adds MySQL reminder table round-trip tests for new fields.
test/Extensions/Tester.Redis/Reminders/RedisReminderTableTests.cs Adds Redis reminder table round-trip tests for new fields.
test/Extensions/Tester.Redis/Reminders/RedisReminderTableSerializationTests.cs Adds Redis serialization/parsing tests for enums + temporal formatting.
test/Extensions/AWSUtils.Tests/Reminder/DynamoDBRemindersTableTests.cs Adds DynamoDB reminder table round-trip tests for new fields.
test/Extensions/AWSUtils.Tests/Reminder/DynamoDBReminderTableEnumParsingTests.cs Adds DynamoDB enum parsing tests for missing/invalid/valid values.
src/Redis/Orleans.Reminders.Redis/Storage/RedisReminderTable.cs Extends Redis reminder payload format to include cron/temporal/enums with robust parsing.
src/Orleans.Runtime/Timers/AsyncTimerFactory.cs Adds TimeProvider support to async timers via factory injection.
src/Orleans.Runtime/Timers/AsyncTimer.cs Switches timer time sources/delays to TimeProvider for testability/determinism.
src/Orleans.Reminders/Timers/ReminderQueryFilter.cs Adds server-side filter DTO + status mask enum for management paging queries.
src/Orleans.Reminders/Timers/ReminderManagementPage.cs Introduces page DTO for reminder management results.
src/Orleans.Reminders/Timers/ReminderManagementGrainExtensions.cs Adds IAsyncEnumerable helpers for paging through management APIs.
src/Orleans.Reminders/Timers/ReminderIterator.cs Implements iterator facade over reminder management paging APIs.
src/Orleans.Reminders/Timers/IReminderRegistry.cs Adds new registry overloads (absolute due, cron, priority/action).
src/Orleans.Reminders/Timers/IReminderManagementGrain.cs Adds management grain interface with paging/filtering and administrative operations.
src/Orleans.Reminders/Timers/IReminderIterator.cs Adds iterator interface for streaming pages without full materialization.
src/Orleans.Reminders/Timers/IRemindable.cs Adds schedule kind + priority/action + cron surface area to reminder contracts.
src/Orleans.Reminders/SystemTargetInterfaces/IReminderTable.cs Extends ReminderEntry + ReminderData to carry cron/temporal/enums.
src/Orleans.Reminders/SystemTargetInterfaces/IReminderService.cs Adds new reminder service overloads (absolute due, cron, priority/action).
src/Orleans.Reminders/ReminderService/ReminderRegistry.cs Adds validation + new overloads for cron/absolute due and priority/action.
src/Orleans.Reminders/ReminderService/RegisterReminderActivationConfiguratorProvider.cs Adds activation-time [RegisterReminder] support via lifecycle observer.
src/Orleans.Reminders/ReminderService/LocalReminderService.cs Adds TimeProvider usage, cron scheduling support, adaptive fields, and legacy suppression behavior.
src/Orleans.Reminders/ReminderService/AdaptiveReminderServiceRegistrationMarker.cs Adds DI marker for suppressing legacy reminder service when adaptive is enabled.
src/Orleans.Reminders/ReminderCronRegistrationExtensions.cs Adds typed-cron overloads for registry/service cron registration.
src/Orleans.Reminders/RegisterReminderAttribute.cs Introduces [RegisterReminder] attribute with validation and priority/action support.
src/Orleans.Reminders/Orleans.Reminders.csproj Enables unsafe blocks to support cron parsing implementation.
src/Orleans.Reminders/Options/ReminderOptions.cs Adds adaptive options (look-ahead, poll interval, bucket size, priority toggle, legacy toggle) + validation.
src/Orleans.Reminders/Hosting/SiloBuilderReminderExtensions.cs Adds overloads to configure ReminderOptions and wires activation configurator provider.
src/Orleans.Reminders/Hosting/SiloBuilderAdaptiveReminderExtensions.cs Adds AddAdaptiveReminderService() DI wiring + idempotency behavior.
src/Orleans.Reminders/GrainReminderExtensions.cs Adds reminder registration overloads for absolute due and priority/action.
src/Orleans.Reminders/GrainReminderCronExtensions.cs Adds grain-level cron reminder registration extension methods.
src/Orleans.Reminders/Cron/ReminderCronExpression.cs Adds typed cron expression wrapper with parsing/format detection and UTC guards.
src/Orleans.Reminders/Cron/ReminderCronBuilder.cs Adds helper builder for common cron schedules and validation.
src/Orleans.Reminders/Cron/Internal/TimeZoneHelper.cs Adds internal DST ambiguity helpers for cron scheduling.
src/Orleans.Reminders/Cron/Internal/ReminderCronParser.cs Adds internal cron parsing helper (5/6 field detection) for runtime use.
src/Orleans.Reminders/Cron/Internal/LanguageFeatures.cs Adds polyfills for compiler/runtime attributes for older target frameworks.
src/Orleans.Reminders/Cron/Internal/DateTimeHelper.cs Adds internal DateTimeOffset rounding helpers for cron logic.
src/Orleans.Reminders/Cron/Internal/CronFormatException.cs Adds custom exception for cron format failures.
src/Orleans.Reminders/Cron/Internal/CronFormat.cs Adds internal enum controlling cron parse format options.
src/Orleans.Reminders/Cron/Internal/CronField.cs Adds cron field metadata (ranges/names) used by parser.
src/Orleans.Reminders/Cron/Internal/CronExpressionFlag.cs Adds internal flags to represent cron expression modifiers.
src/Orleans.Reminders/Cron/Internal/CalendarHelper.cs Adds internal calendar helpers for cron evaluation.
src/Orleans.Reminders/Constants/ReminderOptionsDefaults.cs Adds defaults for look-ahead, poll interval, and bucket size.
src/Azure/Shared/Storage/AzureTableDataManager.cs Adds optional update mode to table upsert, enabling replace semantics when needed.
src/Azure/Orleans.Reminders.Cosmos/Models/ReminderEntity.cs Adds cron/temporal/enums fields to Cosmos reminder entity model.
src/Azure/Orleans.Reminders.Cosmos/CosmosReminderTable.cs Reads/writes cron/temporal/enums fields for Cosmos reminder storage.
src/Azure/Orleans.Reminders.AzureStorage/Storage/RemindersTableManager.cs Adds columns for cron/temporal/enums and switches upsert to Replace mode.
src/Azure/Orleans.Reminders.AzureStorage/Storage/AzureBasedReminderTable.cs Adds parsing/serialization for new fields, with tighter exception handling.
src/AdoNet/Shared/Storage/RelationalOrleansQueries.cs Reads new reminder columns and extends upsert to persist new fields/enums.
src/AdoNet/Shared/Storage/DbStoredQueries.cs Adds new column parameter bindings and simplifies version read using GetInt32.
src/AdoNet/Shared/Storage/DbExtensions.cs Expands GetInt32 conversion support with invariant conversion and nullable variant.
src/AdoNet/Orleans.Reminders.AdoNet/SQLServer-Reminders.sql Adds new columns and index + updates stored queries for SQL Server provider.
src/AdoNet/Orleans.Reminders.AdoNet/ReminderService/AdoNetReminderTable.cs Passes new reminder fields through to relational upsert.
src/AdoNet/Orleans.Reminders.AdoNet/PostgreSQL-Reminders.sql Adds new columns/index and updates upsert function/queries for PostgreSQL provider.
src/AdoNet/Orleans.Reminders.AdoNet/Oracle-Reminders.sql Adds new columns/index and updates function/queries for Oracle provider.
src/AdoNet/Orleans.Reminders.AdoNet/MySQL-Reminders.sql Adds new columns/index and updates stored queries for MySQL provider.
src/AdoNet/Orleans.Reminders.AdoNet/Migrations/SQLServer-Reminders-10.0.0.sql Adds migration script for pre-10.0.0 SQL Server reminder tables.
src/AdoNet/Orleans.Reminders.AdoNet/Migrations/PostgreSQL-Reminders-10.0.0.sql Adds migration script for pre-10.0.0 PostgreSQL reminder tables.
src/AdoNet/Orleans.Reminders.AdoNet/Migrations/Oracle-Reminders-10.0.0.sql Adds migration script for pre-10.0.0 Oracle reminder tables.
src/AdoNet/Orleans.Reminders.AdoNet/Migrations/MySQL-Reminders-10.0.0.sql Adds migration script for pre-10.0.0 MySQL reminder tables.
src/AWS/Orleans.Reminders.DynamoDB/Reminders/DynamoDBReminderTable.cs Adds cron/temporal/enums read/write behavior with robust parsing defaults.
Comments suppressed due to low confidence (1)

test/Grains/TestInternalGrains/ReminderTestGrain2.cs:287

@rkargMsft
Copy link
Copy Markdown
Contributor

Do we want to be changing the existing Reminder interface as opposed to creating a new one that can exist side by side (with perhaps a separate migration process to move existing reminder instances to the new interface)?

Also, I had assumed that new reminders would be built on top of the new DurableJob construct. Was that an expectation or have I misremembered?

@ReubenBond ReubenBond changed the title Remainders v2 Reminders v2 Feb 9, 2026
@KSemenenko
Copy link
Copy Markdown
Author

@ReubenBond I don't know much about DurableJob but I would love to help here, becase I really want reminders with cron so bad =)

@KSemenenko
Copy link
Copy Markdown
Author

@ReubenBond @rkargMsft shoud I move this into separate project? or just add separete exteions like UseAdaptiveReminders and then add extra extions for registeter for remainders?

# Conflicts:
#	test/Extensions/Orleans.AWS.Tests/Reminder/DynamoDBReminderTableEnumParsingTests.cs
#	test/Extensions/Orleans.AdoNet.Tests/StorageTests/DbExtensionsInt32ConversionTests.cs
#	test/Extensions/Orleans.Redis.Tests/Reminders/RedisReminderTableSerializationTests.cs
#	test/Orleans.Core.Tests/Orleans.Core.Tests.csproj
#	test/Orleans.Runtime.Internal.Tests/TimerTests/AdaptiveReminderTests_TableGrain.cs
@KSemenenko
Copy link
Copy Markdown
Author

@pentp comments are resolved

Also I gives me an idea to add one more propery TimeZone - in case I want to run remainder each 9 am each morneing in ET time.

I found this is usfull. what do you think?

@KSemenenko
Copy link
Copy Markdown
Author

@copilot review

@KSemenenko KSemenenko requested a review from Copilot March 14, 2026 14:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 138 out of 138 changed files in this pull request and generated 15 comments.


You can also share your feedback on Copilot code review. Take the survey.

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.

4 participants