|
|
|
@ -9,42 +9,69 @@ using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Linq; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Squidex.Infrastructure.Tasks; |
|
|
|
|
|
|
|
namespace Squidex.Infrastructure.Commands |
|
|
|
{ |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
} |