From 84493107d26c5091812bf4d319f6e6b6d23dda93 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 5 Feb 2021 20:17:08 +0100 Subject: [PATCH] Lazy references. --- .../Assets/AssetsFluidExtension.cs | 36 +++++++++++------- .../Assets/AssetsJintExtension.cs | 37 ++++++++++++------- .../Contents/ReferencesFluidExtension.cs | 36 +++++++++++------- .../Contents/ReferencesJintExtension.cs | 37 ++++++++++++------- .../Assets/AssetsFluidExtensionTests.cs | 9 ++++- .../Assets/AssetsJintExtensionTests.cs | 9 ++++- .../Contents/ReferencesFluidExtensionTests.cs | 9 ++++- .../Contents/ReferencesJintExtensionTests.cs | 9 ++++- 8 files changed, 122 insertions(+), 60 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsFluidExtension.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsFluidExtension.cs index d0fbdacd9..6ecd04860 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsFluidExtension.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsFluidExtension.cs @@ -5,38 +5,40 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.IO; using System.Text.Encodings.Web; using System.Threading.Tasks; using Fluid; using Fluid.Ast; using Fluid.Tags; +using GraphQL.Utilities; using Squidex.Domain.Apps.Core.Rules.EnrichedEvents; using Squidex.Domain.Apps.Core.Templates; using Squidex.Domain.Apps.Core.ValidateContent; +using Squidex.Domain.Apps.Entities.Apps; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Assets { public sealed class AssetsFluidExtension : IFluidExtension { - private readonly IAppProvider appProvider; - private readonly IAssetQueryService assetQuery; + private readonly IServiceProvider serviceProvider; private sealed class AssetTag : ArgumentsTag { - private readonly AssetsFluidExtension root; + private readonly IServiceProvider serviceProvider; - public AssetTag(AssetsFluidExtension root) + public AssetTag(IServiceProvider serviceProvider) { - this.root = root; + this.serviceProvider = serviceProvider; } public override async ValueTask WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context, FilterArgument[] arguments) { if (arguments.Length == 2 && context.GetValue("event")?.ToObjectValue() is EnrichedEvent enrichedEvent) { - var app = await root.appProvider.GetAppAsync(enrichedEvent.AppId.Id, false); + var app = await GetAppAsync(enrichedEvent); if (app == null) { @@ -49,7 +51,9 @@ namespace Squidex.Domain.Apps.Entities.Assets var id = (await arguments[1].Expression.EvaluateAsync(context)).ToStringValue(); - var asset = await root.assetQuery.FindAsync(requestContext, DomainId.Create(id)); + var assetQuery = serviceProvider.GetRequiredService(); + + var asset = await assetQuery.FindAsync(requestContext, DomainId.Create(id)); if (asset != null) { @@ -61,16 +65,20 @@ namespace Squidex.Domain.Apps.Entities.Assets return Completion.Normal; } + + private Task GetAppAsync(EnrichedEvent enrichedEvent) + { + var appProvider = serviceProvider.GetRequiredService(); + + return appProvider.GetAppAsync(enrichedEvent.AppId.Id, false); + } } - public AssetsFluidExtension(IAppProvider appProvider, IAssetQueryService assetQuery) + public AssetsFluidExtension(IServiceProvider serviceProvider) { - Guard.NotNull(assetQuery, nameof(assetQuery)); - Guard.NotNull(appProvider, nameof(appProvider)); - - this.assetQuery = assetQuery; + Guard.NotNull(serviceProvider, nameof(serviceProvider)); - this.appProvider = appProvider; + this.serviceProvider = serviceProvider; } public void RegisterGlobalTypes(IMemberAccessStrategy memberAccessStrategy) @@ -86,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Assets public void RegisterLanguageExtensions(FluidParserFactory factory) { - factory.RegisterTag("asset", new AssetTag(this)); + factory.RegisterTag("asset", new AssetTag(serviceProvider)); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsJintExtension.cs b/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsJintExtension.cs index 971ec9845..4df5836ef 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsJintExtension.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsJintExtension.cs @@ -10,9 +10,11 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; +using GraphQL.Utilities; using Jint.Native; using Jint.Runtime; using Squidex.Domain.Apps.Core.Scripting; +using Squidex.Domain.Apps.Entities.Apps; using Squidex.Infrastructure; using Squidex.Infrastructure.Tasks; @@ -21,17 +23,13 @@ namespace Squidex.Domain.Apps.Entities.Assets public sealed class AssetsJintExtension : IJintExtension { private delegate void GetAssetsDelegate(JsValue references, Action callback); - private readonly IAppProvider appProvider; - private readonly IAssetQueryService assetQuery; + private readonly IServiceProvider serviceProvider; - public AssetsJintExtension(IAppProvider appProvider, IAssetQueryService assetQuery) + public AssetsJintExtension(IServiceProvider serviceProvider) { - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(assetQuery, nameof(assetQuery)); + Guard.NotNull(serviceProvider, nameof(serviceProvider)); - this.appProvider = appProvider; - - this.assetQuery = assetQuery; + this.serviceProvider = serviceProvider; } public void ExtendAsync(ExecutionContext context) @@ -90,17 +88,14 @@ namespace Squidex.Domain.Apps.Entities.Assets try { - var app = await appProvider.GetAppAsync(appId); - - if (app == null) - { - throw new JavaScriptException("App does not exist."); - } + var app = await GetAppAsync(appId); var requestContext = new Context(user, app).Clone(b => b .WithoutTotal()); + var assetQuery = serviceProvider.GetRequiredService(); + var assets = await assetQuery.QueryAsync(requestContext, null, Q.Empty.WithIds(ids)); callback(JsValue.FromObject(context.Engine, assets.ToArray())); @@ -110,5 +105,19 @@ namespace Squidex.Domain.Apps.Entities.Assets context.Fail(ex); } } + + private async Task GetAppAsync(DomainId appId) + { + var appProvider = serviceProvider.GetRequiredService(); + + var app = await appProvider.GetAppAsync(appId); + + if (app == null) + { + throw new JavaScriptException("App does not exist."); + } + + return app; + } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesFluidExtension.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesFluidExtension.cs index 1d624c017..adbb034ab 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesFluidExtension.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesFluidExtension.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,8 +14,10 @@ using System.Threading.Tasks; using Fluid; using Fluid.Ast; using Fluid.Tags; +using GraphQL.Utilities; using Squidex.Domain.Apps.Core.Rules.EnrichedEvents; using Squidex.Domain.Apps.Core.Templates; +using Squidex.Domain.Apps.Entities.Apps; using Squidex.Infrastructure; #pragma warning disable CA1826 // Do not use Enumerable methods on indexable collections @@ -23,23 +26,22 @@ namespace Squidex.Domain.Apps.Entities.Contents { public sealed class ReferencesFluidExtension : IFluidExtension { - private readonly IAppProvider appProvider; - private readonly IContentQueryService contentQuery; + private readonly IServiceProvider serviceProvider; private sealed class ReferenceTag : ArgumentsTag { - private readonly ReferencesFluidExtension root; + private readonly IServiceProvider serviceProvider; - public ReferenceTag(ReferencesFluidExtension root) + public ReferenceTag(IServiceProvider serviceProvider) { - this.root = root; + this.serviceProvider = serviceProvider; } public override async ValueTask WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context, FilterArgument[] arguments) { if (arguments.Length == 2 && context.GetValue("event")?.ToObjectValue() is EnrichedEvent enrichedEvent) { - var app = await root.appProvider.GetAppAsync(enrichedEvent.AppId.Id, false); + var app = await GetAppAsync(enrichedEvent); if (app == null) { @@ -57,7 +59,9 @@ namespace Squidex.Domain.Apps.Entities.Contents var domainId = DomainId.Create(id); var domainIds = new List { domainId }; - var contents = await root.contentQuery.QueryAsync(requestContext, Q.Empty.WithIds(domainIds)); + var contentQuery = serviceProvider.GetRequiredService(); + + var contents = await contentQuery.QueryAsync(requestContext, Q.Empty.WithIds(domainIds)); var content = contents.FirstOrDefault(); if (content != null) @@ -70,16 +74,20 @@ namespace Squidex.Domain.Apps.Entities.Contents return Completion.Normal; } + + private Task GetAppAsync(EnrichedEvent enrichedEvent) + { + var appProvider = serviceProvider.GetRequiredService(); + + return appProvider.GetAppAsync(enrichedEvent.AppId.Id, false); + } } - public ReferencesFluidExtension(IAppProvider appProvider, IContentQueryService contentQuery) + public ReferencesFluidExtension(IServiceProvider serviceProvider) { - Guard.NotNull(contentQuery, nameof(contentQuery)); - Guard.NotNull(appProvider, nameof(appProvider)); - - this.contentQuery = contentQuery; + Guard.NotNull(serviceProvider, nameof(serviceProvider)); - this.appProvider = appProvider; + this.serviceProvider = serviceProvider; } public void RegisterGlobalTypes(IMemberAccessStrategy memberAccessStrategy) @@ -94,7 +102,7 @@ namespace Squidex.Domain.Apps.Entities.Contents public void RegisterLanguageExtensions(FluidParserFactory factory) { - factory.RegisterTag("reference", new ReferenceTag(this)); + factory.RegisterTag("reference", new ReferenceTag(serviceProvider)); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesJintExtension.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesJintExtension.cs index 7fc6428a3..7eb69f12a 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesJintExtension.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/ReferencesJintExtension.cs @@ -12,7 +12,9 @@ using System.Security.Claims; using System.Threading.Tasks; using Jint.Native; using Jint.Runtime; +using Microsoft.Extensions.DependencyInjection; using Squidex.Domain.Apps.Core.Scripting; +using Squidex.Domain.Apps.Entities.Apps; using Squidex.Infrastructure; using Squidex.Infrastructure.Tasks; @@ -21,17 +23,13 @@ namespace Squidex.Domain.Apps.Entities.Contents public sealed class ReferencesJintExtension : IJintExtension { private delegate void GetReferencesDelegate(JsValue references, Action callback); - private readonly IAppProvider appProvider; - private readonly IContentQueryService contentQuery; + private readonly IServiceProvider serviceProvider; - public ReferencesJintExtension(IAppProvider appProvider, IContentQueryService contentQuery) + public ReferencesJintExtension(IServiceProvider serviceProvider) { - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(contentQuery, nameof(contentQuery)); + Guard.NotNull(serviceProvider, nameof(serviceProvider)); - this.appProvider = appProvider; - - this.contentQuery = contentQuery; + this.serviceProvider = serviceProvider; } public void ExtendAsync(ExecutionContext context) @@ -90,12 +88,7 @@ namespace Squidex.Domain.Apps.Entities.Contents try { - var app = await appProvider.GetAppAsync(appId); - - if (app == null) - { - throw new JavaScriptException("App does not exist."); - } + var app = await GetAppAsync(appId); var requestContext = new Context(user, app).Clone(b => b @@ -103,6 +96,8 @@ namespace Squidex.Domain.Apps.Entities.Contents .WithUnpublished() .WithoutTotal()); + var contentQuery = serviceProvider.GetRequiredService(); + var contents = await contentQuery.QueryAsync(requestContext, Q.Empty.WithIds(ids)); callback(JsValue.FromObject(context.Engine, contents.ToArray())); @@ -112,5 +107,19 @@ namespace Squidex.Domain.Apps.Entities.Contents context.Fail(ex); } } + + private async Task GetAppAsync(DomainId appId) + { + var appProvider = serviceProvider.GetRequiredService(); + + var app = await appProvider.GetAppAsync(appId); + + if (app == null) + { + throw new JavaScriptException("App does not exist."); + } + + return app; + } } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs index 3add1b614..7ff9b7291 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using FakeItEasy; +using Microsoft.Extensions.DependencyInjection; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Rules.EnrichedEvents; using Squidex.Domain.Apps.Core.Templates; @@ -26,9 +27,15 @@ namespace Squidex.Domain.Apps.Entities.Assets public AssetsFluidExtensionTests() { + var services = + new ServiceCollection() + .AddSingleton(appProvider) + .AddSingleton(assetQuery) + .BuildServiceProvider(); + var extensions = new IFluidExtension[] { - new AssetsFluidExtension(appProvider, assetQuery) + new AssetsFluidExtension(services) }; A.CallTo(() => appProvider.GetAppAsync(appId.Id, false)) diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs index a5229d320..20ede6483 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs @@ -9,6 +9,7 @@ using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Scripting; @@ -29,9 +30,15 @@ namespace Squidex.Domain.Apps.Entities.Assets public AssetsJintExtensionTests() { + var services = + new ServiceCollection() + .AddSingleton(appProvider) + .AddSingleton(assetQuery) + .BuildServiceProvider(); + var extensions = new IJintExtension[] { - new AssetsJintExtension(appProvider, assetQuery) + new AssetsJintExtension(services) }; A.CallTo(() => appProvider.GetAppAsync(appId.Id, false)) diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesFluidExtensionTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesFluidExtensionTests.cs index ee3acb642..37875c882 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesFluidExtensionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesFluidExtensionTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using FakeItEasy; +using Microsoft.Extensions.DependencyInjection; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Rules.EnrichedEvents; using Squidex.Domain.Apps.Core.Templates; @@ -26,9 +27,15 @@ namespace Squidex.Domain.Apps.Entities.Contents public ReferencesFluidExtensionTests() { + var services = + new ServiceCollection() + .AddSingleton(appProvider) + .AddSingleton(contentQuery) + .BuildServiceProvider(); + var extensions = new IFluidExtension[] { - new ReferencesFluidExtension(appProvider, contentQuery) + new ReferencesFluidExtension(services) }; A.CallTo(() => appProvider.GetAppAsync(appId.Id, false)) diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesJintExtensionTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesJintExtensionTests.cs index 90371b471..5fc9e81da 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesJintExtensionTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ReferencesJintExtensionTests.cs @@ -9,6 +9,7 @@ using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Scripting; @@ -29,9 +30,15 @@ namespace Squidex.Domain.Apps.Entities.Contents public ReferencesJintExtensionTests() { + var services = + new ServiceCollection() + .AddSingleton(appProvider) + .AddSingleton(contentQuery) + .BuildServiceProvider(); + var extensions = new IJintExtension[] { - new ReferencesJintExtension(appProvider, contentQuery) + new ReferencesJintExtension(services) }; A.CallTo(() => appProvider.GetAppAsync(appId.Id, false))