perf(templateengine): alarm-override, folder-delete and template-delete checks read lean template projections (review 2026-10-21 04/P6, 08/P1)
InstanceService.SetAlarmOverrideAsync and TemplateDeletionService move to the no-tracking, body-free GetAllTemplatesForAnalysisAsync; TemplateFolderService counts folder contents from GetTemplateStubsAsync.
This commit is contained in:
+11
-8
@@ -26,7 +26,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new Template("Orphan") { Id = 1 });
|
||||
_repoMock.Setup(r => r.GetInstancesByTemplateIdAsync(1, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Instance>());
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template> { new("Orphan") { Id = 1 } });
|
||||
_repoMock.Setup(r => r.GetCompositionsByTemplateIdAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateComposition>());
|
||||
@@ -34,6 +34,9 @@ public class TemplateDeletionServiceTests
|
||||
var result = await _sut.CanDeleteTemplateAsync(1);
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
// Review 2026-10-21 04/P6 + 08/P1: the reference checks read ids, names and
|
||||
// composition edges only — the no-tracking, body-free analysis projection.
|
||||
_repoMock.Verify(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()), Times.Never);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a template with instances cannot be deleted.</summary>
|
||||
@@ -49,7 +52,7 @@ public class TemplateDeletionServiceTests
|
||||
new("Inst1") { Id = 1 },
|
||||
new("Inst2") { Id = 2 }
|
||||
});
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template> { new("Used") { Id = 1 } });
|
||||
_repoMock.Setup(r => r.GetCompositionsByTemplateIdAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateComposition>());
|
||||
@@ -70,7 +73,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new Template("Base") { Id = 1 });
|
||||
_repoMock.Setup(r => r.GetInstancesByTemplateIdAsync(1, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Instance>());
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template>
|
||||
{
|
||||
new("Base") { Id = 1 },
|
||||
@@ -98,7 +101,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new Template("Module") { Id = 1 });
|
||||
_repoMock.Setup(r => r.GetInstancesByTemplateIdAsync(1, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Instance>());
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template>
|
||||
{
|
||||
new("Module") { Id = 1 },
|
||||
@@ -118,7 +121,7 @@ public class TemplateDeletionServiceTests
|
||||
public async Task CanDeleteTemplate_DoesNotIssuePerTemplateCompositionQuery()
|
||||
{
|
||||
// The composition check must read the Compositions navigation
|
||||
// already loaded by GetAllTemplatesAsync rather than issuing one
|
||||
// already loaded by GetAllTemplatesForAnalysisAsync rather than issuing one
|
||||
// GetCompositionsByTemplateIdAsync round-trip per template.
|
||||
var templates = new List<Template>
|
||||
{
|
||||
@@ -132,7 +135,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new Template("Module") { Id = 1 });
|
||||
_repoMock.Setup(r => r.GetInstancesByTemplateIdAsync(1, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Instance>());
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(templates);
|
||||
|
||||
var result = await _sut.CanDeleteTemplateAsync(1);
|
||||
@@ -165,7 +168,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new Template("Safe") { Id = 1 });
|
||||
_repoMock.Setup(r => r.GetInstancesByTemplateIdAsync(1, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Instance>());
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template> { new("Safe") { Id = 1 } });
|
||||
_repoMock.Setup(r => r.GetCompositionsByTemplateIdAsync(It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateComposition>());
|
||||
@@ -189,7 +192,7 @@ public class TemplateDeletionServiceTests
|
||||
.ReturnsAsync(new List<Instance> { new("Inst1") { Id = 1 } });
|
||||
var composer = new Template("Composer") { Id = 3 };
|
||||
composer.Compositions.Add(new TemplateComposition("Module") { ComposedTemplateId = 1 });
|
||||
_repoMock.Setup(r => r.GetAllTemplatesAsync(It.IsAny<CancellationToken>()))
|
||||
_repoMock.Setup(r => r.GetAllTemplatesForAnalysisAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Template>
|
||||
{
|
||||
new("Busy") { Id = 1 },
|
||||
|
||||
Reference in New Issue
Block a user