Browse Source

Reduce allocations.

pull/470/head
Sebastian 6 years ago
parent
commit
bbdfaef00f
  1. 5
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs
  2. 6
      backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs
  3. 7
      backend/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InviteUserCommandMiddleware.cs
  4. 5
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/AlwaysCreateClientCommandMiddleware.cs
  5. 4
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs
  6. 4
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateIdentityCommandMiddleware.cs
  7. 4
      backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs
  8. 7
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs
  9. 4
      backend/src/Squidex.Domain.Apps.Entities/Comments/CommentsCommandMiddleware.cs
  10. 3
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs
  11. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/SingletonCommandMiddleware.cs
  12. 4
      backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs
  13. 3
      backend/src/Squidex.Domain.Apps.Entities/Rules/RuleCommandMiddleware.cs
  14. 5
      backend/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerCommandMiddleware.cs
  15. 6
      backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs
  16. 1
      backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs
  17. 2
      backend/src/Squidex.Infrastructure/Commands/CommandExtensions.cs
  18. 10
      backend/src/Squidex.Infrastructure/Commands/CustomCommandMiddlewareRunner.cs
  19. 5
      backend/src/Squidex.Infrastructure/Commands/EnrichWithTimestampCommandMiddleware.cs
  20. 5
      backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs
  21. 5
      backend/src/Squidex.Infrastructure/Commands/ICommandMiddleware.cs
  22. 57
      backend/src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs
  23. 4
      backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs
  24. 5
      backend/src/Squidex.Infrastructure/Commands/ReadonlyCommandMiddleware.cs
  25. 6
      backend/src/Squidex.Web/CommandMiddlewares/ETagCommandMiddleware.cs
  26. 7
      backend/src/Squidex.Web/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs
  27. 4
      backend/src/Squidex.Web/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs
  28. 6
      backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs
  29. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Comments/CommentsCommandMiddlewareTests.cs
  30. 7
      backend/tests/Squidex.Infrastructure.Tests/Commands/CustomCommandMiddlewareRunnerTests.cs
  31. 6
      backend/tests/Squidex.Infrastructure.Tests/Commands/InMemoryCommandBusTests.cs
  32. 6
      backend/tests/Squidex.Infrastructure.Tests/Commands/LogCommandMiddlewareTests.cs
  33. 2
      backend/tests/Squidex.Infrastructure.Tests/Commands/ReadonlyCommandMiddlewareTests.cs

5
backend/src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Domain.Apps.Entities.Apps.Commands;
@ -38,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
this.contextProvider = contextProvider; this.contextProvider = contextProvider;
} }
public override async Task HandleAsync(CommandContext context, Func<Task> next) public override async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is UploadAppImage uploadImage) if (context.Command is UploadAppImage uploadImage)
{ {
@ -52,7 +51,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
contextProvider.Context.App = app; contextProvider.Context.App = app;
} }
await next(); await next(context);
} }
private async Task UploadAsync(UploadAppImage uploadImage) private async Task UploadAsync(UploadAppImage uploadImage)

6
backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs

