Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add As/Put method to ISite to allow caching #14372

Merged
merged 11 commits into from
Nov 24, 2023
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Options;
using OrchardCore.Entities;
using OrchardCore.Settings;

namespace OrchardCore.Media.Processing
Expand Down
23 changes: 23 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Settings/SiteSettings.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System.Collections.Concurrent;
using Microsoft.AspNetCore.Routing;
using OrchardCore.Documents;
using OrchardCore.Entities;

namespace OrchardCore.Settings
{
// When updating class also update SiteSettingsDeploymentSource and SettingsStep.
public class SiteSettings : DocumentEntity, ISite
{
private readonly ConcurrentDictionary<string, object> _cache = new();

public string BaseUrl { get; set; }
public string Calendar { get; set; }
public int MaxPagedCount { get; set; }
Expand All @@ -22,5 +26,24 @@ public class SiteSettings : DocumentEntity, ISite
public RouteValueDictionary HomeRoute { get; set; } = new RouteValueDictionary();
public bool AppendVersion { get; set; } = true;
public CacheMode CacheMode { get; set; }

public T As<T>() where T : new()
{
var name = typeof(T).Name;
if (!IsReadOnly)
{
return this.As<T>(name);
}

if (_cache.TryGetValue(name, out var obj) && obj is T value)
{
return value;
}

var settings = this.As<T>(name);
MikeAlhayek marked this conversation as resolved.
Show resolved Hide resolved
_cache[name] = settings;

return settings;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Newtonsoft.Json;

namespace OrchardCore.Data.Documents
{
public class Document : IDocument
Expand All @@ -6,5 +8,11 @@ public class Document : IDocument
/// The <see cref="IDocument.Identifier"/>.
/// </summary>
public string Identifier { get; set; }

/// <summary>
/// Whether the document is immutable or not.
/// </summary>
[JsonIgnore]
public bool IsReadOnly { get; set; } = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ public interface IDocument
/// The unique identifier of the document.
/// </summary>
string Identifier { get; set; }

/// <summary>
/// Whether the document was loaded for updating.
/// </summary>
bool IsReadOnly { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ namespace OrchardCore.Documents
/// </summary>
public class DocumentEntity : Document, IDocumentEntity
{
public JObject Properties { get; set; } = new JObject();
public JObject Properties { get; set; } = new();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace OrchardCore.Entities
{
public class Entity : IEntity
{
public JObject Properties { get; set; } = new JObject();
public JObject Properties { get; set; } = new();
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
using Microsoft.AspNetCore.Routing;
using OrchardCore.Entities;

namespace OrchardCore.Settings
namespace OrchardCore.Settings;

public interface ISite : IEntity
{
public interface ISite : IEntity
{
string SiteName { get; set; }
string PageTitleFormat { get; set; }
string SiteSalt { get; set; }
string SuperUser { get; set; }
string Calendar { get; set; }
string TimeZoneId { get; set; }
ResourceDebugMode ResourceDebugMode { get; set; }
bool UseCdn { get; set; }
string CdnBaseUrl { get; set; }
int PageSize { get; set; }
int MaxPageSize { get; set; }
int MaxPagedCount { get; set; }
string BaseUrl { get; set; }
RouteValueDictionary HomeRoute { get; set; }
bool AppendVersion { get; set; }
CacheMode CacheMode { get; set; }
}
string SiteName { get; set; }

string PageTitleFormat { get; set; }

string SiteSalt { get; set; }

string SuperUser { get; set; }

string Calendar { get; set; }

string TimeZoneId { get; set; }

ResourceDebugMode ResourceDebugMode { get; set; }

bool UseCdn { get; set; }

string CdnBaseUrl { get; set; }

int PageSize { get; set; }

int MaxPageSize { get; set; }

int MaxPagedCount { get; set; }

string BaseUrl { get; set; }

RouteValueDictionary HomeRoute { get; set; }

bool AppendVersion { get; set; }

CacheMode CacheMode { get; set; }

T As<T>() where T : new();
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public async Task<TDocument> GetOrCreateMutableAsync(Func<Task<TDocument>> facto
}

document.Identifier = IdGenerator.GenerateId();
document.IsReadOnly = false;

return document;
}
Expand Down Expand Up @@ -306,6 +307,8 @@ private async Task<TDocument> GetInternalAsync(bool failover = false)

protected async Task SetInternalAsync(TDocument document, bool failover = false)
{
document.IsReadOnly = true;

if (!failover)
{
await UpdateDistributedCacheAsync(document);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using OrchardCore.Media;
using OrchardCore.Media.Processing;
using OrchardCore.Settings;
using OrchardCore.Tests.Utilities;
using SixLabors.ImageSharp.Web.Processors;

namespace OrchardCore.Tests.Modules.OrchardCore.Media
Expand Down Expand Up @@ -71,15 +72,13 @@ private IServiceProvider CreateServiceProvider()
{
var services = new ServiceCollection();

var mockSiteService = Mock.Of<ISiteService>(ss =>
ss.GetSiteSettingsAsync() == Task.FromResult(
Mock.Of<ISite>(s => s.Properties == JObject.FromObject(new { MediaTokenSettings = _mediaTokenSettings }))
)
);
var mockSite = SiteMockHelper.GetSite(_mediaTokenSettings);

var mockSiteService = Mock.Of<ISiteService>(ss => ss.GetSiteSettingsAsync() == Task.FromResult(mockSite.Object));

services.AddMemoryCache();

services.AddSingleton<ISiteService>(mockSiteService);
services.AddSingleton(mockSiteService);
services.AddSingleton<IImageWebProcessor, TokenCommandProcessor>();
services.AddSingleton<IImageWebProcessor, TokenCommandProcessor>();
services.AddSingleton<IImageWebProcessor, ResizeWebProcessor>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.Email;
using OrchardCore.Settings;
using OrchardCore.Tests.Utilities;
using OrchardCore.Users;
using OrchardCore.Users.Controllers;
using OrchardCore.Users.Events;
Expand Down Expand Up @@ -133,15 +134,12 @@ private static RegistrationController SetupRegistrationController(RegistrationSe
.Returns<string>(e =>
{
var user = users.SingleOrDefault(u => (u as User).Email == e);

return Task.FromResult(user);
});

var mockSiteService = Mock.Of<ISiteService>(ss =>
ss.GetSiteSettingsAsync() == Task.FromResult(
Mock.Of<ISite>(s => s.Properties == JObject.FromObject(new { RegistrationSettings = registrationSettings }))
)
);
var mockSite = SiteMockHelper.GetSite(registrationSettings);

var mockSiteService = Mock.Of<ISiteService>(ss => ss.GetSiteSettingsAsync() == Task.FromResult(mockSite.Object));
var mockSmtpService = Mock.Of<ISmtpService>(x => x.SendAsync(It.IsAny<MailMessage>()) == Task.FromResult(SmtpResult.Success));
var mockStringLocalizer = new Mock<IStringLocalizer<RegistrationController>>();
mockStringLocalizer.Setup(l => l[It.IsAny<string>()])
Expand Down
23 changes: 23 additions & 0 deletions test/OrchardCore.Tests/Utilities/SiteMockHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using OrchardCore.Settings;

namespace OrchardCore.Tests.Utilities;

public class SiteMockHelper
{
public static Mock<ISite> GetSite<T>(T obj) where T : new()
{
var properties = new JObject
{
[obj.GetType().Name] = JObject.FromObject(obj)
};

var mockSite = new Mock<ISite>();
mockSite.Setup(x => x.Properties)
.Returns(properties);

mockSite.Setup(x => x.As<T>())
.Returns(obj);

return mockSite;
}
}