diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index db1d4b31f6..8eea6b57cd 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -3,5 +3,10 @@ "LogoUrl": "/assets/images/Logo.png", "ElasticSearch": { "Url": "http://localhost:9200" + }, + "Volo.Docs": { + "DocumentCacheTimeoutInterval": "24:00:00", + "DocumentResource.AbsoluteExpirationRelativeToNow": "24:00:00", + "DocumentResource.SlidingExpiration": "02:00:00" } } \ 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 4e6138d260..61774bfb45 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 @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Nest; using Newtonsoft.Json; using Volo.Abp; using Volo.Abp.Caching; @@ -26,6 +28,10 @@ namespace Volo.Docs.Documents protected IHostEnvironment HostEnvironment { get; } private readonly IDocumentFullSearch _documentFullSearch; private readonly DocsElasticSearchOptions _docsElasticSearchOptions; + private readonly IConfiguration _configuration; + private readonly TimeSpan _cacheTimeout; + private readonly TimeSpan _documentResourceAbsoluteExpiration; + private readonly TimeSpan _documentResourceSlidingExpiration; public DocumentAppService( IProjectRepository projectRepository, @@ -36,7 +42,8 @@ namespace Volo.Docs.Documents IDistributedCache documentUpdateCache, IHostEnvironment hostEnvironment, IDocumentFullSearch documentFullSearch, - IOptions docsElasticSearchOptions) + IOptions docsElasticSearchOptions, + IConfiguration configuration) { _projectRepository = projectRepository; _documentRepository = documentRepository; @@ -46,7 +53,11 @@ namespace Volo.Docs.Documents DocumentUpdateCache = documentUpdateCache; HostEnvironment = hostEnvironment; _documentFullSearch = documentFullSearch; + _configuration = configuration; _docsElasticSearchOptions = docsElasticSearchOptions.Value; + _cacheTimeout = GetCacheTimeout(); + _documentResourceAbsoluteExpiration = GetDocumentResourceAbsoluteExpirationTimeout(); + _documentResourceSlidingExpiration = GetDocumentResourceSlidingExpirationTimeout(); } public virtual async Task GetAsync(GetDocumentInput input) @@ -132,9 +143,8 @@ namespace Volo.Docs.Documents GetResourceAsync, () => new DistributedCacheEntryOptions { - //TODO: Configurable? - AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(6), - SlidingExpiration = TimeSpan.FromMinutes(30) + AbsoluteExpirationRelativeToNow = _documentResourceAbsoluteExpiration, + SlidingExpiration = _documentResourceSlidingExpiration } ); } @@ -200,48 +210,23 @@ namespace Volo.Docs.Documents { version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; - async Task GetDocumentAsync(Document oldDocument = null) - { - Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the source..."); - - var source = _documentStoreFactory.Create(project.DocumentStoreType); - var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version, oldDocument?.LastSignificantUpdateTime); - - 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, - CreationTime = sourceDocument.CreationTime, - LastUpdatedTime = sourceDocument.LastUpdatedTime, - LastSignificantUpdateTime = sourceDocument.LastSignificantUpdateTime - }); - - return CreateDocumentWithDetailsDto(project, sourceDocument); - } - if (HostEnvironment.IsDevelopment()) { - return await GetDocumentAsync(); + return await GetDocumentAsync(documentName, project, languageCode, version); } var document = await _documentRepository.FindAsync(project.Id, documentName, languageCode, version); if (document == null) { - return await GetDocumentAsync(); + return await GetDocumentAsync(documentName, project, languageCode, version); } //Only the latest version (dev) of the document needs to update the cache. if (!project.LatestVersionBranchName.IsNullOrWhiteSpace() && document.Version == project.LatestVersionBranchName && - //TODO: Configurable cache time? - document.LastCachedTime + TimeSpan.FromHours(2) < DateTime.Now) + document.LastCachedTime + _cacheTimeout < DateTime.Now) { - return await GetDocumentAsync(document); + return await GetDocumentAsync(documentName, project, languageCode, version, document); } var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}"; @@ -263,5 +248,62 @@ namespace Volo.Docs.Documents documentDto.Contributors = ObjectMapper.Map, List>(document.Contributors); return documentDto; } + + private async Task GetDocumentAsync(string documentName, Project project, string languageCode, string version, Document oldDocument = null) + { + Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the source..."); + + var source = _documentStoreFactory.Create(project.DocumentStoreType); + var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version, oldDocument?.LastSignificantUpdateTime); + + 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, + CreationTime = sourceDocument.CreationTime, + LastUpdatedTime = sourceDocument.LastUpdatedTime, + LastSignificantUpdateTime = sourceDocument.LastSignificantUpdateTime + }); + + return CreateDocumentWithDetailsDto(project, sourceDocument); + } + + private TimeSpan GetCacheTimeout() + { + var value = _configuration["Volo.Docs:DocumentCacheTimeoutInterval"]; + if (value.IsNullOrEmpty()) + { + return TimeSpan.FromHours(6); + } + + return TimeSpan.Parse(value); + } + + private TimeSpan GetDocumentResourceAbsoluteExpirationTimeout() + { + var value = _configuration["Volo.Docs:DocumentResource.AbsoluteExpirationRelativeToNow"]; + if (value.IsNullOrEmpty()) + { + return TimeSpan.FromHours(6); + } + + return TimeSpan.Parse(value); + } + + private TimeSpan GetDocumentResourceSlidingExpirationTimeout() + { + var value = _configuration["Volo.Docs:DocumentResource.SlidingExpiration"]; + if (value.IsNullOrEmpty()) + { + return TimeSpan.FromMinutes(30); + } + + return TimeSpan.Parse(value); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs index 012fc7aed9..a6285389de 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; using Volo.Abp.Domain.Services; using Volo.Docs.Documents; using Volo.Docs.GitHub.Projects; using Volo.Docs.Projects; -using Newtonsoft.Json.Linq; using Octokit; using Volo.Abp; using Volo.Extensions; @@ -206,8 +204,14 @@ namespace Volo.Docs.GitHub.Documents var url = project.GetGitHubUrl(); var ownerName = GetOwnerNameFromUrl(url); var repositoryName = GetRepositoryNameFromUrl(url); - return await _githubRepositoryManager.GetFileCommitsAsync(ownerName, repositoryName, - version, filename, project.GetGitHubAccessTokenOrNull()); + + return await _githubRepositoryManager.GetFileCommitsAsync( + ownerName, + repositoryName, + version, + filename, + project.GetGitHubAccessTokenOrNull() + ); } protected virtual string GetOwnerNameFromUrl(string url) @@ -219,7 +223,7 @@ namespace Volo.Docs.GitHub.Documents } catch (Exception) { - throw new Exception($"Github url is not valid: {url}"); + throw new Exception($"GitHub url is not valid: {url}"); } }