@ -164,7 +164,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
} }
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is CreateApp createApp) if (context.Command is CreateApp createApp)
{ {
@ -174,7 +174,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
try try
{ {
await next(); await next(context);
} }
finally finally
{ {
@ -195,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
} }
else else
{ {
await next(); await next(context);
if (context.IsCompleted) if (context.IsCompleted)
{ {

7
backend/src/Squidex.Domain.Apps.Entities/Apps/Invitation/InviteUserCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -25,13 +24,13 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation
this.userResolver = userResolver; this.userResolver = userResolver;
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is AssignContributor assignContributor && ShouldInvite(assignContributor)) if (context.Command is AssignContributor assignContributor && ShouldInvite(assignContributor))
{ {
var created = await userResolver.CreateUserIfNotExistsAsync(assignContributor.ContributorId, true); var created = await userResolver.CreateUserIfNotExistsAsync(assignContributor.ContributorId, true);
await next(); await next(context);
if (created && context.PlainResult is IAppEntity app) if (created && context.PlainResult is IAppEntity app)
{ {
@ -40,7 +39,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Invitation
} }
else else
{ {
await next(); await next(context);
} }
} }

5
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/AlwaysCreateClientCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
@ -15,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
public sealed class AlwaysCreateClientCommandMiddleware : ICommandMiddleware public sealed class AlwaysCreateClientCommandMiddleware : ICommandMiddleware
{ {
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.IsCompleted && context.Command is CreateApp createApp) if (context.IsCompleted && context.Command is CreateApp createApp)
{ {
@ -24,7 +23,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
context.CommandBus.PublishAsync(command).Forget(); context.CommandBus.PublishAsync(command).Forget();
} }
return next(); return next(context);
} }
} }
} }

4
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
private const string TemplateName = "Blog"; private const string TemplateName = "Blog";
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp)) if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp))
{ {
@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
CreatePostsAsync(publish)); CreatePostsAsync(publish));
} }
await next(); await next(context);
} }
private static bool IsRightTemplate(CreateApp createApp) private static bool IsRightTemplate(CreateApp createApp)

4
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateIdentityCommandMiddleware.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
private const string TemplateName = "Identity"; private const string TemplateName = "Identity";
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp)) if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp))
{ {
@ -43,7 +43,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
CreateUsersSchemaAsync(publish)); CreateUsersSchemaAsync(publish));
} }
await next(); await next(context);
} }
private static bool IsRightTemplate(CreateApp createApp) private static bool IsRightTemplate(CreateApp createApp)

4
backend/src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateProfileCommandMiddleware.cs

@ -20,7 +20,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
{ {
private const string TemplateName = "Profile"; private const string TemplateName = "Profile";
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp)) if (context.IsCompleted && context.Command is CreateApp createApp && IsRightTemplate(createApp))
{ {
@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
CreateSkillsSchemaAsync(publish)); CreateSkillsSchemaAsync(publish));
} }
await next(); await next(context);
} }
private static bool IsRightTemplate(CreateApp createApp) private static bool IsRightTemplate(CreateApp createApp)

7
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -47,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
this.assetMetadataSources = assetMetadataSources; this.assetMetadataSources = assetMetadataSources;
} }
public override async Task HandleAsync(CommandContext context, Func<Task> next) public override async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
var tempFile = context.ContextId.ToString(); var tempFile = context.ContextId.ToString();
@ -71,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
context.Complete(result); context.Complete(result);
await next(); await next(context);
return; return;
} }
} }
@ -121,7 +120,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
} }
} }
private async Task HandleCoreAsync(CommandContext context, Func<Task> next) private async Task HandleCoreAsync(CommandContext context, NextDelegate next)
{ {
await base.HandleAsync(context, next); await base.HandleAsync(context, next);

4
backend/src/Squidex.Domain.Apps.Entities/Comments/CommentsCommandMiddleware.cs

@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.Comments
this.userResolver = userResolver; this.userResolver = userResolver;
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is CommentsCommand commentsCommand) if (context.Command is CommentsCommand commentsCommand)
{ {
@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Entities.Comments
await ExecuteCommandAsync(context, commentsCommand); await ExecuteCommandAsync(context, commentsCommand);
} }
await next(); await next(context);
} }
private async Task ExecuteCommandAsync(CommandContext context, CommentsCommand commentsCommand) private async Task ExecuteCommandAsync(CommandContext context, CommentsCommand commentsCommand)

3
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.Commands;
@ -29,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
this.contextProvider = contextProvider; this.contextProvider = contextProvider;
} }
public override async Task HandleAsync(CommandContext context, Func<Task> next) public override async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
await base.HandleAsync(context, next); await base.HandleAsync(context, next);

