Skip to content

Commit

Permalink
Added example of providing EventStoreDB SubscriptionToAll filter to m…
Browse files Browse the repository at this point in the history
…atch a specific set of event types
  • Loading branch information
oskardudycz committed May 24, 2024
1 parent a65bffe commit 2fbf052
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using Core.Events;
using Core.EventStoreDB.Subscriptions.Checkpoints;
using Core.EventStoreDB.Subscriptions.Filtering;
using FluentAssertions;
using Xunit;

namespace Core.EventStoreDB.Tests.Subscriptions.Filtering;
using static EventFilters;

public class EventTypeFiltersTests
{
[Fact]
public void ExcludeSystemAndCheckpointEventsRegex_Should_NotMatch_SystemEvents()
{
ExcludeSystemAndCheckpointEventsRegex.IsMatch("$scavengeIndexInitialized").Should().BeFalse();
ExcludeSystemAndCheckpointEventsRegex.IsMatch(typeof(CheckpointStored).FullName!).Should().BeFalse();
ExcludeSystemAndCheckpointEventsRegex.IsMatch("Core.EventStoreDB.Subscriptions.Checkpoints.CheckpointStored").Should().BeFalse();
}

[Fact]
public void ExcludeSystemAndCheckpointEventsRegex_Should_Match_OtherEvents()
{
ExcludeSystemAndCheckpointEventsRegex.IsMatch("ShoppingCartOpened").Should().BeTrue();
ExcludeSystemAndCheckpointEventsRegex.IsMatch("SomeOtherEvent").Should().BeTrue();
}

[Fact]
public void OneOfEventTypesRegex_Should_Match_ProvidedEvents()
{
var regex = OneOfEventTypesRegex("ShoppingCartOpened", "OrderPlaced");

regex.IsMatch("ShoppingCartOpened").Should().BeTrue();
regex.IsMatch("OrderPlaced").Should().BeTrue();
}

[Fact]
public void OneOfEventTypesRegex_Should_NotMatch_OtherEvents()
{
var regex = OneOfEventTypesRegex("ShoppingCartOpened", "OrderPlaced");

regex.IsMatch("OrderCancelled").Should().BeFalse();
regex.IsMatch("$systemEvent").Should().BeFalse();
}

[Fact]
public void OneOfEventTypesRegex_WithEventTypeMapper_Should_Match_ProvidedEventTypesWithCustomMap()
{
var eventTypeMapper = new EventTypeMapper();
eventTypeMapper.AddCustomMap<ShoppingCartOpened>("ShoppingCartOpened");

var regex = OneOfEventTypesRegex(eventTypeMapper, typeof(ShoppingCartOpened));

regex.IsMatch("ShoppingCartOpened").Should().BeTrue();
}

[Fact]
public void OneOfEventTypesRegex_WithEventTypeMapper_Should_NotMatch_OtherEventTypesWithCustomMap()
{
var eventTypeMapper = new EventTypeMapper();
eventTypeMapper.AddCustomMap<ShoppingCartOpened>("ShoppingCartOpened");

var regex = OneOfEventTypesRegex(eventTypeMapper, typeof(ShoppingCartOpened));

regex.IsMatch("OrderPlaced").Should().BeFalse();
}

[Fact]
public void OneOfEventTypesRegex_WithEventTypeMapper_Should_Match_ProvidedEventTypes()
{
var eventTypeMapper = new EventTypeMapper();

var regex = OneOfEventTypesRegex(eventTypeMapper, typeof(ShoppingCartOpened));

regex.IsMatch(typeof(ShoppingCartOpened).FullName!).Should().BeTrue();
}

[Fact]
public void OneOfEventTypesRegex_WithEventTypeMapper_Should_NotMatch_OtherEventTypes()
{
var eventTypeMapper = new EventTypeMapper();

var regex = OneOfEventTypesRegex(eventTypeMapper, typeof(ShoppingCartOpened));

regex.IsMatch("OrderPlaced").Should().BeFalse();
}

private record ShoppingCartOpened(
Guid ShoppingCartId,
Guid ClientId
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.RegularExpressions;
using Core.Events;
using Core.EventStoreDB.Subscriptions.Batch;
using Core.EventStoreDB.Subscriptions.Checkpoints;
using Core.EventStoreDB.Subscriptions.Filtering;
using Core.Extensions;
using EventStore.Client;
using Grpc.Core;
Expand All @@ -16,14 +16,10 @@ namespace Core.EventStoreDB.Subscriptions;

public class EventStoreDBSubscriptionToAllOptions
{
public static readonly IEventFilter ExcludeSystemAndCheckpointEvents =
EventTypeFilter.RegularExpression(
@"^(?!\$)(?!Core\.EventStoreDB\.Subscriptions\.Checkpoints\.CheckpointStored$).+");

public required string SubscriptionId { get; init; }

public SubscriptionFilterOptions FilterOptions { get; set; } =
new(ExcludeSystemAndCheckpointEvents);
new(EventFilters.ExcludeSystemAndCheckpointEvents);

public Action<EventStoreClientOperationOptions>? ConfigureOperation { get; set; }
public UserCredentials? Credentials { get; set; }
Expand Down
33 changes: 33 additions & 0 deletions Core.EventStoreDB/Subscriptions/Filtering/EventFilters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Text.RegularExpressions;
using Core.Events;
using Core.EventStoreDB.Subscriptions.Checkpoints;
using EventStore.Client;

namespace Core.EventStoreDB.Subscriptions.Filtering;

public static class EventFilters
{
public static readonly Regex ExcludeSystemAndCheckpointEventsRegex =
new(@"^(?!\$)(?!" + Regex.Escape(typeof(CheckpointStored).FullName!) + "$).+");

public static Regex OneOfEventTypesRegex(params string[] values) =>
new("^(" + string.Join("|", values.Select(Regex.Escape)) + ")$");

public static Regex OneOfEventTypesRegex(EventTypeMapper eventTypeMapper, params Type[] eventTypes) =>
OneOfEventTypesRegex(eventTypes.Select(eventTypeMapper.ToName).ToArray());

public static Regex OneOfEventTypesRegex(params Type[] eventTypes) =>
OneOfEventTypesRegex(EventTypeMapper.Instance, eventTypes);

public static readonly IEventFilter ExcludeSystemAndCheckpointEvents =
EventTypeFilter.RegularExpression(ExcludeSystemAndCheckpointEventsRegex);

public static IEventFilter OneOfEventTypes(params string[] values) =>
EventTypeFilter.RegularExpression(OneOfEventTypesRegex(values));

public static IEventFilter OneOfEventTypes(EventTypeMapper eventTypeMapper, params Type[] eventTypes) =>
EventTypeFilter.RegularExpression(OneOfEventTypesRegex(eventTypeMapper, eventTypes));

public static IEventFilter OneOfEventTypes(params Type[] eventTypes) =>
EventTypeFilter.RegularExpression(OneOfEventTypesRegex(eventTypes));
}

0 comments on commit 2fbf052

Please sign in to comment.