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
12 changes: 9 additions & 3 deletions src/Orleans.Reminders/Options/ReminderOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public sealed class ReminderOptions
/// <summary>
/// Validator for <see cref="ReminderOptions"/>.
/// </summary>
internal sealed class ReminderOptionsValidator : IConfigurationValidator
internal sealed partial class ReminderOptionsValidator : IConfigurationValidator
{
private readonly ILogger<ReminderOptionsValidator> logger;
private readonly IOptions<ReminderOptions> options;
Expand Down Expand Up @@ -65,8 +65,14 @@ public void ValidateConfiguration()

if (options.Value.MinimumReminderPeriod.TotalMinutes < ReminderOptionsDefaults.MinimumReminderPeriodMinutes)
{
logger.LogWarning((int)RSErrorCode.RS_FastReminderInterval,
$"{nameof(ReminderOptions)}.{nameof(ReminderOptions.MinimumReminderPeriod)} is {options.Value.MinimumReminderPeriod:g} (default {ReminderOptionsDefaults.MinimumReminderPeriodMinutes:g}. High-Frequency reminders are unsuitable for production use.");
LogWarnFastReminderInterval(options.Value.MinimumReminderPeriod, ReminderOptionsDefaults.MinimumReminderPeriodMinutes);
}
}

[LoggerMessage(
Level = LogLevel.Warning,
EventId = (int)RSErrorCode.RS_FastReminderInterval,
Message = $"{nameof(ReminderOptions)}.{nameof(ReminderOptions.MinimumReminderPeriod)} is {{MinimumReminderPeriod}} (default {{MinimumReminderPeriodMinutes}}. High-Frequency reminders are unsuitable for production use."
)]
private partial void LogWarnFastReminderInterval(TimeSpan minimumReminderPeriod, uint minimumReminderPeriodMinutes);
}
147 changes: 91 additions & 56 deletions src/Orleans.Reminders/ReminderService/GrainBasedReminderTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Orleans.Runtime.ReminderService
{
[Reentrant]
[KeepAlive]
internal sealed class ReminderTableGrain : Grain, IReminderTableGrain, IGrainMigrationParticipant
internal sealed partial class ReminderTableGrain : Grain, IReminderTableGrain, IGrainMigrationParticipant
{
private readonly ILogger _logger;
private Dictionary<GrainId, Dictionary<string, ReminderEntry>> _reminderTable = new();
Expand All @@ -24,31 +24,19 @@ public ReminderTableGrain(ILogger<ReminderTableGrain> logger)

public override Task OnActivateAsync(CancellationToken cancellationToken)
{
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Activated");
}

LogDebugActivated();
return Task.CompletedTask;
}

public override Task OnDeactivateAsync(DeactivationReason reason, CancellationToken cancellationToken)
{
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Deactivated");
}

LogDebugDeactivated();
return Task.CompletedTask;
}

public Task TestOnlyClearTable()
{
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("TestOnlyClearTable");
}

LogDebugTestOnlyClearTable();
_reminderTable.Clear();
return Task.CompletedTask;
}
Expand All @@ -68,22 +56,10 @@ public Task<ReminderTableData> ReadRows(uint begin, uint end)
if (range.InRange(e.Key))
list.AddRange(e.Value.Values);

if (_logger.IsEnabled(LogLevel.Trace))
{
_logger.LogTrace(
"Selected {SelectCount} out of {TotalCount} reminders from memory for {Range}. Selected: {Reminders}",
list.Count,
_reminderTable.Values.Sum(r => r.Count),
range.ToString(),
Utils.EnumerableToString(list));
}
LogTraceSelectedReminders(list.Count, new(_reminderTable), range, new(list));

var result = new ReminderTableData(list);
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("Read {ReminderCount} reminders from memory: {Reminders}", result.Reminders.Count, Utils.EnumerableToString(result.Reminders));
}

LogDebugReadReminders(result.Reminders.Count, new(result.Reminders));
return Task.FromResult(result);
}

Expand All @@ -95,16 +71,13 @@ public Task<ReminderEntry> ReadRow(GrainId grainId, string reminderName)
reminders.TryGetValue(reminderName, out result);
}

if (_logger.IsEnabled(LogLevel.Trace))
if (result is null)
{
if (result is null)
{
_logger.LogTrace("Reminder not found for grain {Grain} reminder {ReminderName} ", grainId, reminderName);
}
else
{
_logger.LogTrace("Read for grain {Grain} reminder {ReminderName} row {Reminder}", grainId, reminderName, result.ToString());
}
LogTraceReminderNotFound(grainId, reminderName);
}
else
{
LogTraceReadRow(grainId, reminderName, result);
}

