mirror of https://github.com/Squidex/squidex.git
25 changed files with 361 additions and 150 deletions
@ -0,0 +1,53 @@ |
|||||
|
// ==========================================================================
|
||||
|
// CompoundEventConsumer.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.Events |
||||
|
{ |
||||
|
public sealed class CompoundEventConsumer : IEventConsumer |
||||
|
{ |
||||
|
private readonly IEventConsumer[] inners; |
||||
|
|
||||
|
public string Name { get; } |
||||
|
|
||||
|
public CompoundEventConsumer(IEventConsumer first, params IEventConsumer[] inners) |
||||
|
{ |
||||
|
Guard.NotNull(first, nameof(first)); |
||||
|
Guard.NotNull(inners, nameof(inners)); |
||||
|
|
||||
|
this.inners = new[] { first }.Union(inners).ToArray(); |
||||
|
|
||||
|
Name = first.GetType().Name; |
||||
|
} |
||||
|
|
||||
|
public CompoundEventConsumer(string name, params IEventConsumer[] inners) |
||||
|
{ |
||||
|
Guard.NotNull(inners, nameof(inners)); |
||||
|
Guard.NotNullOrEmpty(name, nameof(name)); |
||||
|
|
||||
|
this.inners = inners; |
||||
|
|
||||
|
Name = name; |
||||
|
} |
||||
|
|
||||
|
public Task ClearAsync() |
||||
|
{ |
||||
|
return Task.WhenAll(inners.Select(i => i.ClearAsync())); |
||||
|
} |
||||
|
|
||||
|
public async Task On(Envelope<IEvent> @event) |
||||
|
{ |
||||
|
foreach (var inner in inners) |
||||
|
{ |
||||
|
await inner.On(@event); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Envelope.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using NodaTime; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.Events |
||||
|
{ |
||||
|
public class Envelope<TPayload> where TPayload : class |
||||
|
{ |
||||
|
private readonly EnvelopeHeaders headers; |
||||
|
private readonly TPayload payload; |
||||
|
|
||||
|
public EnvelopeHeaders Headers |
||||
|
{ |
||||
|
get { return headers; } |
||||
|
} |
||||
|
|
||||
|
public TPayload Payload |
||||
|
{ |
||||
|
get { return payload; } |
||||
|
} |
||||
|
|
||||
|
public Envelope(TPayload payload) |
||||
|
: this(payload, new EnvelopeHeaders()) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Envelope(TPayload payload, PropertiesBag bag) |
||||
|
: this(payload, new EnvelopeHeaders(bag)) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public Envelope(TPayload payload, EnvelopeHeaders headers) |
||||
|
{ |
||||
|
Guard.NotNull(payload, nameof(payload)); |
||||
|
Guard.NotNull(headers, nameof(headers)); |
||||
|
|
||||
|
this.payload = payload; |
||||
|
this.headers = headers; |
||||
|
} |
||||
|
|
||||
|
public static Envelope<TPayload> Create(TPayload payload) |
||||
|
{ |
||||
|
var eventId = Guid.NewGuid(); |
||||
|
|
||||
|
var envelope = |
||||
|
new Envelope<TPayload>(payload) |
||||
|
.SetEventId(eventId) |
||||
|
.SetTimestamp(SystemClock.Instance.GetCurrentInstant()); |
||||
|
|
||||
|
return envelope; |
||||
|
} |
||||
|
|
||||
|
public Envelope<TOther> To<TOther>() where TOther : class |
||||
|
{ |
||||
|
return new Envelope<TOther>(payload as TOther, headers.Clone()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
// ==========================================================================
|
||||
|
// CompoundEventConsumerTests.cs
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex Group
|
||||
|
// All rights reserved.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Threading.Tasks; |
||||
|
using Moq; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.CQRS.Events |
||||
|
{ |
||||
|
public class CompoundEventConsumerTests |
||||
|
{ |
||||
|
private readonly Mock<IEventConsumer> consumer1 = new Mock<IEventConsumer>(); |
||||
|
private readonly Mock<IEventConsumer> consumer2 = new Mock<IEventConsumer>(); |
||||
|
|
||||
|
private sealed class MyEvent : IEvent |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_return_given_name() |
||||
|
{ |
||||
|
var sut = new CompoundEventConsumer("consumer-name"); |
||||
|
|
||||
|
Assert.Equal("consumer-name", sut.Name); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_return_first_inner_name() |
||||
|
{ |
||||
|
var sut = new CompoundEventConsumer(consumer1.Object, consumer2.Object); |
||||
|
|
||||
|
Assert.Equal(consumer1.Object.GetType().Name, sut.Name); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_clear_all_consumers() |
||||
|
{ |
||||
|
consumer1.Setup(x => x.ClearAsync()).Returns(TaskHelper.Done).Verifiable(); |
||||
|
consumer2.Setup(x => x.ClearAsync()).Returns(TaskHelper.Done).Verifiable(); |
||||
|
|
||||
|
var sut = new CompoundEventConsumer("consumer-name", consumer1.Object, consumer2.Object); |
||||
|
|
||||
|
await sut.ClearAsync(); |
||||
|
|
||||
|
consumer1.VerifyAll(); |
||||
|
consumer2.VerifyAll(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_invoke_all_consumers() |
||||
|
{ |
||||
|
var @event = Envelope.Create(new MyEvent()); |
||||
|
|
||||
|
consumer1.Setup(x => x.On(@event)).Returns(TaskHelper.Done).Verifiable(); |
||||
|
consumer2.Setup(x => x.On(@event)).Returns(TaskHelper.Done).Verifiable(); |
||||
|
|
||||
|
var sut = new CompoundEventConsumer("consumer-name", consumer1.Object, consumer2.Object); |
||||
|
|
||||
|
await sut.On(@event); |
||||
|
|
||||
|
consumer1.VerifyAll(); |
||||
|
consumer2.VerifyAll(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue