Move cache instructions pruning to background job (#19598)

* Remove pruning logic from `CacheInstructionService.ProcessInstructions()`

* Add and register `CacheInstructionsPruningJob` background job

* Add unit tests

* Remove breaking change in ICacheInstructionService

* Adjust some obsoletion messages to mention v17

* Added missing scope

* Update tests

* Fix obsoletion messages version

* Update ProcessInstructions methods summary
This commit is contained in:
Laura Neto
2025-07-01 11:17:59 +02:00
committed by GitHub
parent 3b4639de08
commit dcd8b42522
9 changed files with 269 additions and 108 deletions

View File

@@ -20,8 +20,10 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
private const string LocalIdentity = "localIdentity";
private const string AlternateIdentity = "alternateIdentity";
private CancellationToken CancellationToken => new();
private CancellationToken CancellationToken => CancellationToken.None;
private CacheRefresherCollection CacheRefreshers => GetRequiredService<CacheRefresherCollection>();
private IServerRoleAccessor ServerRoleAccessor => GetRequiredService<IServerRoleAccessor>();
[Test]
@@ -150,33 +152,16 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
// Create three instruction records, each with two instructions. First two records are for a different identity.
CreateAndDeliveryMultipleInstructions(sut);
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken,
LocalIdentity, DateTime.UtcNow.AddSeconds(-1), -1);
var result = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, -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);
});
}
[Test]
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);
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken,
LocalIdentity, DateTime.UtcNow.AddHours(-1), -1);
Assert.IsTrue(result.InstructionsWerePruned);
}
[Test]
public void Processes_No_Instructions_When_CancellationToken_is_Cancelled()
{
@@ -187,14 +172,12 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Cancel();
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole,
cancellationTokenSource.Token, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), -1);
var result = sut.ProcessInstructions(CacheRefreshers, cancellationTokenSource.Token, LocalIdentity, -1);
Assert.Multiple(() =>
{
Assert.AreEqual(0, result.LastId);
Assert.AreEqual(0, result.NumberOfInstructionsProcessed);
Assert.IsFalse(result.InstructionsWerePruned);
});
}
@@ -209,14 +192,12 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
var lastId = -1;
// Run once
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken,
LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId);
var result = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, 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.
@@ -224,13 +205,7 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
// The instructions has now been processed and shouldn't be processed on the next call...
// Run again.
var secondResult = sut.ProcessInstructions(
CacheRefreshers,
ServerRoleAccessor.CurrentServerRole,
CancellationToken,
LocalIdentity,
DateTime.UtcNow.AddSeconds(-1),
lastId);
var secondResult = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, lastId);
Assert.Multiple(() =>
{
Assert.AreEqual(
@@ -238,7 +213,6 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
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);
});
}
@@ -249,8 +223,7 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
CreateAndDeliveryMultipleInstructions(sut);
var lastId = -1;
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken,
LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId);
var result = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, lastId);
Assert.AreEqual(3, result.LastId); // Make sure LastId is 3, the rest is tested in other test.
lastId = result.LastId;
@@ -259,14 +232,12 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
var instructions = CreateInstructions();
sut.DeliverInstructions(instructions, AlternateIdentity);
var secondResult = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole,
CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId);
var secondResult = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, lastId);
Assert.Multiple(() =>
{
Assert.AreEqual(4, secondResult.LastId);
Assert.AreEqual(1, secondResult.NumberOfInstructionsProcessed);
Assert.IsFalse(secondResult.InstructionsWerePruned);
});
}
@@ -277,8 +248,7 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
CreateAndDeliveryMultipleInstructions(sut);
var lastId = -1;
var result = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole, CancellationToken,
LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId);
var result = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, lastId);
Assert.AreEqual(3, result.LastId); // Make sure LastId is 3, the rest is tested in other test.
lastId = result.LastId;
@@ -287,14 +257,12 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
var instructions = CreateInstructions();
sut.DeliverInstructions(instructions, LocalIdentity);
var secondResult = sut.ProcessInstructions(CacheRefreshers, ServerRoleAccessor.CurrentServerRole,
CancellationToken, LocalIdentity, DateTime.UtcNow.AddSeconds(-1), lastId);
var secondResult = sut.ProcessInstructions(CacheRefreshers, CancellationToken, LocalIdentity, lastId);
Assert.Multiple(() =>
{
Assert.AreEqual(4, secondResult.LastId);
Assert.AreEqual(0, secondResult.NumberOfInstructionsProcessed);
Assert.IsFalse(secondResult.InstructionsWerePruned);
});
}
@@ -306,10 +274,4 @@ internal sealed class CacheInstructionServiceTests : UmbracoIntegrationTest
sut.DeliverInstructions(instructions, i == 2 ? LocalIdentity : AlternateIdentity);
}
}
private void EnsureServerRegistered()
{
var serverRegistrationService = GetRequiredService<IServerRegistrationService>();
serverRegistrationService.TouchServer("http://localhost", TimeSpan.FromMinutes(10));
}
}