5
backend/src/Squidex.Domain.Apps.Entities/Contents/SingletonCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Contents.Commands; using Squidex.Domain.Apps.Entities.Contents.Commands;
@ -18,9 +17,9 @@ namespace Squidex.Domain.Apps.Entities.Contents
{ {
public sealed class SingletonCommandMiddleware : ICommandMiddleware public sealed class SingletonCommandMiddleware : ICommandMiddleware
{ {
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
await next(); await next(context);
if (context.IsCompleted && if (context.IsCompleted &&
context.Command is CreateSchema createSchema && context.Command is CreateSchema createSchema &&

4
backend/src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesIndex.cs

@ -70,9 +70,9 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
} }
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
await next(); await next(context);
if (context.IsCompleted) if (context.IsCompleted)
{ {

3
backend/src/Squidex.Domain.Apps.Entities/Rules/RuleCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
using Squidex.Domain.Apps.Entities.Rules.Commands; using Squidex.Domain.Apps.Entities.Rules.Commands;
@ -30,7 +29,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
this.contextProvider = contextProvider; this.contextProvider = contextProvider;
} }
public override async Task HandleAsync(CommandContext context, Func<Task> next) public override async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
await base.HandleAsync(context, next); await base.HandleAsync(context, next);

5
backend/src/Squidex.Domain.Apps.Entities/Rules/UsageTracking/UsageTrackerCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
using Squidex.Domain.Apps.Core.Rules.Triggers; using Squidex.Domain.Apps.Core.Rules.Triggers;
@ -27,7 +26,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking
usageTrackerGrain = grainFactory.GetGrain<IUsageTrackerGrain>(SingleGrain.Id); usageTrackerGrain = grainFactory.GetGrain<IUsageTrackerGrain>(SingleGrain.Id);
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
switch (context.Command) switch (context.Command)
{ {
@ -55,7 +54,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.UsageTracking
} }
} }
await next(); await next(context);
} }
} }
} }

6
backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs

@ -94,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
} }
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is CreateSchema createSchema) if (context.Command is CreateSchema createSchema)
{ {
@ -104,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
try try
{ {
await next(); await next(context);
} }
finally finally
{ {
@ -123,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
} }
else else
{ {
await next(); await next(context);
if (context.IsCompleted) if (context.IsCompleted)
{ {

1
backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Threading; using System.Threading;

2
backend/src/Squidex.Infrastructure/Commands/CommandExtensions.cs

@ -14,7 +14,7 @@ namespace Squidex.Infrastructure.Commands
{ {
public static Task HandleAsync(this ICommandMiddleware commandMiddleware, CommandContext context) public static Task HandleAsync(this ICommandMiddleware commandMiddleware, CommandContext context)
{ {
return commandMiddleware.HandleAsync(context, () => TaskHelper.Done); return commandMiddleware.HandleAsync(context, x => TaskHelper.Done);
} }
} }
} }

10
backend/src/Squidex.Infrastructure/Commands/CustomCommandMiddlewareRunner.cs

@ -23,19 +23,19 @@ namespace Squidex.Infrastructure.Commands
this.extensions = extensions.Reverse().ToList(); this.extensions = extensions.Reverse().ToList();
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
foreach (var handler in extensions) foreach (var handler in extensions)
{ {
next = Join(handler, context, next); next = Join(handler, next);
} }
await next(); await next(context);
} }
private static Func<Task> Join(ICommandMiddleware handler, CommandContext context, Func<Task> next) private static NextDelegate Join(ICommandMiddleware handler, NextDelegate next)
{ {
return () => handler.HandleAsync(context, next); return context => handler.HandleAsync(context, next);
} }
} }
} }

5
backend/src/Squidex.Infrastructure/Commands/EnrichWithTimestampCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using NodaTime; using NodaTime;
@ -22,14 +21,14 @@ namespace Squidex.Infrastructure.Commands
this.clock = clock; this.clock = clock;
} }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is ITimestampCommand timestampCommand) if (context.Command is ITimestampCommand timestampCommand)
{ {
timestampCommand.Timestamp = clock.GetCurrentInstant(); timestampCommand.Timestamp = clock.GetCurrentInstant();
} }
return next(); return next(context);
} }
} }
} }

