Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

move HtmlText caching from repository to service layer #4520

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,15 @@ namespace Oqtane.Modules.HtmlText.Manager
[PrivateApi("Mark HtmlText classes as private, since it's not very useful in the public docs")]
public class HtmlTextManager : MigratableModuleBase, IInstallable, IPortable, ISearchable
{
private readonly IServiceProvider _serviceProvider;
private readonly IHtmlTextRepository _htmlText;
private readonly IDBContextDependencies _DBContextDependencies;
private readonly ISqlRepository _sqlRepository;

public HtmlTextManager(
IServiceProvider serviceProvider,
IHtmlTextRepository htmlText,
IDBContextDependencies DBContextDependencies,
ISqlRepository sqlRepository)
{
_serviceProvider = serviceProvider;
_htmlText = htmlText;
_DBContextDependencies = DBContextDependencies;
_sqlRepository = sqlRepository;
Expand All @@ -53,19 +50,15 @@ public Task<List<SearchContent>> GetSearchContentsAsync(PageModule pageModule, D
{
var searchContents = new List<SearchContent>();

var htmltexts = _htmlText.GetHtmlTexts(pageModule.ModuleId);
if (htmltexts != null && htmltexts.Any())
var htmltext = _htmlText.GetHtmlTexts(pageModule.ModuleId)?.OrderByDescending(item => item.CreatedOn).FirstOrDefault();
if (htmltext != null && htmltext.CreatedOn >= lastIndexedOn)
{
var htmltext = htmltexts.OrderByDescending(item => item.CreatedOn).First();
if (htmltext.CreatedOn >= lastIndexedOn)
searchContents.Add(new SearchContent
{
searchContents.Add(new SearchContent
{
Body = htmltext.Content,
ContentModifiedBy = htmltext.CreatedBy,
ContentModifiedOn = htmltext.CreatedOn
});
}
Body = htmltext.Content,
ContentModifiedBy = htmltext.CreatedBy,
ContentModifiedOn = htmltext.CreatedOn
});
}

return Task.FromResult(searchContents);
Expand Down
59 changes: 3 additions & 56 deletions Oqtane.Server/Modules/HtmlText/Repository/HtmlTextRepository.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,24 @@
using System.Linq;
using Oqtane.Documentation;
using System.Collections.Generic;
using Microsoft.Extensions.Caching.Memory;
using System;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using Oqtane.Shared;

namespace Oqtane.Modules.HtmlText.Repository
{
[PrivateApi("Mark HtmlText classes as private, since it's not very useful in the public docs")]
public class HtmlTextRepository : IHtmlTextRepository, ITransientService
{
private readonly IDbContextFactory<HtmlTextContext> _factory;
private readonly IMemoryCache _cache;
private readonly SiteState _siteState;

public HtmlTextRepository(IDbContextFactory<HtmlTextContext> factory, IMemoryCache cache, SiteState siteState)
public HtmlTextRepository(IDbContextFactory<HtmlTextContext> factory)
{
_factory = factory;
_cache = cache;
_siteState = siteState;
}

public IEnumerable<Models.HtmlText> GetHtmlTexts(int moduleId)
{
return _cache.GetOrCreate($"HtmlText:{_siteState.Alias.SiteKey}:{moduleId}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
using var db = _factory.CreateDbContext();
return db.HtmlText.Where(item => item.ModuleId == moduleId).ToList();
});
using var db = _factory.CreateDbContext();
return db.HtmlText.Where(item => item.ModuleId == moduleId).ToList();
}

public Models.HtmlText GetHtmlText(int htmlTextId)
Expand All @@ -44,7 +32,6 @@ public Models.HtmlText AddHtmlText(Models.HtmlText htmlText)
using var db = _factory.CreateDbContext();
db.HtmlText.Add(htmlText);
db.SaveChanges();
ClearCache(htmlText.ModuleId);
return htmlText;
}

Expand All @@ -53,47 +40,7 @@ public void DeleteHtmlText(int htmlTextId)
using var db = _factory.CreateDbContext();
Models.HtmlText htmlText = db.HtmlText.FirstOrDefault(item => item.HtmlTextId == htmlTextId);
if (htmlText != null) db.HtmlText.Remove(htmlText);
ClearCache(htmlText.ModuleId);
db.SaveChanges();
}

public async Task<IEnumerable<Models.HtmlText>> GetHtmlTextsAsync(int moduleId)
{
return await _cache.GetOrCreateAsync($"HtmlText:{_siteState.Alias.SiteKey}:{moduleId}", async entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
using var db = _factory.CreateDbContext();
return await db.HtmlText.Where(item => item.ModuleId == moduleId).ToListAsync();
});
}

public async Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId)
{
using var db = _factory.CreateDbContext();
return await db.HtmlText.FindAsync(htmlTextId);
}

public async Task<Models.HtmlText> AddHtmlTextAsync(Models.HtmlText htmlText)
{
using var db = _factory.CreateDbContext();
db.HtmlText.Add(htmlText);
await db.SaveChangesAsync();
ClearCache(htmlText.ModuleId);
return htmlText;
}

public async Task DeleteHtmlTextAsync(int htmlTextId)
{
using var db = _factory.CreateDbContext();
Models.HtmlText htmlText = db.HtmlText.FirstOrDefault(item => item.HtmlTextId == htmlTextId);
db.HtmlText.Remove(htmlText);
ClearCache(htmlText.ModuleId);
await db.SaveChangesAsync();
}

