Marten Operation Side Effects
TIP
You can certainly write your own IMartenOp
implementations and use them as return values in your Wolverine handlers
INFO
This integration includes full support for the storage action side effects model when using Marten with Wolverine.
TIP
This integration also includes full support for the storage action side effects model when using Marten~~~~ with Wolverine.
The Wolverine.Marten
library includes some helpers for Wolverine side effects using Marten with the IMartenOp
interface:
/// <summary>
/// Interface for any kind of Marten related side effect
/// </summary>
public interface IMartenOp : ISideEffect
{
void Execute(IDocumentSession session);
}
The built in side effects can all be used from the MartenOps
static class like this HTTP endpoint example:
[WolverinePost("/invoices/{invoiceId}/pay")]
public static IMartenOp Pay([Document] Invoice invoice)
{
invoice.Paid = true;
return MartenOps.Store(invoice);
}
There are existing Marten ops for storing, inserting, updating, and deleting a document. There's also a specific helper for starting a new event stream as shown below:
public static class TodoListEndpoint
{
[WolverinePost("/api/todo-lists")]
public static (TodoCreationResponse, IStartStream) CreateTodoList(
CreateTodoListRequest request
)
{
var listId = CombGuidIdGeneration.NewGuid();
var result = new TodoListCreated(listId, request.Title);
var startStream = MartenOps.StartStream<TodoList>(listId, result);
return (new TodoCreationResponse(listId), startStream);
}
}
The major advantage of using a Marten side effect is to help keep your Wolverine handlers or HTTP endpoints be a pure function that can be easily unit tested through measuring the expected return values. Using IMartenOp
also helps you utilize synchronous methods for your logic, even though at runtime Wolverine itself will be wrapping asynchronous code about your simpler, synchronous code.
Returning Multiple Marten Side Effects 3.6
Due to (somewhat) popular demand, Wolverine lets you return zero to many IMartenOp
operations as side effects from a message handler or HTTP endpoint method like so:
// Just keep in mind that this "example" was rigged up for test coverage
public static IEnumerable<IMartenOp> Handle(AppendManyNamedDocuments command)
{
var number = 1;
foreach (var name in command.Names)
{
yield return MartenOps.Store(new NamedDocument{Id = name, Number = number++});
}
}
Wolverine will pick up on any return type that can be cast to IEnumerable<IMartenOp>
, so for example:
IEnumerable<IMartenOp>
IMartenOp[]
List<IMartenOp>
And you get the point. Wolverine is not (yet) smart enough to know that an array or enumerable of a concrete type of IMartenOp
is a side effect.
Like any other "side effect", you could technically return this as the main return type of a method or as part of a tuple.