5
backend/src/Squidex.Infrastructure/Commands/GrainCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Orleans; using Orleans;
@ -22,11 +21,11 @@ namespace Squidex.Infrastructure.Commands
this.grainFactory = grainFactory; this.grainFactory = grainFactory;
} }
public virtual async Task HandleAsync(CommandContext context, Func<Task> next) public virtual async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
await ExecuteCommandAsync(context); await ExecuteCommandAsync(context);
await next(); await next(context);
} }
protected async Task ExecuteCommandAsync(CommandContext context) protected async Task ExecuteCommandAsync(CommandContext context)

5
backend/src/Squidex.Infrastructure/Commands/ICommandMiddleware.cs

@ -5,13 +5,14 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Squidex.Infrastructure.Commands namespace Squidex.Infrastructure.Commands
{ {
public delegate Task NextDelegate(CommandContext context);
public interface ICommandMiddleware public interface ICommandMiddleware
{ {
Task HandleAsync(CommandContext context, Func<Task> next); Task HandleAsync(CommandContext context, NextDelegate next);
} }
} }

57
backend/src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs

@ -9,42 +9,69 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Infrastructure.Commands namespace Squidex.Infrastructure.Commands
{ {
public sealed class InMemoryCommandBus : ICommandBus public sealed class InMemoryCommandBus : ICommandBus
{ {
private readonly List<ICommandMiddleware> middlewares; private readonly IStep pipeline;
public InMemoryCommandBus(IEnumerable<ICommandMiddleware> middlewares) private interface IStep
{ {
Guard.NotNull(middlewares); Task InvokeAsync(CommandContext context);
}
this.middlewares = middlewares.Reverse().ToList(); private class NoopStep : IStep
{
public Task InvokeAsync(CommandContext context)
{
return Task.CompletedTask;
}
} }
public async Task<CommandContext> PublishAsync(ICommand command) private class DefaultStep : IStep
{ {
Guard.NotNull(command); private readonly IStep next;
private readonly ICommandMiddleware middleware;
var context = new CommandContext(command, this); public DefaultStep(ICommandMiddleware middleware, IStep next)
{
this.middleware = middleware;
var next = new Func<Task>(() => TaskHelper.Done); this.next = next;
}
foreach (var handler in middlewares) public Task InvokeAsync(CommandContext context)
{ {
next = Join(handler, context, next); return middleware.HandleAsync(context, next.InvokeAsync);
} }
}
public InMemoryCommandBus(IEnumerable<ICommandMiddleware> middlewares)
{
Guard.NotNull(middlewares);
await next(); var reverseMiddlewares = middlewares.Reverse().ToList();
return context; IStep next = new NoopStep();
foreach (var middleware in reverseMiddlewares)
{
next = new DefaultStep(middleware, next);
}
pipeline = next;
} }
private static Func<Task> Join(ICommandMiddleware handler, CommandContext context, Func<Task> next) public async Task<CommandContext> PublishAsync(ICommand command)
{ {
return () => handler.HandleAsync(context, next); Guard.NotNull(command);
var context = new CommandContext(command, this);
await pipeline.InvokeAsync(context);
return context;
} }
} }
} }

4
backend/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs

