Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,10 @@ private async Task ReadAndReconcileRange(ISingleRange range, int rangeSerialNumb
private void ReconcileTableEntry(ReminderEntry entry, long tableSequence, DateTime now, List<Task> stopTasks)
{
var key = new ReminderIdentity(entry.GrainId, entry.ReminderName);
var shouldLoad = IsReminderWithinLoadingWindow(entry, now, reminderOptions.ReminderLoadingWindow);
var nextTick = CalculateNextTickTime(entry, now);
// Keep distant schedules in storage; exact-due entries are intentionally skipped to simplify fake-time tests.
var isWithinLoadingWindow = nextTick <= now.AddClamped(reminderOptions.ReminderLoadingWindow);
var shouldLoad = nextTick > now && isWithinLoadingWindow;
if (!localReminders.TryGetValue(key, out var localReminder))
{
// Distant reminders remain exclusively in storage until a later refresh brings their next tick
Expand Down Expand Up @@ -592,7 +595,7 @@ private void ReconcileTableEntry(ReminderEntry entry, long tableSequence, DateTi
return;
}

if (!shouldLoad)
if (!isWithinLoadingWindow || (state is LocalReminderState.Tombstone && !shouldLoad))
{
LogTraceRemovingReminder(localReminder);
stopTasks.Add(
Expand Down
8 changes: 4 additions & 4 deletions src/Orleans.Testing.Reminders/ReminderTestClock.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#nullable enable

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Time.Testing;
using Orleans.Hosting;
using Orleans.Reminders;
using Orleans.TestingHost;

namespace Orleans.Testing.Reminders;
Expand All @@ -13,8 +13,8 @@ namespace Orleans.Testing.Reminders;
/// </summary>
/// <remarks>
/// Attach an instance to an <see cref="InProcessTestClusterBuilder"/> before building the cluster.
/// The attached clock replaces the silo <see cref="TimeProvider"/> and tunes
/// <see cref="ReminderOptions"/> for deterministic reminder scheduling.
/// The attached clock replaces the reminder subsystem's keyed <see cref="TimeProvider"/> and tunes
/// <see cref="ReminderOptions"/> for deterministic reminder scheduling without affecting unrelated silo timers.
/// </remarks>
public sealed class ReminderTestClock : IDisposable
{
Expand Down Expand Up @@ -74,7 +74,7 @@ public static ReminderTestClock Attach(

builder.ConfigureSilo((_, siloBuilder) =>
{
siloBuilder.Services.Replace(ServiceDescriptor.Singleton<TimeProvider>(clock.TimeProvider));
siloBuilder.Services.AddKeyedSingleton<TimeProvider>(ReminderTimeProviderNames.Reminders, clock.TimeProvider);
siloBuilder.Services.PostConfigure<ReminderOptions>(options =>
{
options.MinimumReminderPeriod = clock.MinimumReminderPeriod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Reactive.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Internal;
using Orleans.Reminders;
using Orleans.Testing.Reminders;
using Orleans.TestingHost;
using TestExtensions;
Expand Down Expand Up @@ -36,6 +37,8 @@ public class Fixture : BaseInProcessTestClusterFixture

protected override void ConfigureTestCluster(InProcessTestClusterBuilder builder)
{
// The controlled-read tests validate ordering within one reminder owner.
builder.Options.InitialSilosCount = 1;
_reminderClock = builder.AddReminderTestClock();
builder.ConfigureSilo((_, siloBuilder) =>
{
Expand Down Expand Up @@ -78,6 +81,19 @@ public ReminderTests_TableGrain(Fixture fixture) : base(fixture.ReminderClock, f

// Basic tests

[Fact]
public void ReminderTestClock_IsScopedToReminderService()
{
foreach (var silo in HostedCluster.Silos)
{
var unkeyedProvider = silo.ServiceProvider.GetRequiredService<TimeProvider>();
var reminderProvider = silo.ServiceProvider.GetRequiredKeyedService<TimeProvider>(ReminderTimeProviderNames.Reminders);

Assert.Same(TimeProvider.System, unkeyedProvider);
Assert.NotSame(unkeyedProvider, reminderProvider);
}
}

/// <summary>
/// Tests basic reminder operations including stopping reminders by reference.
/// </summary>
Expand Down
Loading