private void ClearCache(int moduleId)
{
_cache.Remove($"HtmlText:{_siteState.Alias.SiteKey}:{moduleId}");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Oqtane.Documentation;

namespace Oqtane.Modules.HtmlText.Repository
Expand All @@ -11,10 +10,5 @@ public interface IHtmlTextRepository
Models.HtmlText GetHtmlText(int htmlTextId);
Models.HtmlText AddHtmlText(Models.HtmlText htmlText);
void DeleteHtmlText(int htmlTextId);

Task<IEnumerable<Models.HtmlText>> GetHtmlTextsAsync(int moduleId);
Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId);
Task<Models.HtmlText> AddHtmlTextAsync(Models.HtmlText htmlText);
Task DeleteHtmlTextAsync(int htmlTextId);
}
}
53 changes: 33 additions & 20 deletions Oqtane.Server/Modules/HtmlText/Services/HtmlTextService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using Oqtane.Documentation;
using Oqtane.Enums;
using Oqtane.Infrastructure;
Expand All @@ -17,24 +19,26 @@ public class ServerHtmlTextService : IHtmlTextService, ITransientService
{
private readonly IHtmlTextRepository _htmlText;
private readonly IUserPermissions _userPermissions;
private readonly IMemoryCache _cache;
private readonly ILogManager _logger;
private readonly IHttpContextAccessor _accessor;
private readonly Alias _alias;

public ServerHtmlTextService(IHtmlTextRepository htmlText, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
public ServerHtmlTextService(IHtmlTextRepository htmlText, IUserPermissions userPermissions, IMemoryCache cache, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
{
_htmlText = htmlText;
_userPermissions = userPermissions;
_cache = cache;
_logger = logger;
_accessor = accessor;
_alias = tenantManager.GetAlias();
}

public async Task<List<Models.HtmlText>> GetHtmlTextsAsync(int moduleId)
public Task<List<Models.HtmlText>> GetHtmlTextsAsync(int moduleId)
{
if (_accessor.HttpContext.User.IsInRole(RoleNames.Registered))
{
return (await _htmlText.GetHtmlTextsAsync(moduleId)).ToList();
return Task.FromResult(GetCachedHtmlTexts(moduleId));
}
else
{
Expand All @@ -43,19 +47,11 @@ public ServerHtmlTextService(IHtmlTextRepository htmlText, IUserPermissions user
}
}

public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
public Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, moduleId, PermissionNames.View))
{
var htmltexts = await _htmlText.GetHtmlTextsAsync(moduleId);
if (htmltexts != null && htmltexts.Any())
{
return htmltexts.OrderByDescending(item => item.CreatedOn).First();
}
else
{
return null;
}
return Task.FromResult(GetCachedHtmlTexts(moduleId)?.OrderByDescending(item => item.CreatedOn).FirstOrDefault());
}
else
{
Expand All @@ -64,11 +60,11 @@ public ServerHtmlTextService(IHtmlTextRepository htmlText, IUserPermissions user
}
}

public async Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId, int moduleId)
public Task<Models.HtmlText> GetHtmlTextAsync(int htmlTextId, int moduleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, moduleId, PermissionNames.View))
{
return await _htmlText.GetHtmlTextAsync(htmlTextId);
return Task.FromResult(GetCachedHtmlTexts(moduleId)?.FirstOrDefault(item => item.HtmlTextId == htmlTextId));
}
else
{
Expand All @@ -77,32 +73,49 @@ public ServerHtmlTextService(IHtmlTextRepository htmlText, IUserPermissions user
}
}

public async Task<Models.HtmlText> AddHtmlTextAsync(Models.HtmlText htmlText)
public Task<Models.HtmlText> AddHtmlTextAsync(Models.HtmlText htmlText)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, htmlText.ModuleId, PermissionNames.Edit))
{
htmlText = await _htmlText.AddHtmlTextAsync(htmlText);
htmlText = _htmlText.AddHtmlText(htmlText);
ClearCache(htmlText.ModuleId);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Html/Text Added {HtmlText}", htmlText);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Add Attempt {HtmlText}", htmlText);
htmlText = null;
}
return htmlText;
return Task.FromResult(htmlText);
}

public async Task DeleteHtmlTextAsync(int htmlTextId, int moduleId)
public Task DeleteHtmlTextAsync(int htmlTextId, int moduleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, moduleId, PermissionNames.Edit))
{
await _htmlText.DeleteHtmlTextAsync(htmlTextId);
_htmlText.DeleteHtmlText(htmlTextId);
ClearCache(moduleId);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Html/Text Deleted {HtmlTextId}", htmlTextId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Html/Text Delete Attempt {HtmlTextId} {ModuleId}", htmlTextId, moduleId);
}
return Task.CompletedTask;
}

private List<Models.HtmlText> GetCachedHtmlTexts(int moduleId)
{
return _cache.GetOrCreate($"HtmlText:{_alias.SiteKey}:{moduleId}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return _htmlText.GetHtmlTexts(moduleId).ToList();
});
}

private void ClearCache(int moduleId)
{
_cache.Remove($"HtmlText:{_alias.SiteKey}:{moduleId}");
}
}
}