@ -22,7 +22,7 @@ namespace Squidex.Infrastructure.Commands
this.log = log; this.log = log;
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
var logContext = (id: context.ContextId.ToString(), command: context.Command.GetType().Name); var logContext = (id: context.ContextId.ToString(), command: context.Command.GetType().Name);
@ -40,7 +40,7 @@ namespace Squidex.Infrastructure.Commands
.WriteProperty("status", "Completed") .WriteProperty("status", "Completed")
.WriteProperty("commandType", ctx.command))) .WriteProperty("commandType", ctx.command)))
{ {
await next(); await next(context);
} }
log.LogInformation(logContext, (ctx, w) => w log.LogInformation(logContext, (ctx, w) => w

5
backend/src/Squidex.Infrastructure/Commands/ReadonlyCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -22,14 +21,14 @@ namespace Squidex.Infrastructure.Commands
this.options = options.Value; this.options = options.Value;
} }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (options.IsReadonly) if (options.IsReadonly)
{ {
throw new DomainException("Application is in readonly mode at the moment."); throw new DomainException("Application is in readonly mode at the moment.");
} }
return next(); return next(context);
} }
} }
} }

6
backend/src/Squidex.Web/CommandMiddlewares/ETagCommandMiddleware.cs

@ -25,13 +25,13 @@ namespace Squidex.Web.CommandMiddlewares
this.httpContextAccessor = httpContextAccessor; this.httpContextAccessor = httpContextAccessor;
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
var httpContext = httpContextAccessor.HttpContext; var httpContext = httpContextAccessor.HttpContext;
if (httpContext == null) if (httpContext == null)
{ {
await next(); await next(context);
return; return;
} }
@ -50,7 +50,7 @@ namespace Squidex.Web.CommandMiddlewares
} }
} }
await next(); await next(context);
if (context.PlainResult is EntitySavedResult result) if (context.PlainResult is EntitySavedResult result)
{ {

7
backend/src/Squidex.Web/CommandMiddlewares/EnrichWithActorCommandMiddleware.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Security; using System.Security;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -24,11 +23,11 @@ namespace Squidex.Web.CommandMiddlewares
this.httpContextAccessor = httpContextAccessor; this.httpContextAccessor = httpContextAccessor;
} }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (httpContextAccessor.HttpContext == null) if (httpContextAccessor.HttpContext == null)
{ {
return next(); return next(context);
} }
if (context.Command is SquidexCommand squidexCommand) if (context.Command is SquidexCommand squidexCommand)
@ -48,7 +47,7 @@ namespace Squidex.Web.CommandMiddlewares
} }
} }
return next(); return next(context);
} }
} }
} }

4
backend/src/Squidex.Web/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs

@ -23,7 +23,7 @@ namespace Squidex.Web.CommandMiddlewares
this.contextProvider = contextProvider; this.contextProvider = contextProvider;
} }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is IAppCommand appCommand && appCommand.AppId == null) if (context.Command is IAppCommand appCommand && appCommand.AppId == null)
{ {
@ -39,7 +39,7 @@ namespace Squidex.Web.CommandMiddlewares
appSelfCommand.AppId = appId.Id; appSelfCommand.AppId = appId.Id;
} }
return next(); return next(context);
} }
private NamedId<Guid> GetAppId() private NamedId<Guid> GetAppId()

6
backend/src/Squidex.Web/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs

@ -28,11 +28,11 @@ namespace Squidex.Web.CommandMiddlewares
this.actionContextAccessor = actionContextAccessor; this.actionContextAccessor = actionContextAccessor;
} }
public async Task HandleAsync(CommandContext context, Func<Task> next) public async Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (actionContextAccessor.ActionContext == null) if (actionContextAccessor.ActionContext == null)
{ {
await next(); await next(context);
return; return;
} }
@ -51,7 +51,7 @@ namespace Squidex.Web.CommandMiddlewares
schemaSelfCommand.SchemaId = schemaId?.Id ?? Guid.Empty; schemaSelfCommand.SchemaId = schemaId?.Id ?? Guid.Empty;
} }
await next(); await next(context);
} }
private async Task<NamedId<Guid>?> GetSchemaIdAsync(CommandContext context) private async Task<NamedId<Guid>?> GetSchemaIdAsync(CommandContext context)

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Comments/CommentsCommandMiddlewareTests.cs

