diff --git a/src/Azure/Orleans.Reminders.AzureStorage/Storage/AzureBasedReminderTable.cs b/src/Azure/Orleans.Reminders.AzureStorage/Storage/AzureBasedReminderTable.cs index 85113b1f59..0301de2c01 100644 --- a/src/Azure/Orleans.Reminders.AzureStorage/Storage/AzureBasedReminderTable.cs +++ b/src/Azure/Orleans.Reminders.AzureStorage/Storage/AzureBasedReminderTable.cs @@ -17,7 +17,7 @@ public class AzureBasedReminderTable : IReminderTable private readonly ILoggerFactory loggerFactory; private readonly ClusterOptions clusterOptions; private readonly AzureTableReminderStorageOptions storageOptions; - private RemindersTableManager remTableManager; + private readonly RemindersTableManager remTableManager; public AzureBasedReminderTable( IGrainReferenceConverter grainReferenceConverter, @@ -30,15 +30,26 @@ public AzureBasedReminderTable( this.loggerFactory = loggerFactory; this.clusterOptions = clusterOptions.Value; this.storageOptions = storageOptions.Value; + this.remTableManager = new RemindersTableManager( + this.clusterOptions.ServiceId, + this.clusterOptions.ClusterId, + this.storageOptions, + this.loggerFactory); } public async Task Init() { - this.remTableManager = await RemindersTableManager.GetManager( - this.clusterOptions.ServiceId, - this.clusterOptions.ClusterId, - this.loggerFactory, - options: this.storageOptions); + try + { + logger.Info("Creating RemindersTableManager for service id {0} and cluster id {1}.", clusterOptions.ServiceId, clusterOptions.ClusterId); + await remTableManager.InitTableAsync(); + } + catch (Exception ex) + { + string errorMsg = $"Exception trying to create or connect to the Azure table: {ex.Message}"; + logger.Error((int)AzureReminderErrorCode.AzureTable_39, errorMsg, ex); + throw new OrleansException(errorMsg, ex); + } } private ReminderTableData ConvertFromTableEntryList(List<(ReminderTableEntry Entity, string ETag)> entries) diff --git a/src/Azure/Orleans.Reminders.AzureStorage/Storage/RemindersTableManager.cs b/src/Azure/Orleans.Reminders.AzureStorage/Storage/RemindersTableManager.cs index 3872092abe..7819aa6492 100644 --- a/src/Azure/Orleans.Reminders.AzureStorage/Storage/RemindersTableManager.cs +++ b/src/Azure/Orleans.Reminders.AzureStorage/Storage/RemindersTableManager.cs @@ -8,14 +8,11 @@ using Azure; using Azure.Data.Tables; using Microsoft.Extensions.Logging; -using Orleans.AzureUtils.Utilities; using Orleans.Reminders.AzureStorage; -using Orleans.Internal; -using Orleans.Configuration; namespace Orleans.Runtime.ReminderService { - internal class ReminderTableEntry : ITableEntity + internal sealed class ReminderTableEntry : ITableEntity { public string GrainReference { get; set; } // Part of RowKey public string ReminderName { get; set; } // Part of RowKey @@ -86,29 +83,12 @@ public override string ToString() } } - internal class RemindersTableManager : AzureTableDataManager + internal sealed class RemindersTableManager : AzureTableDataManager { - public string ServiceId { get; private set; } - public string ClusterId { get; private set; } + public string ServiceId { get; } + public string ClusterId { get; } - public static async Task GetManager(string serviceId, string clusterId, ILoggerFactory loggerFactory, AzureStorageOperationOptions options) - { - var singleton = new RemindersTableManager(serviceId, clusterId, options, loggerFactory); - try - { - singleton.Logger.Info("Creating RemindersTableManager for service id {0} and clusterId {1}.", serviceId, clusterId); - await singleton.InitTableAsync(); - } - catch (Exception ex) - { - string errorMsg = $"Exception trying to create or connect to the Azure table: {ex.Message}"; - singleton.Logger.Error((int)AzureReminderErrorCode.AzureTable_39, errorMsg, ex); - throw new OrleansException(errorMsg, ex); - } - return singleton; - } - - private RemindersTableManager( + public RemindersTableManager( string serviceId, string clusterId, AzureStorageOperationOptions options, diff --git a/src/Orleans.Runtime/ReminderService/LocalReminderService.cs b/src/Orleans.Runtime/ReminderService/LocalReminderService.cs index 32d611c2c0..f2f3e8598f 100644 --- a/src/Orleans.Runtime/ReminderService/LocalReminderService.cs +++ b/src/Orleans.Runtime/ReminderService/LocalReminderService.cs @@ -47,15 +47,20 @@ internal LocalReminderService( this.listRefreshTimer = asyncTimerFactory.Create(Constants.RefreshReminderList, "ReminderService.ReminderListRefresher"); } + public override async Task Init(IServiceProvider serviceProvider) + { + await base.Init(serviceProvider); + + // confirm that it can access the underlying store, as after this the ReminderService will load in the background, without the opportunity to prevent the Silo from starting + await reminderTable.Init().WithTimeout(initTimeout, $"ReminderTable Initialization failed due to timeout {initTimeout}"); + } + /// /// Attempt to retrieve reminders, that are my responsibility, from the global reminder table when starting this silo (reminder service instance) /// /// public override async Task Start() { - // confirm that it can access the underlying store, as after this the ReminderService will load in the background, without the opportunity to prevent the Silo from starting - await reminderTable.Init().WithTimeout(initTimeout, $"ReminderTable Initialization failed due to timeout {initTimeout}"); - await base.Start(); } diff --git a/src/Orleans.Runtime/Silo/Silo.cs b/src/Orleans.Runtime/Silo/Silo.cs index 3920dbd77f..d64cf523e5 100644 --- a/src/Orleans.Runtime/Silo/Silo.cs +++ b/src/Orleans.Runtime/Silo/Silo.cs @@ -60,7 +60,7 @@ public enum SiloType new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); private readonly SiloStatisticsManager siloStatistics; private readonly InsideRuntimeClient runtimeClient; - private IReminderService reminderService; + private LocalReminderService reminderService; private SystemTarget fallbackScheduler; private readonly ISiloStatusOracle siloStatusOracle; private Watchdog platformWatchdog; @@ -96,7 +96,6 @@ public enum SiloType private bool isFastKilledNeeded = false; // Set to true if something goes wrong in the shutdown/stop phase - private IGrainContext reminderServiceContext; private LifecycleSchedulingSystemTarget lifecycleSchedulingSystemTarget; /// @@ -397,6 +396,13 @@ private async Task OnRuntimeGrainServicesStart(CancellationToken ct) { var stopWatch = Stopwatch.StartNew(); + // Initialize the reminder service. + if (reminderService is not null) + { + await this.scheduler.QueueTask(() => reminderService.Init(Services), reminderService) + .WithTimeout(this.initTimeout, $"GrainService Initializing failed due to timeout {initTimeout}"); + } + // Load and init grain services before silo becomes active. await StartAsyncTaskWithPerfAnalysis("Init grain services", () => CreateGrainServices(), stopWatch); @@ -462,8 +468,7 @@ private async Task OnActiveStart(CancellationToken ct) async Task StartReminderService() { // so, we have the view of the membership in the consistentRingProvider. We can start the reminder service - this.reminderServiceContext = (this.reminderService as IGrainContext) ?? this.fallbackScheduler; - await this.scheduler.QueueTask(this.reminderService.Start, this.reminderServiceContext) + await this.scheduler.QueueTask(this.reminderService.Start, this.reminderService) .WithTimeout(this.initTimeout, $"Starting ReminderService failed due to timeout {initTimeout}"); this.logger.Debug("Reminder service started successfully."); } @@ -702,7 +707,7 @@ private async Task OnActiveStop(CancellationToken ct) if (reminderService != null) { await this.scheduler - .QueueTask(reminderService.Stop, this.reminderServiceContext) + .QueueTask(reminderService.Stop, this.reminderService) .WithCancellation(ct, "Stopping ReminderService failed because the task was cancelled"); }