return Task.FromResult(result);
Expand All @@ -118,21 +91,14 @@ public Task<string> UpsertRow(ReminderEntry entry)

var old = entryRef; // tracing purposes only
entryRef = entry;
if (_logger.IsEnabled(LogLevel.Trace))
{
_logger.LogTrace("Upserted entry {Updated}, replaced {Replaced}", entry, old);
}
LogTraceUpsertedEntry(entry, old);

return Task.FromResult(entry.ETag);
}

public Task<bool> RemoveRow(GrainId grainId, string reminderName, string eTag)
{
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug("RemoveRow Grain = {Grain}, ReminderName = {ReminderName}, eTag = {ETag}", grainId, reminderName, eTag);
}

LogDebugRemoveRow(grainId, reminderName, eTag);
if (_reminderTable.TryGetValue(grainId, out var data)
&& data.TryGetValue(reminderName, out var e)
&& e.ETag == eTag)
Expand All @@ -149,14 +115,7 @@ public Task<bool> RemoveRow(GrainId grainId, string reminderName, string eTag)
return Task.FromResult(true);
}

_logger.LogWarning(
(int)RSErrorCode.RS_Table_Remove,
"RemoveRow failed for Grain = {Grain}, ReminderName = {ReminderName}, eTag = {ETag}. Table now is: {NewValues}",
grainId,
reminderName,
eTag,
Utils.EnumerableToString(_reminderTable.Values.SelectMany(x => x.Values)));

LogWarningRemoveRow(grainId, reminderName, eTag, new(_reminderTable));
return Task.FromResult(false);
}

Expand All @@ -172,5 +131,81 @@ void IGrainMigrationParticipant.OnRehydrate(IRehydrationContext rehydrationConte
_reminderTable = table;
}
}

[LoggerMessage(
Level = LogLevel.Debug,
Message = "Activated"
)]
private partial void LogDebugActivated();

[LoggerMessage(
Level = LogLevel.Debug,
Message = "Deactivated"
)]
private partial void LogDebugDeactivated();

[LoggerMessage(
Level = LogLevel.Debug,
Message = "TestOnlyClearTable"
)]
private partial void LogDebugTestOnlyClearTable();

private readonly struct TotalCountLogRecord(Dictionary<GrainId, Dictionary<string, ReminderEntry>> reminderTable)
{
public override string ToString() => reminderTable.Values.Sum(r => r.Count).ToString();
}

private readonly struct RemindersLogRecord(IEnumerable<ReminderEntry> reminders)
{
public override string ToString() => Utils.EnumerableToString(reminders);
}

[LoggerMessage(
Level = LogLevel.Trace,
Message = "Selected {SelectCount} out of {TotalCount} reminders from memory for {Range}. Selected: {Reminders}"
)]
private partial void LogTraceSelectedReminders(int selectCount, TotalCountLogRecord totalCount, IRingRange range, RemindersLogRecord reminders);

[LoggerMessage(
Level = LogLevel.Debug,
Message = "Read {ReminderCount} reminders from memory: {Reminders}"
)]
private partial void LogDebugReadReminders(int reminderCount, RemindersLogRecord reminders);

[LoggerMessage(
Level = LogLevel.Trace,
Message = "Reminder not found for grain {Grain} reminder {ReminderName}"
)]
private partial void LogTraceReminderNotFound(GrainId grain, string reminderName);

[LoggerMessage(
Level = LogLevel.Trace,
Message = "Read for grain {Grain} reminder {ReminderName} row {Reminder}"
)]
private partial void LogTraceReadRow(GrainId grain, string reminderName, ReminderEntry reminder);

[LoggerMessage(
Level = LogLevel.Trace,
Message = "Upserted entry {Updated}, replaced {Replaced}"
)]
private partial void LogTraceUpsertedEntry(ReminderEntry updated, ReminderEntry replaced);

[LoggerMessage(
Level = LogLevel.Debug,
Message = "RemoveRow Grain = {Grain}, ReminderName = {ReminderName}, eTag = {ETag}"
)]
private partial void LogDebugRemoveRow(GrainId grain, string reminderName, string eTag);

private readonly struct NewValuesLogRecord(Dictionary<GrainId, Dictionary<string, ReminderEntry>> reminderTable)
{
public override string ToString() => Utils.EnumerableToString(reminderTable.Values.SelectMany(x => x.Values));
}

[LoggerMessage(
Level = LogLevel.Warning,
EventId = (int)RSErrorCode.RS_Table_Remove,
Message = "RemoveRow failed for Grain = {Grain}, ReminderName = {ReminderName}, eTag = {ETag}. Table now is: {NewValues}"
)]
private partial void LogWarningRemoveRow(GrainId grain, string reminderName, string eTag, NewValuesLogRecord newValues);
}
}
Loading