Skip to content

Marten 9.26.0

Choose a tag to compare

@jeremydmiller jeremydmiller released this 17 Aug 11:46
· 249 commits to master since this release
5cc9488

Consumes JasperFx 2.50.0, which promoted two things into the shared contracts. Both changes here are additive — existing code compiles and behaves identically.

Reach the event store from a store-agnostic session (#669)

JasperFx.Events.Documents gained an Events accessor on its session contracts, so a consumer that opens its own session through IDocumentSessionFactory can now reach the event store without naming Marten:

tier member
IDocumentReadOperations IQueryEventStore Events
IDocumentSessionOperations IEventStoreOperations Events

Marten implements both. This does not affect handlers taking a chain parameter — Wolverine already fills those. It matters for the two shapes where you decide when a session exists: a background or timer publisher that opens a session and appends, and a deliberate second read session opened alongside a chain's writing session.

⚠️ Worth knowing if you maintain a store or a session wrapper. C# interface implementation is not return-type covariant, so a session that already declares an Events property of its own event-store type does not satisfy the contract member — it binds to a default that throws, and the build still succeeds with zero errors. Marten's own IQuerySession.Events returns Marten.Events.IQueryEventStore, a subtype, which is exactly this case; both tiers needed an explicit implementation. The shared compliance suite is what catches it.

IEventBinarySerializer promoted to JasperFx.Events

Binary event serialization (#4515) was Marten-specific, so a consumer compiling one body of source against several Critter Stack stores needed a separate identical serializer per store. The two-method interface and [BinaryEvent] now live in JasperFx.Events, and one serializer serves every store.

Non-breaking, in both directions:

  • Marten.Events.IEventBinarySerializer still exists and now derives from the core interface, so existing implementations keep compiling and also satisfy the core type.
  • EventGraph.UseBinarySerializer<T>, DefaultBinarySerializer, IEventStoreOptions and EventMapping.BinarySerializer widened to accept the core interface, so a store-agnostic serializer can be registered.
  • Both the Marten and the core [BinaryEvent] attributes are honored.

Fixed: binary serializer registration was order-dependent

EventMapping resolved its binary serializer in its constructor, and AddEventType<T>() builds mappings eagerly. So this threw "no IEventBinarySerializer was registered" out of what reads as a plain type registration:

opts.Events.AddEventType<SomeBinaryEvent>();          // [BinaryEvent]-marked
opts.Events.DefaultBinarySerializer = mySerializer;   // too late

while the same two lines in the opposite order worked. Resolution is lazy now, deferring the failure to first use — which is what the documentation always described. The guard is volatile, because it is read from the append path on many threads and a torn read would route a binary event down the JSON path silently rather than throwing.

Also

  • Enrolled in the two new shared compliance suites, DocumentSessionEventsCompliance and BinaryEventSerializationCompliance.
  • Docs updated: events/binary-serialization.md, documents/sessions.md.

Full changelog: 9.25.0...9.26.0