@ -56,7 +56,7 @@ namespace Squidex.Domain.Apps.Entities.Comments
var isNextCalled = false; var isNextCalled = false;
await sut.HandleAsync(context, () => await sut.HandleAsync(context, c =>
{ {
isNextCalled = true; isNextCalled = true;

7
backend/tests/Squidex.Infrastructure.Tests/Commands/CustomCommandMiddlewareRunnerTests.cs

@ -5,7 +5,6 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using FakeItEasy; using FakeItEasy;
@ -31,14 +30,14 @@ namespace Squidex.Infrastructure.Commands
this.value = value; this.value = value;
} }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
if (context.Command is Command command) if (context.Command is Command command)
{ {
command.Values.Add(value); command.Values.Add(value);
} }
return next(); return next(context);
} }
} }
@ -57,7 +56,7 @@ namespace Squidex.Infrastructure.Commands
var isNextCalled = false; var isNextCalled = false;
await sut.HandleAsync(context, () => await sut.HandleAsync(context, c =>
{ {
isNextCalled = true; isNextCalled = true;

6
backend/tests/Squidex.Infrastructure.Tests/Commands/InMemoryCommandBusTests.cs

@ -21,7 +21,7 @@ namespace Squidex.Infrastructure.Commands
{ {
public ICommand LastCommand { get; private set; } public ICommand LastCommand { get; private set; }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
LastCommand = context.Command; LastCommand = context.Command;
@ -35,7 +35,7 @@ namespace Squidex.Infrastructure.Commands
{ {
public ICommand LastCommand { get; private set; } public ICommand LastCommand { get; private set; }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
LastCommand = context.Command; LastCommand = context.Command;
@ -47,7 +47,7 @@ namespace Squidex.Infrastructure.Commands
{ {
public ICommand LastCommand { get; private set; } public ICommand LastCommand { get; private set; }
public Task HandleAsync(CommandContext context, Func<Task> next) public Task HandleAsync(CommandContext context, NextDelegate next)
{ {
LastCommand = context.Command; LastCommand = context.Command;

6
backend/tests/Squidex.Infrastructure.Tests/Commands/LogCommandMiddlewareTests.cs

@ -47,7 +47,7 @@ namespace Squidex.Infrastructure.Commands
{ {
var context = new CommandContext(command, commandBus); var context = new CommandContext(command, commandBus);
await sut.HandleAsync(context, () => await sut.HandleAsync(context, c =>
{ {
context.Complete(true); context.Complete(true);
@ -68,7 +68,7 @@ namespace Squidex.Infrastructure.Commands
await Assert.ThrowsAsync<InvalidOperationException>(async () => await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{ {
await sut.HandleAsync(context, () => throw new InvalidOperationException()); await sut.HandleAsync(context, c => throw new InvalidOperationException());
}); });
Assert.Equal(log.LogLevels, new Dictionary<SemanticLogLevel, int> Assert.Equal(log.LogLevels, new Dictionary<SemanticLogLevel, int>
@ -84,7 +84,7 @@ namespace Squidex.Infrastructure.Commands
{ {
var context = new CommandContext(command, commandBus); var context = new CommandContext(command, commandBus);
await sut.HandleAsync(context, () => TaskHelper.Done); await sut.HandleAsync(context, c => TaskHelper.Done);
Assert.Equal(log.LogLevels, new Dictionary<SemanticLogLevel, int> Assert.Equal(log.LogLevels, new Dictionary<SemanticLogLevel, int>
{ {

2
backend/tests/Squidex.Infrastructure.Tests/Commands/ReadonlyCommandMiddlewareTests.cs

@ -51,7 +51,7 @@ namespace Squidex.Infrastructure.Commands
private async Task MakeCallAsync(CommandContext context) private async Task MakeCallAsync(CommandContext context)
{ {
await sut.HandleAsync(context, () => await sut.HandleAsync(context, c =>
{ {
context.Complete(true); context.Complete(true);

Loading…
Cancel
Save