From 1feae0de5407a1c5344e59555cc443093c52a014 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 12 May 2018 17:34:51 +0200 Subject: [PATCH] Performance improvements. --- .../Assets/MongoAssetRepository.cs | 2 +- .../AppProvider.cs | 22 +-- .../MongoXmlRepository.cs | 2 +- .../Caching/AsyncLocalCache.cs | 91 +++++++++++ .../Caching/HttpRequestCache.cs | 68 -------- .../{IRequestCache.cs => ILocalCache.cs} | 6 +- .../Caching/RequestCacheExtensions.cs | 4 +- .../Commands/DomainObjectGrain.cs | 7 - .../Commands/IDomainObjectGrain.cs | 2 - .../Orleans/LocalCacheFilter.cs | 33 ++++ .../Squidex.Infrastructure.csproj | 1 - src/Squidex.Infrastructure/States/IStore.cs | 2 + src/Squidex.Infrastructure/States/Store.cs | 7 + src/Squidex/Config/Domain/EntitiesServices.cs | 3 - .../Config/Domain/InfrastructureServices.cs | 4 +- src/Squidex/Config/Domain/StoreServices.cs | 4 +- src/Squidex/Config/Orleans/SiloWrapper.cs | 1 + src/Squidex/Config/Web/WebExtensions.cs | 7 + src/Squidex/Config/Web/WebServices.cs | 9 + .../Pipeline/EnforceHttpsMiddleware.cs | 8 +- src/Squidex/Pipeline/LocalCacheMiddleware.cs | 35 ++++ .../RequestLogPerformanceMiddleware.cs | 10 +- src/Squidex/WebStartup.cs | 1 + .../pages/content/content-page.component.html | 2 +- .../Caching/AsyncLocalCacheTests.cs | 127 +++++++++++++++ .../Caching/HttpRequestCacheTests.cs | 133 --------------- .../States/PersistenceEventSourcingTests.cs | 4 - .../States/PersistenceSnapshotTests.cs | 13 +- tools/Migrate_01/MigrationPath.cs | 40 ++--- tools/Migrate_01/Migrations/AddPatterns.cs | 2 - .../Migrations/DeleteArchiveCollection.cs | 32 ---- ...onSetup.cs => DeleteContentCollections.cs} | 11 +- .../Migrate_01/Migrations/RebuildSnapshots.cs | 4 +- tools/Migrate_01/Rebuilder.cs | 154 +++++++----------- 34 files changed, 440 insertions(+), 411 deletions(-) create mode 100644 src/Squidex.Infrastructure/Caching/AsyncLocalCache.cs delete mode 100644 src/Squidex.Infrastructure/Caching/HttpRequestCache.cs rename src/Squidex.Infrastructure/Caching/{IRequestCache.cs => ILocalCache.cs} (86%) create mode 100644 src/Squidex.Infrastructure/Orleans/LocalCacheFilter.cs create mode 100644 src/Squidex/Pipeline/LocalCacheMiddleware.cs create mode 100644 tests/Squidex.Infrastructure.Tests/Caching/AsyncLocalCacheTests.cs delete mode 100644 tests/Squidex.Infrastructure.Tests/Caching/HttpRequestCacheTests.cs delete mode 100644 tools/Migrate_01/Migrations/DeleteArchiveCollection.cs rename tools/Migrate_01/Migrations/{DeleteArchiveCollectionSetup.cs => DeleteContentCollections.cs} (62%) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index 737c7288c..c7b8e58e6 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -84,7 +84,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets public async Task> QueryAsync(Guid appId, HashSet ids) { - var find = Collection.Find(Filter.In(x => x.Id, ids)).SortByDescending(x => x.LastModified); + var find = Collection.Find(x => ids.Contains(x.Id)).SortByDescending(x => x.LastModified); var assetItems = find.ToListAsync(); var assetCount = find.CountAsync(); diff --git a/src/Squidex.Domain.Apps.Entities/AppProvider.cs b/src/Squidex.Domain.Apps.Entities/AppProvider.cs index f7ada02c3..1a34f532b 100644 --- a/src/Squidex.Domain.Apps.Entities/AppProvider.cs +++ b/src/Squidex.Domain.Apps.Entities/AppProvider.cs @@ -23,20 +23,20 @@ namespace Squidex.Domain.Apps.Entities public sealed class AppProvider : IAppProvider { private readonly IGrainFactory grainFactory; - private readonly IRequestCache requestCache; + private readonly ILocalCache localCache; - public AppProvider(IGrainFactory grainFactory, IRequestCache requestCache) + public AppProvider(IGrainFactory grainFactory, ILocalCache localCache) { Guard.NotNull(grainFactory, nameof(grainFactory)); - Guard.NotNull(requestCache, nameof(requestCache)); + Guard.NotNull(localCache, nameof(localCache)); this.grainFactory = grainFactory; - this.requestCache = requestCache; + this.localCache = localCache; } public Task<(IAppEntity, ISchemaEntity)> GetAppWithSchemaAsync(Guid appId, Guid id) { - return requestCache.GetOrCreateAsync($"GetAppWithSchemaAsync({appId}, {id})", async () => + return localCache.GetOrCreateAsync($"GetAppWithSchemaAsync({appId}, {id})", async () => { using (Profile.Method()) { @@ -61,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities public Task GetAppAsync(string appName) { - return requestCache.GetOrCreateAsync($"GetAppAsync({appName})", async () => + return localCache.GetOrCreateAsync($"GetAppAsync({appName})", async () => { using (Profile.Method()) { @@ -86,7 +86,7 @@ namespace Squidex.Domain.Apps.Entities public Task GetSchemaAsync(Guid appId, string name) { - return requestCache.GetOrCreateAsync($"GetSchemaAsync({appId}, {name})", async () => + return localCache.GetOrCreateAsync($"GetSchemaAsync({appId}, {name})", async () => { using (Profile.Method()) { @@ -104,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities public Task GetSchemaAsync(Guid appId, Guid id, bool allowDeleted = false) { - return requestCache.GetOrCreateAsync($"GetSchemaAsync({appId}, {id}, {allowDeleted})", async () => + return localCache.GetOrCreateAsync($"GetSchemaAsync({appId}, {id}, {allowDeleted})", async () => { using (Profile.Method()) { @@ -122,7 +122,7 @@ namespace Squidex.Domain.Apps.Entities public Task> GetSchemasAsync(Guid appId) { - return requestCache.GetOrCreateAsync($"GetSchemasAsync({appId})", async () => + return localCache.GetOrCreateAsync($"GetSchemasAsync({appId})", async () => { using (Profile.Method()) { @@ -139,7 +139,7 @@ namespace Squidex.Domain.Apps.Entities public Task> GetRulesAsync(Guid appId) { - return requestCache.GetOrCreateAsync($"GetRulesAsync({appId})", async () => + return localCache.GetOrCreateAsync($"GetRulesAsync({appId})", async () => { using (Profile.Method()) { @@ -156,7 +156,7 @@ namespace Squidex.Domain.Apps.Entities public Task> GetUserApps(string userId) { - return requestCache.GetOrCreateAsync($"GetUserApps({userId})", async () => + return localCache.GetOrCreateAsync($"GetUserApps({userId})", async () => { using (Profile.Method()) { diff --git a/src/Squidex.Domain.Users.MongoDb/MongoXmlRepository.cs b/src/Squidex.Domain.Users.MongoDb/MongoXmlRepository.cs index b57c58d53..b1d264b58 100644 --- a/src/Squidex.Domain.Users.MongoDb/MongoXmlRepository.cs +++ b/src/Squidex.Domain.Users.MongoDb/MongoXmlRepository.cs @@ -36,7 +36,7 @@ namespace Squidex.Domain.Users.MongoDb public void StoreElement(XElement element, string friendlyName) { - Collection.UpdateOne(Filter.Eq(x => x.Id, friendlyName), + Collection.UpdateOne(x => x.Id == friendlyName, Update.Set(x => x.Xml, element.ToString()), Upsert); } diff --git a/src/Squidex.Infrastructure/Caching/AsyncLocalCache.cs b/src/Squidex.Infrastructure/Caching/AsyncLocalCache.cs new file mode 100644 index 000000000..7156a6c06 --- /dev/null +++ b/src/Squidex.Infrastructure/Caching/AsyncLocalCache.cs @@ -0,0 +1,91 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Concurrent; +using System.Threading; + +namespace Squidex.Infrastructure.Caching +{ + public sealed class AsyncLocalCache : ILocalCache + { + private static readonly AsyncLocal> Cache = new AsyncLocal>(); + private static readonly AsyncLocalCleaner Cleaner; + + private sealed class AsyncLocalCleaner : IDisposable + { + private readonly AsyncLocal> cache; + + public AsyncLocalCleaner(AsyncLocal> cache) + { + this.cache = cache; + } + + public void Dispose() + { + cache.Value = null; + } + } + + static AsyncLocalCache() + { + Cleaner = new AsyncLocalCleaner(Cache); + } + + public IDisposable StartContext() + { + Cache.Value = new ConcurrentDictionary(); + + return Cleaner; + } + + public void Add(object key, object value) + { + var cacheKey = GetCacheKey(key); + + var cache = Cache.Value; + + if (cache != null) + { + cache[cacheKey] = value; + } + } + + public void Remove(object key) + { + var cacheKey = GetCacheKey(key); + + var cache = Cache.Value; + + if (cache != null) + { + cache.TryRemove(cacheKey, out var value); + } + } + + public bool TryGetValue(object key, out object value) + { + var cacheKey = GetCacheKey(key); + + var cache = Cache.Value; + + if (cache != null) + { + return cache.TryGetValue(cacheKey, out value); + } + + value = null; + + return false; + } + + private static string GetCacheKey(object key) + { + return $"CACHE_{key}"; + } + } +} diff --git a/src/Squidex.Infrastructure/Caching/HttpRequestCache.cs b/src/Squidex.Infrastructure/Caching/HttpRequestCache.cs deleted file mode 100644 index 3c21de6bb..000000000 --- a/src/Squidex.Infrastructure/Caching/HttpRequestCache.cs +++ /dev/null @@ -1,68 +0,0 @@ -// ========================================================================== -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex UG (haftungsbeschraenkt) -// All rights reserved. Licensed under the MIT license. -// ========================================================================== - -using Microsoft.AspNetCore.Http; - -namespace Squidex.Infrastructure.Caching -{ - public sealed class HttpRequestCache : IRequestCache - { - private readonly IHttpContextAccessor httpContextAccessor; - - public HttpRequestCache(IHttpContextAccessor httpContextAccessor) - { - Guard.NotNull(httpContextAccessor, nameof(httpContextAccessor)); - - this.httpContextAccessor = httpContextAccessor; - } - - public void Add(object key, object value) - { - var cacheKey = GetCacheKey(key); - - var items = httpContextAccessor.HttpContext?.Items; - - if (items != null) - { - items[cacheKey] = value; - } - } - - public void Remove(object key) - { - var cacheKey = GetCacheKey(key); - - var items = httpContextAccessor.HttpContext?.Items; - - if (items != null) - { - items?.Remove(cacheKey); - } - } - - public bool TryGetValue(object key, out object value) - { - var cacheKey = GetCacheKey(key); - - var items = httpContextAccessor.HttpContext?.Items; - - if (items != null) - { - return items.TryGetValue(cacheKey, out value); - } - - value = null; - - return false; - } - - private static string GetCacheKey(object key) - { - return $"CACHE_{key}"; - } - } -} diff --git a/src/Squidex.Infrastructure/Caching/IRequestCache.cs b/src/Squidex.Infrastructure/Caching/ILocalCache.cs similarity index 86% rename from src/Squidex.Infrastructure/Caching/IRequestCache.cs rename to src/Squidex.Infrastructure/Caching/ILocalCache.cs index b6bb6aaf1..5eec26296 100644 --- a/src/Squidex.Infrastructure/Caching/IRequestCache.cs +++ b/src/Squidex.Infrastructure/Caching/ILocalCache.cs @@ -5,10 +5,14 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; + namespace Squidex.Infrastructure.Caching { - public interface IRequestCache + public interface ILocalCache { + IDisposable StartContext(); + void Add(object key, object value); void Remove(object key); diff --git a/src/Squidex.Infrastructure/Caching/RequestCacheExtensions.cs b/src/Squidex.Infrastructure/Caching/RequestCacheExtensions.cs index 0523b9c54..2a3d6ed8c 100644 --- a/src/Squidex.Infrastructure/Caching/RequestCacheExtensions.cs +++ b/src/Squidex.Infrastructure/Caching/RequestCacheExtensions.cs @@ -12,7 +12,7 @@ namespace Squidex.Infrastructure.Caching { public static class RequestCacheExtensions { - public static async Task GetOrCreateAsync(this IRequestCache cache, object key, Func> task) + public static async Task GetOrCreateAsync(this ILocalCache cache, object key, Func> task) { if (cache.TryGetValue(key, out var value) && value is T typedValue) { @@ -26,7 +26,7 @@ namespace Squidex.Infrastructure.Caching return typedValue; } - public static T GetOrCreate(this IRequestCache cache, object key, Func task) + public static T GetOrCreate(this ILocalCache cache, object key, Func task) { if (cache.TryGetValue(key, out var value) && value is T typedValue) { diff --git a/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs b/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs index 20892810a..91beac110 100644 --- a/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs +++ b/src/Squidex.Infrastructure/Commands/DomainObjectGrain.cs @@ -105,13 +105,6 @@ namespace Squidex.Infrastructure.Commands { } - public Task WriteSnapshotAsync() - { - snapshot.Version = persistence.Version; - - return persistence.WriteSnapshotAsync(snapshot); - } - protected Task CreateReturnAsync(TCommand command, Func> handler) where TCommand : class, IAggregateCommand { return InvokeAsync(command, handler, false); diff --git a/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs b/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs index 500db0245..f52ce2122 100644 --- a/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs +++ b/src/Squidex.Infrastructure/Commands/IDomainObjectGrain.cs @@ -13,8 +13,6 @@ namespace Squidex.Infrastructure.Commands { public interface IDomainObjectGrain : IGrainWithGuidKey { - Task WriteSnapshotAsync(); - Task> ExecuteAsync(J command); } } diff --git a/src/Squidex.Infrastructure/Orleans/LocalCacheFilter.cs b/src/Squidex.Infrastructure/Orleans/LocalCacheFilter.cs new file mode 100644 index 000000000..7a49d31cf --- /dev/null +++ b/src/Squidex.Infrastructure/Orleans/LocalCacheFilter.cs @@ -0,0 +1,33 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Threading.Tasks; +using Orleans; +using Squidex.Infrastructure.Caching; + +namespace Squidex.Infrastructure.Orleans +{ + public sealed class LocalCacheFilter : IIncomingGrainCallFilter + { + private readonly ILocalCache localCache; + + public LocalCacheFilter(ILocalCache localCache) + { + Guard.NotNull(localCache, nameof(localCache)); + + this.localCache = localCache; + } + + public async Task Invoke(IIncomingGrainCallContext context) + { + using (localCache.StartContext()) + { + await context.Invoke(); + } + } + } +} diff --git a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj index 5da83c8bf..96dcbebf2 100644 --- a/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj +++ b/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj @@ -8,7 +8,6 @@ True - diff --git a/src/Squidex.Infrastructure/States/IStore.cs b/src/Squidex.Infrastructure/States/IStore.cs index 1ba437fde..e1e1101bd 100644 --- a/src/Squidex.Infrastructure/States/IStore.cs +++ b/src/Squidex.Infrastructure/States/IStore.cs @@ -18,5 +18,7 @@ namespace Squidex.Infrastructure.States IPersistence WithSnapshots(Type owner, TKey key, Func applySnapshot); IPersistence WithSnapshotsAndEventSourcing(Type owner, TKey key, Func applySnapshot, Func, Task> applyEvent); + + Task ClearSnapshotsAsync(); } } diff --git a/src/Squidex.Infrastructure/States/Store.cs b/src/Squidex.Infrastructure/States/Store.cs index 3a010d3ed..461c443fb 100644 --- a/src/Squidex.Infrastructure/States/Store.cs +++ b/src/Squidex.Infrastructure/States/Store.cs @@ -57,5 +57,12 @@ namespace Squidex.Infrastructure.States return new Persistence(key, owner, eventStore, eventDataFormatter, snapshotStore, streamNameResolver, mode, applySnapshot, applyEvent); } + + public Task ClearSnapshotsAsync() + { + var snapshotStore = (ISnapshotStore)services.GetService(typeof(ISnapshotStore)); + + return snapshotStore.ClearAsync(); + } } } diff --git a/src/Squidex/Config/Domain/EntitiesServices.cs b/src/Squidex/Config/Domain/EntitiesServices.cs index 854457911..48804c635 100644 --- a/src/Squidex/Config/Domain/EntitiesServices.cs +++ b/src/Squidex/Config/Domain/EntitiesServices.cs @@ -172,9 +172,6 @@ namespace Squidex.Config.Domain services.AddTransientAs() .As(); - services.AddTransientAs() - .As(); - services.AddTransientAs() .As(); diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index deccd4b66..e4a223a5c 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -32,8 +32,8 @@ namespace Squidex.Config.Domain services.AddSingletonAs(c => new CachingUsageTracker(c.GetRequiredService(), c.GetRequiredService())) .As(); - services.AddSingletonAs() - .As(); + services.AddSingletonAs() + .As(); services.AddSingletonAs() .As(); diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index 496ce0989..972d60141 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -112,10 +112,10 @@ namespace Squidex.Config.Domain .As() .As(); - services.AddTransientAs(c => new DeleteArchiveCollectionSetup(mongoContentDatabase)) + services.AddTransientAs() .As(); - services.AddTransientAs() + services.AddTransientAs(c => new DeleteContentCollections(mongoContentDatabase)) .As(); } }); diff --git a/src/Squidex/Config/Orleans/SiloWrapper.cs b/src/Squidex/Config/Orleans/SiloWrapper.cs index 96a110c08..0c739a051 100644 --- a/src/Squidex/Config/Orleans/SiloWrapper.cs +++ b/src/Squidex/Config/Orleans/SiloWrapper.cs @@ -55,6 +55,7 @@ namespace Squidex.Config.Orleans { var hostBuilder = new SiloHostBuilder() .UseDashboard(options => options.HostSelf = false) + .AddIncomingGrainCallFilter() .AddStartupTask>() .AddStartupTask>() .AddStartupTask>() diff --git a/src/Squidex/Config/Web/WebExtensions.cs b/src/Squidex/Config/Web/WebExtensions.cs index 744b6adf3..50e4ce74f 100644 --- a/src/Squidex/Config/Web/WebExtensions.cs +++ b/src/Squidex/Config/Web/WebExtensions.cs @@ -13,6 +13,13 @@ namespace Squidex.Config.Web { public static class WebExtensions { + public static IApplicationBuilder UseMyLocalCache(this IApplicationBuilder app) + { + app.UseMiddleware(); + + return app; + } + public static IApplicationBuilder UseMyTracking(this IApplicationBuilder app) { app.UseMiddleware(); diff --git a/src/Squidex/Config/Web/WebServices.cs b/src/Squidex/Config/Web/WebServices.cs index ec2b3a0cf..fbb865fa1 100644 --- a/src/Squidex/Config/Web/WebServices.cs +++ b/src/Squidex/Config/Web/WebServices.cs @@ -24,6 +24,15 @@ namespace Squidex.Config.Web services.AddSingletonAs() .AsSelf(); + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .AsSelf(); + services.AddMvc().AddMySerializers(); services.AddCors(); services.AddRouting(); diff --git a/src/Squidex/Pipeline/EnforceHttpsMiddleware.cs b/src/Squidex/Pipeline/EnforceHttpsMiddleware.cs index 5cbc5efbe..4f4c6158e 100644 --- a/src/Squidex/Pipeline/EnforceHttpsMiddleware.cs +++ b/src/Squidex/Pipeline/EnforceHttpsMiddleware.cs @@ -13,18 +13,16 @@ using Squidex.Config; namespace Squidex.Pipeline { - public sealed class EnforceHttpsMiddleware + public sealed class EnforceHttpsMiddleware : IMiddleware { - private readonly RequestDelegate next; private readonly IOptions urls; - public EnforceHttpsMiddleware(RequestDelegate next, IOptions urls) + public EnforceHttpsMiddleware(IOptions urls) { - this.next = next; this.urls = urls; } - public async Task Invoke(HttpContext context) + public async Task InvokeAsync(HttpContext context, RequestDelegate next) { if (!urls.Value.EnforceHTTPS) { diff --git a/src/Squidex/Pipeline/LocalCacheMiddleware.cs b/src/Squidex/Pipeline/LocalCacheMiddleware.cs new file mode 100644 index 000000000..52567997a --- /dev/null +++ b/src/Squidex/Pipeline/LocalCacheMiddleware.cs @@ -0,0 +1,35 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Squidex.Infrastructure; +using Squidex.Infrastructure.Caching; + +namespace Squidex.Pipeline +{ + public sealed class LocalCacheMiddleware : IMiddleware + { + private readonly ILocalCache localCache; + + public LocalCacheMiddleware(ILocalCache localCache) + { + Guard.NotNull(localCache, nameof(localCache)); + + this.localCache = localCache; + } + + public async Task InvokeAsync(HttpContext context, RequestDelegate next) + { + using (localCache.StartContext()) + { + await next(context); + } + } + } +} diff --git a/src/Squidex/Pipeline/RequestLogPerformanceMiddleware.cs b/src/Squidex/Pipeline/RequestLogPerformanceMiddleware.cs index 76c381b13..e7afe2c16 100644 --- a/src/Squidex/Pipeline/RequestLogPerformanceMiddleware.cs +++ b/src/Squidex/Pipeline/RequestLogPerformanceMiddleware.cs @@ -8,25 +8,23 @@ using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Filters; using Squidex.Infrastructure.Log; namespace Squidex.Pipeline { - public sealed class RequestLogPerformanceMiddleware : ActionFilterAttribute + public sealed class RequestLogPerformanceMiddleware : IMiddleware { private readonly RequestLogProfilerSessionProvider requestSession; - private readonly RequestDelegate next; private readonly ISemanticLog log; - public RequestLogPerformanceMiddleware(RequestLogProfilerSessionProvider requestSession, RequestDelegate next, ISemanticLog log) + public RequestLogPerformanceMiddleware(RequestLogProfilerSessionProvider requestSession, ISemanticLog log) { this.requestSession = requestSession; - this.next = next; + this.log = log; } - public async Task Invoke(HttpContext context) + public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var stopWatch = Stopwatch.StartNew(); diff --git a/src/Squidex/WebStartup.cs b/src/Squidex/WebStartup.cs index 7b2188fec..3e6baa3e3 100644 --- a/src/Squidex/WebStartup.cs +++ b/src/Squidex/WebStartup.cs @@ -46,6 +46,7 @@ namespace Squidex app.ApplicationServices.RunMigrate(); app.ApplicationServices.RunRunnables(); + app.UseMyLocalCache(); app.UseMyCors(); app.UseMyForwardingRules(); app.UseMyTracking(); diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.html b/src/Squidex/app/features/content/pages/content/content-page.component.html index c119b7849..83b038a5e 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.html +++ b/src/Squidex/app/features/content/pages/content/content-page.component.html @@ -81,7 +81,7 @@