Fisher 0.8.0
Consumes JasperFx 2.50.0 and moves Fisher's binary event serialization onto the shared contracts.
⚠️ Upgrade JasperFx and Fisher together
Fisher 0.7.2 with JasperFx 2.50.0 does not compile. JasperFx 2.50.0 adds an Events accessor to IDocumentSessionOperations, and on 0.7.2 that reaches IDocumentSession down two unrelated inheritance branches with neither hiding the other — so every session.Events call site fails with:
error CS0229: Ambiguity between 'IDocumentSessionOperations.Events' and 'IQuerySession.Events'
0.8.0 fixes it by re-declaring the member on Fisher's own IDocumentSession. This release requires JasperFx >= 2.50.0, but NuGet cannot express the other direction — so if you are on 0.7.2, do not take JasperFx 2.50.0 on its own.
🐛 Fixed: binary event bodies could be written to the wrong column (shipped in 0.7.x)
A binary event's INSERT named data_binary before the optional metadata columns but bound its value last. With any of EnableCorrelationId / EnableCausationId / EnableHeaders / EnableUserName turned on, every value from data_binary onward shifted by one: the event body landed in correlation_id and the correlation id in data_binary.
It survived review because the comment at the call site asserted the invariant it violated, and it survived testing because the binary tests enabled no metadata columns and the metadata tests appended no binary event — each half was covered, the combination was not. Both are exercised together now.
Affected rows are unreadable on the event body; the row and the stream are otherwise intact, so it presents as a deserialization failure rather than an append error.
💥 Breaking: binary serialization moved to the JasperFx contracts
IEventBinarySerializer and [BinaryEvent] now come from JasperFx.Events instead of Fisher.Events, so one serializer implementation works across Marten, Polecat and Fisher. Migrating:
was (Fisher.Events) |
now (JasperFx.Events) |
|---|---|
Serialize(object eventBody, Type eventType) |
Serialize(Type type, object data) — argument order reversed |
Deserialize(byte[] data, Type eventType) |
Deserialize(Type type, byte[] data) |
Events.BinarySerializer = … |
Events.DefaultBinarySerializer = … |
| — | Events.UseBinarySerializer<TEvent>(…) for per-type registration |
[BinaryEvent] on class/struct/interface |
class/struct only |
The reversal is a compile error rather than a silent swap, because the parameter types also exchange places.
Storage: per-row dispatch, and no migration to opt in
data_binary is now an unconditional nullable BLOB and data stays TEXT NOT NULL, with binary rows carrying a {} placeholder. Whether a row is binary is decided per row by data_binary IS NULL, never by the event type.
Both differ from 0.7.x deliberately:
- An existing store upgrades with a single
ADD COLUMN. Weasel.Sqlite can add a nullable column in place but needs a full table recreation to change nullability — keepingdataNOT NULL is what avoids rewriting the events table. - Per-row dispatch is what makes marking a type
[BinaryEvent]an in-place change: rows already written stay JSON and still read. Type-based dispatch would send those down the binary path, where a null BLOB is an exception or an all-defaults event.
data nullable with real NULLs in binary rows; restoring NOT NULL would be a table recreation that fails on them. Given the feature is eight days old, pre-1.0, and requires writing your own serializer, no migration path was built. If you have such a store, raise an issue before upgrading.
Also
- jasperfx#669 —
IDocumentReadOperations.EventsandIDocumentSessionOperations.Eventsimplemented onFisherSession, so a session you open yourself can reach the event store store-agnostically. - Serializer registration is no longer order-sensitive: registering an event type before its serializer now defers the refusal to the append, where it is actionable.
- Enrolled in the shared
BinaryEventSerializationComplianceandDocumentSessionEventsCompliancesuites.
Tests: Fisher.Tests 1265 passed / 0 failed on net9.0 and net10.0.
Full changelog: v0.7.2...v0.8.0