Marking Events as Skipped 8.6
What if your code happens to append an event that turns out to be completely erroneous (not necessarily because of your code) and you wish you could retroactively have it removed from the event store? You could go and delete the event record directly from the mt_events
table, but maybe you have regulatory requirements that no events can ever be deleted -- which is the real world case that spawned this feature. You could also try a compensating event that effectively reverses the impact of the earlier, now invalid event, but that requires more work and foresight on your part.
Instead, you can mark events in a Marten event store as "skipped" such that these events are left as is in the database, but will no longer be applied:
- In projections. You'd have to rebuild a projection that includes a skipped event to update the resulting projection though.
- Subscriptions. If you rewind a subscription and replay it, the events marked as "skipped" are, well, skipped
AggregateStreamAsync()
in all usagesFetchLatest()
andFetchForWriting()
usages, but again, you may have to rebuild a projection to take the skipped events out of the results
TIP
Definitely check out Rebuilding a Single Stream for part of the recipe for "healing" a system from bad events.
To get started, you will first have to enable potential event skipping like this:
var builder = Host.CreateApplicationBuilder();
builder.Services.AddMarten(opts =>
{
opts.Connection(builder.Configuration.GetConnectionString("marten"));
// This is false by default for backwards compatibility,
// turning this on will add an extra column and filtering during
// various event store operations
opts.Events.EnableEventSkippingInProjectionsOrSubscriptions = true;
});
That flag just enables the ability to mark events as skipped. As you'd imagine, that flag alters Marten behavior by:
- Adds a new field called
is_skipped
to yourmt_events
table - Adds an additional filter on
is_skipped = FALSE
on many event store operations detailed above
To mark events as skipped, you can either use raw SQL against your mt_events
table, or this helper API: