Skip to content

Marten 9.34.0

Choose a tag to compare

@jeremydmiller jeremydmiller released this 13 Sep 12:36
· 155 commits to master since this release

Native AOT support for event-sourced applications, and a round of integrity fixes to the diagnostics and monitoring surface — including one deliberate behaviour change worth reading before upgrading.

Native AOT

Event-sourced applications now run under Native AOT.

  • #5375 — Closes four generics where the compiler can emit them, so an event-sourced app runs under Native AOT rather than failing at runtime on a construction the trimmer removed.
  • #5377 — The jsonb containment payload is written by Marten with Utf8JsonWriter instead of round-tripping through the consumer's serializer, removing a reflection-dependent path from AOT reads.

Diagnostics and monitoring

Three fixes to the event store explorer and projection-status APIs. All three are cases where a monitoring read returned something misleading, or changed the system it was observing.

  • #5400 — Behaviour change. The four explorer read APIs no longer provision anything. They resolved their database through ITenancy.FindOrCreateDatabase, and two tenancy models take the "or create" half literally: ShardedTenancy assigned an unknown tenant to a shard and ran partition + per-tenant sequence DDL for it, and SingleServerMultiTenancy issued CREATE DATABASE for a database named after the id. A console polling a retired or mistyped tenant id therefore brought that tenant — or a whole database — into existence.

    An unrecognized tenant id now throws UnknownTenantIdException, which is what StaticMultiTenancy and MasterTableTenancy already did, so the explorer answers the same way across every tenancy model. Adds the public ITenancy.TryFindDatabase, a read-only counterpart to FindOrCreateDatabase; it is a default interface member, so custom ITenancy implementations keep working unchanged. FindOrCreateDatabase itself is untouched — create-on-demand remains its documented job for real tenant traffic.

    If you call GetRecentStreamsAsync, ReadStreamAsync, QueryByTagsAsync or GetProjectionStatusesAsync with a tenant id that may not exist, it now throws where it previously succeeded.

  • #5382 — GetProjectionStatusesAsync(ct) threw NotSupportedException on a database-per-tenant store, because a tenant-less call has no default tenant to open a session against. It now answers from the projection registry, so "is this projection still registered?" — the only store-agnostic way to ask, and what orphan detection is built on — works on the store shape that most needs it.

    Note the original issue reported that both overloads threw. Only the tenant-less one did; passing a tenant id or a database identifier from AllDatabases() has always worked and reads real per-database progression.

  • #5396 — ShardStatus.State reports the state of a reachable daemon instead of always answering Unknown. Unknown now means what it is documented to mean: there is no daemon here to ask.

Correctness

  • #5386 — The expected version for optimistic concurrency is seeded from a mapped version/revision member, not just the IVersioned marker interface. Thanks to @JurJean for the report and the original fix.
  • #5389 — Enum member renames are resolved by asking the serializer, so [JsonStringEnumMemberName] / [EnumMember] names are honored in LINQ translation rather than the CLR member name being assumed.
  • #5390 — The jsonb containment payload writer handles nested dictionary keys and byte[], and its limits are documented. Thanks to @erdtsieck.

Event modeling

  • #5397 — ProjectionEventModelSource is registered from AddMarten and AddMartenStore<T>, so Event Model views resolve from a Marten store without manual wiring.

pgvector

  • #5399 — Four defects the pgvector import left behind.

Docs and internals

  • #5381 — Documents PrefixSearch and the session-level full-text search shortcuts.
  • #5391 — The PostgreSQL setup docs described a Marten that no longer exists (stale PLV8 instructions, a non-functional image override, and an invented build matrix).
  • #5395 — Enrolls GuidOptimisticConcurrencyCompliance in the shared compliance suite.
  • #5370, #5371 — Takes Bobcat's shipped runner adapter and its interceptor opt-in.

Dependencies

  • JasperFx 2.69.1
  • Weasel 9.32.0

Known limitation

#5382's tenant-less registry answer reports ProcessedSequence and EventStoreSequence as 0 because nothing was read — which a caller cannot distinguish from a shard that has genuinely never run. That ambiguity is deliberate for now; #5383 tracks the database-scoped overloads that read real progression per database.


Cut as a minor on public API surface: #5400 adds ITenancy.TryFindDatabase, and #5397 changes DI registration.