diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/QueryExecutionContext.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/QueryExecutionContext.cs index 866e49213..691c031cd 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/QueryExecutionContext.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/QueryExecutionContext.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Infrastructure; @@ -17,6 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries { public class QueryExecutionContext : Dictionary { + private readonly SemaphoreSlim maxRequests = new SemaphoreSlim(10); private readonly ConcurrentDictionary cachedContents = new ConcurrentDictionary(); private readonly ConcurrentDictionary cachedAssets = new ConcurrentDictionary(); private readonly IContentQueryService contentQuery; @@ -45,7 +47,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries if (asset == null) { - asset = await assetQuery.FindAssetAsync(context, id); + await maxRequests.WaitAsync(); + try + { + asset = await assetQuery.FindAssetAsync(context, id); + } + finally + { + maxRequests.Release(); + } if (asset != null) { @@ -62,7 +72,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries if (content == null) { - content = await contentQuery.FindContentAsync(context, schemaId.ToString(), id); + await maxRequests.WaitAsync(); + try + { + content = await contentQuery.FindContentAsync(context, schemaId.ToString(), id); + } + finally + { + maxRequests.Release(); + } if (content != null) { @@ -77,7 +95,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries { var q = Q.Empty.WithODataQuery(odata); - var assets = await assetQuery.QueryAsync(context, null, q); + IResultList assets; + + await maxRequests.WaitAsync(); + try + { + assets = await assetQuery.QueryAsync(context, null, q); + } + finally + { + maxRequests.Release(); + } foreach (var asset in assets) { @@ -91,14 +119,24 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries { var q = Q.Empty.WithODataQuery(odata); - var result = await contentQuery.QueryAsync(context, schemaIdOrName, q); + IResultList contents; + + await maxRequests.WaitAsync(); + try + { + contents = await contentQuery.QueryAsync(context, schemaIdOrName, q); + } + finally + { + maxRequests.Release(); + } - foreach (var content in result) + foreach (var content in contents) { cachedContents[content.Id] = content; } - return result; + return contents; } public virtual async Task> GetReferencedAssetsAsync(ICollection ids) @@ -109,7 +147,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries if (notLoadedAssets.Count > 0) { - var assets = await assetQuery.QueryAsync(context, null, Q.Empty.WithIds(notLoadedAssets)); + IResultList assets; + + await maxRequests.WaitAsync(); + try + { + assets = await assetQuery.QueryAsync(context, null, Q.Empty.WithIds(notLoadedAssets)); + } + finally + { + maxRequests.Release(); + } foreach (var asset in assets) { @@ -128,9 +176,19 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries if (notLoadedContents.Count > 0) { - var result = await contentQuery.QueryAsync(context, notLoadedContents); + IResultList contents; + + await maxRequests.WaitAsync(); + try + { + contents = await contentQuery.QueryAsync(context, notLoadedContents); + } + finally + { + maxRequests.Release(); + } - foreach (var content in result) + foreach (var content in contents) { cachedContents[content.Id] = content; } @@ -139,11 +197,19 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries return ids.Select(cachedContents.GetOrDefault).NotNull().ToList(); } - public Task> QueryReferencingContentsAsync(string schemaIdOrName, string odata, Guid reference) + public async Task> QueryReferencingContentsAsync(string schemaIdOrName, string odata, Guid reference) { var q = Q.Empty.WithODataQuery(odata).WithReference(reference); - return contentQuery.QueryAsync(context, schemaIdOrName, q); + await maxRequests.WaitAsync(); + try + { + return await contentQuery.QueryAsync(context, schemaIdOrName, q); + } + finally + { + maxRequests.Release(); + } } } } diff --git a/backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs b/backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs index 5252fe795..be08eb1db 100644 --- a/backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs +++ b/backend/src/Squidex.Infrastructure/Assets/ImageSharp/ImageSharpAssetThumbnailGenerator.cs @@ -24,7 +24,7 @@ namespace Squidex.Infrastructure.Assets.ImageSharp { public sealed class ImageSharpAssetThumbnailGenerator : IAssetThumbnailGenerator { - private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(Math.Max(Environment.ProcessorCount / 4, 1)); + private readonly SemaphoreSlim maxTasks = new SemaphoreSlim(Math.Max(Environment.ProcessorCount / 4, 1)); public async Task CreateThumbnailAsync(Stream source, Stream destination, ResizeOptions options) { @@ -42,8 +42,7 @@ namespace Squidex.Infrastructure.Assets.ImageSharp var w = options.Width ?? 0; var h = options.Height ?? 0; - await semaphoreSlim.WaitAsync(); - + await maxTasks.WaitAsync(); try { using (var image = Image.Load(source, out var format)) @@ -89,7 +88,7 @@ namespace Squidex.Infrastructure.Assets.ImageSharp } finally { - semaphoreSlim.Release(); + maxTasks.Release(); } } @@ -156,8 +155,7 @@ namespace Squidex.Infrastructure.Assets.ImageSharp Guard.NotNull(source, nameof(source)); Guard.NotNull(destination, nameof(destination)); - await semaphoreSlim.WaitAsync(); - + await maxTasks.WaitAsync(); try { using (var image = Image.Load(source, out var format)) @@ -178,7 +176,7 @@ namespace Squidex.Infrastructure.Assets.ImageSharp } finally { - semaphoreSlim.Release(); + maxTasks.Release(); } }