From 915c071191a578b5db17a5463ffec6d58a5b9910 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:32:52 +0000 Subject: [PATCH] perf: cache book sitemap lookups Cache the singleton MCP query service's ordered and chapter-grouped sitemap data so repeated requests avoid sorting and filtering the same immutable content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Services/BookToolQueryService.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/EssentialCSharp.Web/Services/BookToolQueryService.cs b/EssentialCSharp.Web/Services/BookToolQueryService.cs index b0c6677a..2657836d 100644 --- a/EssentialCSharp.Web/Services/BookToolQueryService.cs +++ b/EssentialCSharp.Web/Services/BookToolQueryService.cs @@ -7,20 +7,29 @@ namespace EssentialCSharp.Web.Services; public sealed class BookToolQueryService : IBookToolQueryService { - private readonly ISiteMappingService _siteMappingService; private readonly IGuidelinesService _guidelinesService; private readonly string _siteUrl; + private readonly List _orderedMappings; + private readonly Dictionary> _mappingsByChapter; public BookToolQueryService( ISiteMappingService siteMappingService, IGuidelinesService guidelinesService, IOptions siteSettings) { - _siteMappingService = siteMappingService; _guidelinesService = guidelinesService; _siteUrl = string.IsNullOrWhiteSpace(siteSettings.Value.BaseUrl) ? "https://essentialcsharp.com" : siteSettings.Value.BaseUrl.TrimEnd('/'); + + _orderedMappings = siteMappingService.SiteMappings + .OrderBy(mapping => mapping.ChapterNumber) + .ThenBy(mapping => mapping.PageNumber) + .ThenBy(mapping => mapping.OrderOnPage) + .ToList(); + _mappingsByChapter = _orderedMappings + .GroupBy(mapping => mapping.ChapterNumber) + .ToDictionary(group => group.Key, group => group.ToList()); } public ChapterListToolResult GetChapterList() @@ -196,18 +205,12 @@ private SiteMapping ResolveSection(string sectionKey) => ?? throw new McpException($"Section '{sectionKey}' not found. Use GetChapterSections or GetChapterList to discover valid section slugs."); private List GetOrderedMappings() => - _siteMappingService.SiteMappings - .OrderBy(mapping => mapping.ChapterNumber) - .ThenBy(mapping => mapping.PageNumber) - .ThenBy(mapping => mapping.OrderOnPage) - .ToList(); + _orderedMappings; private List GetChapterMappings(int chapter) => - _siteMappingService.SiteMappings - .Where(mapping => mapping.ChapterNumber == chapter) - .OrderBy(mapping => mapping.PageNumber) - .ThenBy(mapping => mapping.OrderOnPage) - .ToList(); + _mappingsByChapter.TryGetValue(chapter, out List? mappings) + ? mappings + : []; private BookTocItemResult MapTocItem(SiteMappingDto item) {