-
-
Notifications
You must be signed in to change notification settings - Fork 146
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finally able to correctly forward messages to IEvent<T> when using th…
…e event forwarding
- Loading branch information
1 parent
da097b4
commit c679892
Showing
3 changed files
with
172 additions
and
27 deletions.
There are no files selected for viewing
126 changes: 126 additions & 0 deletions
126
src/Persistence/MartenTests/Bugs/event_forwarding_bug.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
using IntegrationTests; | ||
using JasperFx.Core; | ||
using JasperFx.Core.Reflection; | ||
using Marten; | ||
using Marten.Events; | ||
using Microsoft.Extensions.Hosting; | ||
using Shouldly; | ||
using Wolverine; | ||
using Wolverine.Marten; | ||
using Wolverine.Runtime.Routing; | ||
using Wolverine.Tracking; | ||
|
||
namespace MartenTests.Bugs; | ||
|
||
public class event_forwarding_bug | ||
{ | ||
[Fact] | ||
public async Task publish_ievent_of_t() | ||
{ | ||
// The "Arrange" | ||
using var host = await Host.CreateDefaultBuilder() | ||
.UseWolverine(opts => | ||
{ | ||
opts.Policies.AutoApplyTransactions(); | ||
|
||
opts.Durability.Mode = DurabilityMode.Solo; | ||
|
||
opts.Services.AddMarten(m => | ||
{ | ||
m.Connection(Servers.PostgresConnectionString); | ||
m.DatabaseSchemaName = "forwarding"; | ||
|
||
m.Events.StreamIdentity = StreamIdentity.AsString; | ||
m.Projections.LiveStreamAggregation<ShoppingList>(); | ||
}).UseLightweightSessions() | ||
.IntegrateWithWolverine() | ||
.EventForwardingToWolverine();; | ||
}).StartAsync(); | ||
|
||
var runtime = host.GetRuntime(); | ||
var routing = runtime.RoutingFor(typeof(Event<ShoppingListCreated>)); | ||
|
||
// The "Act". This method is an extension method in Wolverine | ||
// specifically for facilitating integration testing that should | ||
// invoke the given message with Wolverine, then wait until all | ||
// additional "work" is complete | ||
var session = await host.InvokeMessageAndWaitAsync(new CreateShoppingList()); | ||
|
||
// And finally, just assert that a single message of | ||
// type IEvent<ShoppingListCreated> was executed | ||
session.Executed.SingleMessage<IEvent<ShoppingListCreated>>() | ||
.ShouldNotBeNull(); | ||
} | ||
} | ||
|
||
public record AddShoppingListItem(string ShoppingListId, string ItemName); | ||
|
||
public static class AddShoppingListItemHandler | ||
{ | ||
public static async Task Handle(AddShoppingListItem command, IDocumentSession session) | ||
{ | ||
var stream = await session.Events.FetchForWriting<ShoppingList>(command.ShoppingListId); | ||
var shoppingList = stream.Aggregate; | ||
if (shoppingList is null) | ||
throw new InvalidOperationException("Shopping list does not exist"); | ||
|
||
if (shoppingList.Contains(command.ItemName)) | ||
throw new InvalidOperationException("Item is already in shopping list"); | ||
|
||
stream.AppendOne(new ShoppingListItemAdded(command.ItemName)); | ||
} | ||
} | ||
|
||
public record CreateShoppingList(); | ||
|
||
public static class CreateShoppingListHandler | ||
{ | ||
public static string Handle(CreateShoppingList _, IDocumentSession session) | ||
{ | ||
var shoppingListId = CombGuidIdGeneration.NewGuid().ToString(); | ||
session.Events.StartStream<ShoppingList>(shoppingListId, new ShoppingListCreated(shoppingListId)); | ||
return shoppingListId; | ||
} | ||
} | ||
|
||
public static class IntegrationHandler | ||
{ | ||
public static void Handle(IEvent<ShoppingListCreated> _) | ||
{ | ||
// Don't need a body here, and I'll show why not | ||
// next | ||
} | ||
} | ||
|
||
public record ShoppingListCreated(string Id); | ||
|
||
public record ShoppingListItemAdded(string ItemName); | ||
|
||
public class ShoppingList | ||
{ | ||
public string Id { get; init; } = null!; | ||
private List<ShoppingListItem> Items { get; init; } = null!; | ||
|
||
public bool Contains(string itemName) => Items.Any(item => item.Name == itemName); | ||
|
||
public static ShoppingList Create(ShoppingListCreated _) | ||
{ | ||
return new ShoppingList | ||
{ | ||
Items = [], | ||
}; | ||
} | ||
|
||
public void Apply(ShoppingListItemAdded @event) | ||
{ | ||
Items.Add(new ShoppingListItem | ||
{ | ||
Name = @event.ItemName | ||
}); | ||
} | ||
} | ||
|
||
public record ShoppingListItem | ||
{ | ||
public required string Name { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters