From 712029da61094258aa93a906a1b12731bfd5b29a Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 17 Feb 2020 12:51:13 +0800 Subject: [PATCH] Cache document update information. --- .../Documents/DocumentAdminAppService.cs | 37 ++++++++++------- .../Volo/Docs/Documents/DocumentAppService.cs | 40 ++++++++++++++----- .../Volo/Docs/Documents/DocumentUpdateInfo.cs | 14 +++++++ .../Docs/Documents/IDocumentRepository.cs | 7 ++-- .../Documents/EFCoreDocumentRepository.cs | 7 ++++ .../Docs/Documents/MongoDocumentRepository.cs | 8 ++++ .../Documents/TagHelpers/TreeTagHelper.cs | 16 ++++++-- .../Volo/Docs/DocumentRepository_Tests.cs | 10 +++++ 8 files changed, 106 insertions(+), 33 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentUpdateInfo.cs diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs index e50e0c4d03..5fa746907b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Newtonsoft.Json; using Volo.Abp.Application.Services; +using Volo.Abp.Caching; using Volo.Docs.Documents; using Volo.Docs.Projects; @@ -16,14 +17,17 @@ namespace Volo.Docs.Admin.Documents private readonly IProjectRepository _projectRepository; private readonly IDocumentRepository _documentRepository; private readonly IDocumentSourceFactory _documentStoreFactory; + private readonly IDistributedCache _documentUpdateCache; public DocumentAdminAppService(IProjectRepository projectRepository, IDocumentRepository documentRepository, - IDocumentSourceFactory documentStoreFactory) + IDocumentSourceFactory documentStoreFactory, + IDistributedCache documentUpdateCache) { _projectRepository = projectRepository; _documentRepository = documentRepository; _documentStoreFactory = documentStoreFactory; + _documentUpdateCache = documentUpdateCache; } public async Task PullAllAsync(PullAllDocumentInput input) @@ -54,16 +58,12 @@ namespace Volo.Docs.Admin.Documents foreach (var document in documents) { - var oldDocument = await _documentRepository.FindAsync(document.ProjectId, document.Name, + await _documentRepository.DeleteAsync(document.ProjectId, document.Name, document.LanguageCode, document.Version); - if (oldDocument != null) - { - await _documentRepository.DeleteAsync(oldDocument); - } - - await _documentRepository.InsertAsync(document); + await _documentRepository.InsertAsync(document, true); + await UpdateDocumentUpdateInfoCache(document); } } @@ -74,15 +74,21 @@ namespace Volo.Docs.Admin.Documents var source = _documentStoreFactory.Create(project.DocumentStoreType); var sourceDocument = await source.GetDocumentAsync(project, input.Name, input.LanguageCode, input.Version); - var oldDocument = await _documentRepository.FindAsync(sourceDocument.ProjectId, sourceDocument.Name, + await _documentRepository.DeleteAsync(sourceDocument.ProjectId, sourceDocument.Name, sourceDocument.LanguageCode, sourceDocument.Version); + await _documentRepository.InsertAsync(sourceDocument, true); + await UpdateDocumentUpdateInfoCache(sourceDocument); + } - if (oldDocument != null) + private async Task UpdateDocumentUpdateInfoCache(Document document) + { + var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}"; + await _documentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo { - await _documentRepository.DeleteAsync(oldDocument); - } - - await _documentRepository.InsertAsync(sourceDocument); + Name = document.Name, + LastUpdatedTime = document.LastUpdatedTime, + UpdatedCount = document.UpdatedCount + }); } private async Task GetDocumentAsync( @@ -93,7 +99,8 @@ namespace Volo.Docs.Admin.Documents { version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; var source = _documentStoreFactory.Create(project.DocumentStoreType); - return await source.GetDocumentAsync(project, documentName, languageCode, version); + var document = await source.GetDocumentAsync(project, documentName, languageCode, version); + return document; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs index f4ae3a9158..1ef35fda54 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs @@ -18,6 +18,7 @@ namespace Volo.Docs.Documents private readonly IDocumentSourceFactory _documentStoreFactory; protected IDistributedCache LanguageCache { get; } protected IDistributedCache ResourceCache { get; } + protected IDistributedCache DocumentUpdateCache { get; } protected IHostEnvironment HostEnvironment { get; } public DocumentAppService( IProjectRepository projectRepository, @@ -25,6 +26,7 @@ namespace Volo.Docs.Documents IDocumentSourceFactory documentStoreFactory, IDistributedCache languageCache, IDistributedCache resourceCache, + IDistributedCache documentUpdateCache, IHostEnvironment hostEnvironment) { _projectRepository = projectRepository; @@ -32,6 +34,7 @@ namespace Volo.Docs.Documents _documentStoreFactory = documentStoreFactory; LanguageCache = languageCache; ResourceCache = resourceCache; + DocumentUpdateCache = documentUpdateCache; HostEnvironment = hostEnvironment; } @@ -73,20 +76,18 @@ namespace Volo.Docs.Documents var navigationNode = JsonConvert.DeserializeObject(navigationDocument.Content); var leafs = navigationNode.Items.GetAllNodes(x => x.Items) - .Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace()) + .Where(x => !x.Path.IsNullOrWhiteSpace()) .ToList(); foreach (var leaf in leafs) { - var document = await GetDocumentWithDetailsDtoAsync( - project, - leaf.Path, - input.LanguageCode, - input.Version - ); - - leaf.LastUpdatedTime = document.LastUpdatedTime; - leaf.UpdatedCount = document.UpdatedCount; + var cacheKey = $"DocumentUpdateInfo{project.Id}#{leaf.Path}#{input.LanguageCode}#{input.Version}"; + var documentUpdateInfo = await DocumentUpdateCache.GetAsync(cacheKey); + if (documentUpdateInfo != null) + { + leaf.LastUpdatedTime = documentUpdateInfo.LastUpdatedTime; + leaf.UpdatedCount = documentUpdateInfo.UpdatedCount; + } } return navigationNode; @@ -165,10 +166,19 @@ namespace Volo.Docs.Documents var source = _documentStoreFactory.Create(project.DocumentStoreType); var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version); - await _documentRepository.InsertAsync(sourceDocument); + await _documentRepository.DeleteAsync(project.Id, sourceDocument.Name, sourceDocument.LanguageCode, sourceDocument.Version); + await _documentRepository.InsertAsync(sourceDocument, true); Logger.LogInformation($"Document retrieved: {documentName}"); + var cacheKey = $"DocumentUpdateInfo{sourceDocument.ProjectId}#{sourceDocument.Name}#{sourceDocument.LanguageCode}#{sourceDocument.Version}"; + await DocumentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo + { + Name = sourceDocument.Name, + LastUpdatedTime = sourceDocument.LastUpdatedTime, + UpdatedCount = sourceDocument.UpdatedCount + }); + return CreateDocumentWithDetailsDto(project, sourceDocument); } @@ -192,6 +202,14 @@ namespace Volo.Docs.Documents return await GetDocumentAsync(); } + var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}"; + await DocumentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo + { + Name = document.Name, + LastUpdatedTime = document.LastUpdatedTime, + UpdatedCount = document.UpdatedCount + }); + return CreateDocumentWithDetailsDto(project, document); } diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentUpdateInfo.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentUpdateInfo.cs new file mode 100644 index 0000000000..fbdc7056a5 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Documents/DocumentUpdateInfo.cs @@ -0,0 +1,14 @@ +using System; + +namespace Volo.Docs.Documents +{ + [Serializable] + public class DocumentUpdateInfo + { + public virtual string Name { get; set; } + + public virtual DateTime LastUpdatedTime { get; set; } + + public virtual int UpdatedCount { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs index aaabb2d8c7..75e8a22e6d 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Repositories; @@ -12,5 +10,8 @@ namespace Volo.Docs.Documents Task FindAsync(Guid projectId, string name, string languageCode, string version, bool includeDetails = true, CancellationToken cancellationToken = default); + + Task DeleteAsync(Guid projectId, string name, string languageCode, string version, + CancellationToken cancellationToken = default); } -} +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs index d9a96e6c4f..7698ef0b39 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs @@ -25,5 +25,12 @@ namespace Volo.Docs.Documents x.Version == version, cancellationToken); } + + public async Task DeleteAsync(Guid projectId, string name, string languageCode, string version, CancellationToken cancellationToken = default) + { + await DeleteAsync(x => + x.ProjectId == projectId && x.Name == name && x.LanguageCode == languageCode && + x.Version == version, cancellationToken: cancellationToken); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs index 548b89e246..ee72171e0d 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs @@ -24,5 +24,13 @@ namespace Volo.Docs.Documents x.LanguageCode == languageCode && x.Version == version, cancellationToken); } + + public async Task DeleteAsync(Guid projectId, string name, string languageCode, string version, + CancellationToken cancellationToken = default) + { + await DeleteAsync(x => + x.ProjectId == projectId && x.Name == name && x.LanguageCode == languageCode && + x.Version == version, cancellationToken: cancellationToken); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index 23be8a8cff..485de84e4d 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -123,10 +123,18 @@ namespace Volo.Docs.Areas.Documents.TagHelpers } else { - var badge = node.Path.IsNullOrWhiteSpace() - ? "" - : "" + - (node.LastUpdatedTime + TimeSpan.FromDays(30) > DateTime.Now ? (node.UpdatedCount == 1 ? _localizer["New"] : _localizer["Upd"]) : "") + ""; + var badge = ""; + if (!node.Path.IsNullOrWhiteSpace() && node.LastUpdatedTime.HasValue && node.LastUpdatedTime + TimeSpan.FromDays(30) > DateTime.Now) + { + if (node.UpdatedCount > 1) + { + badge = "" + _localizer["Upd"] + ""; + } + else + { + badge = "" + _localizer["New"] + ""; + } + } listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, node.Text.IsNullOrEmpty() diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs index 31d0e8a6fd..68a2ebb5e6 100644 --- a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs +++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs @@ -24,5 +24,15 @@ namespace Volo.Docs var document = await DocumentRepository.FindAsync(DocsTestData.PorjectId, "CLI.md", "en", "2.0.0"); document.ShouldNotBeNull(); } + + [Fact] + public async Task DeleteAsync() + { + (await DocumentRepository.GetListAsync()).ShouldNotBeEmpty(); + + await DocumentRepository.DeleteAsync(DocsTestData.PorjectId, "CLI.md", "en", "2.0.0"); + + (await DocumentRepository.GetListAsync()).ShouldBeEmpty(); + } } }