public void Processes_Instructions_Only_Once() { // This test shows what's happening in issue #10112 // The DatabaseServerMessenger will run its sync operation every five seconds which calls CacheInstructionService.ProcessInstructions, // which is why the CacheRefresherNotification keeps dispatching, because the cache instructions gets constantly processed. var sut = (CacheInstructionService)GetRequiredService <ICacheInstructionService>(); CreateAndDeliveryMultipleInstructions(sut); var lastId = -1; // Run once ProcessInstructionsResult result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId); Assert.Multiple(() => { Assert.AreEqual(3, result.LastId); // 3 records found. Assert.AreEqual(2, result.NumberOfInstructionsProcessed); // 2 records processed (as one is for the same identity). Assert.IsFalse(result.InstructionsWerePruned); }); // DatabaseServerMessenger stores the LastID after ProcessInstructions has been run. lastId = result.LastId; // The instructions has now been processed and shouldn't be processed on the next call... // Run again. ProcessInstructionsResult secondResult = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId); Assert.Multiple(() => { Assert.AreEqual(0, secondResult.LastId); // No instructions was processed so LastId is 0, this is consistent with behavior from V8 Assert.AreEqual(0, secondResult.NumberOfInstructionsProcessed); // Nothing was processed. Assert.IsFalse(secondResult.InstructionsWerePruned); }); }
public void Correct_ID_For_Instruction_With_Same_Identity() { var sut = (CacheInstructionService)GetRequiredService <ICacheInstructionService>(); CreateAndDeliveryMultipleInstructions(sut); var lastId = -1; ProcessInstructionsResult result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId); Assert.AreEqual(3, result.LastId); // Make sure LastId is 3, the rest is tested in other test. lastId = result.LastId; // Add new instruction List <RefreshInstruction> instructions = CreateInstructions(); sut.DeliverInstructions(instructions, LocalIdentity); ProcessInstructionsResult secondResult = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId); Assert.Multiple(() => { Assert.AreEqual(4, secondResult.LastId); Assert.AreEqual(0, secondResult.NumberOfInstructionsProcessed); Assert.IsFalse(secondResult.InstructionsWerePruned); }); }
public void Can_Process_And_Purge_Instructions() { // Purging of instructions only occurs on single or master servers, so we need to ensure this is set before running the test. EnsureServerRegistered(); var sut = (CacheInstructionService)GetRequiredService <ICacheInstructionService>(); CreateAndDeliveryMultipleInstructions(sut); ProcessInstructionsResult result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddHours(-1), -1); Assert.IsTrue(result.InstructionsWerePruned); }
public void Can_Process_Instructions() { var sut = (CacheInstructionService)GetRequiredService <ICacheInstructionService>(); // Create three instruction records, each with two instructions. First two records are for a different identity. CreateAndDeliveryMultipleInstructions(sut); ProcessInstructionsResult result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), -1); Assert.Multiple(() => { Assert.AreEqual(3, result.LastId); // 3 records found. Assert.AreEqual(2, result.NumberOfInstructionsProcessed); // 2 records processed (as one is for the same identity). Assert.IsFalse(result.InstructionsWerePruned); }); }
public void Processes_No_Instructions_When_CancellationToken_is_Cancelled() { var sut = (CacheInstructionService)GetRequiredService <ICacheInstructionService>(); CreateAndDeliveryMultipleInstructions(sut); var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.Cancel(); ProcessInstructionsResult result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, cancellationTokenSource.Token, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), -1); Assert.Multiple(() => { Assert.AreEqual(0, result.LastId); Assert.AreEqual(0, result.NumberOfInstructionsProcessed); Assert.IsFalse(result.InstructionsWerePruned); }); }
/// <inheritdoc/> public ProcessInstructionsResult ProcessInstructions( CacheRefresherCollection cacheRefreshers, ServerRole serverRole, CancellationToken cancellationToken, string localIdentity, DateTime lastPruned, int lastId) { using (_profilingLogger.DebugDuration <CacheInstructionService>("Syncing from database...")) using (ICoreScope scope = ScopeProvider.CreateCoreScope()) { var numberOfInstructionsProcessed = ProcessDatabaseInstructions(cacheRefreshers, cancellationToken, localIdentity, ref lastId); // Check for pruning throttling. if (cancellationToken.IsCancellationRequested || (DateTime.UtcNow - lastPruned) <= _globalSettings.DatabaseServerMessenger.TimeBetweenPruneOperations) { scope.Complete(); return(ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId)); } var instructionsWerePruned = false; switch (serverRole) { case ServerRole.Single: case ServerRole.SchedulingPublisher: PruneOldInstructions(); instructionsWerePruned = true; break; } scope.Complete(); return(instructionsWerePruned ? ProcessInstructionsResult.AsCompletedAndPruned(numberOfInstructionsProcessed, lastId) : ProcessInstructionsResult.AsCompleted(numberOfInstructionsProcessed, lastId)); } }
/// <summary> /// Synchronize the server (throttled). /// </summary> public override void Sync() { if (!EnsureInitialized()) { return; } lock (_locko) { if (_syncing) { return; } // Don't continue if we are released if (_cancellationToken.IsCancellationRequested) { return; } if ((DateTime.UtcNow - _lastSync) <= GlobalSettings.DatabaseServerMessenger.TimeBetweenSyncOperations) { return; } // Set our flag and the lock to be in it's original state (i.e. it can be awaited) _syncing = true; _syncIdle.Reset(); _lastSync = DateTime.UtcNow; } try { ProcessInstructionsResult result = CacheInstructionService.ProcessInstructions( _cacheRefreshers, _serverRoleAccessor.CurrentServerRole, _cancellationToken, LocalIdentity, _lastPruned, _lastSyncedFileManager.LastSyncedId); if (result.InstructionsWerePruned) { _lastPruned = _lastSync; } if (result.LastId > 0) { _lastSyncedFileManager.SaveLastSyncedId(result.LastId); } } finally { lock (_locko) { // We must reset our flag and signal any waiting locks _syncing = false; } _syncIdle.Set(); } }