Bump Marten from 8.37.0 to 9.15.4#68
Open
dependabot[bot] wants to merge 1 commit into
Open
Conversation
--- updated-dependencies: - dependency-name: Marten dependency-version: 9.15.4 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: Marten dependency-version: 9.15.4 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updated Marten from 8.37.0 to 9.15.4.
Release notes
Sourced from Marten's releases.
9.15.4
What's Changed
New Contributors
Full Changelog: JasperFx/marten@v9.15.3...v9.15.4
9.15.3
This addresses a potential vulnerability from SQL injection via non-string constant in a LINQ Select projection
Not a common usage, but still.
What's Changed
Full Changelog: JasperFx/marten@9.15.2...v9.15.3
9.15.2
Marten 9.15.2
A patch release. Both fixes come out of the same 512-tenant-database production deployment, reported by @erdtsieck, and both turned out to be worse than the reports described.
Bulk event insert ran a full schema apply on every batch
#4946 — fixed in #4949
The batch
BulkInsertEventsAsyncoverloads opened withStorage.ApplyAllConfiguredChangesToDatabaseAsync()on every call.That is not a cheap check. It calls
Tenancy.BuildDatabases()and runs a full schema delta — partition introspection plusinformation_schemasweeps — across every database in the store. So a sharded store paid one apply per database, per batch. On the reporting deployment, each ~1,000-event batch was triggering 512 schema applies.The measured effect: import throughput collapsed to ~17 events/s, against >3,000/s for the streaming overload. A 686k-event tenant projected to roughly 11 hours. The connection pool filled with ~370 backends whose last statement was Weasel's partition-introspection query, which fed directly into the server-wide connection pressure that deployment was already fighting.
That the streaming overload
BulkInsertEventStreamAsynchas no such call and is fine is the tell: the schema apply was never part of the contract. It was a leftover.The apply is now:
AutoCreateisNone— it is a no-op there by contract, so all that remained was the introspection cost; andIMartenDatabase.Identifier.One subtlety worth recording, because it is the kind of thing that bites later: the memoized apply deliberately does not take a caller's
CancellationToken. The first caller to arrive owns the single in-flight task that every concurrent caller for that database awaits — so binding that shared task to one caller's token would let a single cancelled batch fail sibling batches that were never cancelled. Each caller applies its own token at the await site instead. A schema apply is short and idempotent, so letting it run to completion is the cheaper trade.Under
AutoCreate.None, the event storage must already exist before import. That is the documented contract and it matches the streaming overload — but if you were previously relying on the per-call apply to create it for you under a non-Nonestore, note the change.The document bulk-insert path (
BulkInsertAsync/BulkInsertDocumentsAsync) is unaffected. It routes through the ordinary per-featureEnsureStorageExistsAsyncthat Weasel already memoizes, not a full-store delta.Tenant provisioning silently under-provisioned partitions
#4944 — fixed in #4950
AddPartitionToAllTables, and the tenant-provisioning paths built on it, walked the calling store'sStoreOptionsto decide which tables needed a list partition for a new tenant.So any tool or host that provisions tenants from a store which doesn't register every document type silently under-provisioned. Document types unknown to the caller never got their partitions — and the tenant then failed with a Postgres
23514check-constraint violation on first write to the missing partition. Nothing failed at provisioning time; the damage surfaced later, somewhere else.The workaround was "the provisioning tool must register all document types," which re-creates schema knowledge in a second place and drifts as document types are added.
The sweep is now database-driven: it enumerates tenant list-partitioned tables from the Postgres catalog, so a partially-registered store still provisions every partitioned table it finds.
Scoping is enforced inside the catalog query rather than filtered in memory afterward:
AllSchemaNames()only. Foreign partitioned tables in a shared database are never touched.tenant_id. This is the filter that matters most, and it is what keeps the sweep off Marten's own non-tenant list partitioning:UseArchivedStreamPartitioningkeysmt_eventsonis_archived, andByList()keys on its own field. Without it, a "helpful" sweep would start adding tenant partitions to tables partitioned on something else entirely.ByExternallyManagedListPartitions()are subtracted.Opt out with
SweepPartitionedTablesFromDatabase(default on). No Weasel change was required.Known limitation, and it is a real one: a document type registered into a schema the calling store has never heard of stays invisible to the schema filter — a store cannot own a schema it does not know exists. Single-schema stores (the default, and the reporting deployment's shape) are fully covered. Closing this properly would need a persisted table list alongside
mt_tenant_partitions.... (truncated)
9.15.1
Patch release for a silent data-correctness regression. If you use
ForTenant()on an identity-mapped or dirty-tracked session, upgrade.Fixed
#4947 —
ForTenant()on an identity session stopped returning tenancy-neutral documents (reported by @dervagabund, with a repro — thank you). AForTenant()view of an identity- or dirty-tracked session no longer saw global (tenancy-neutral) documents tracked by the parent session. Since a global document has exactly one row per id for the whole database,LoadAsyncthrough theForTenantview missed the identity map, went to the database, and returnednullfor a document that is there. A silent wrong answer, not an error.Affected: 9.13.0, 9.14.x, 9.15.0. Introduced by the fix for #4801, which tenant-scoped the identity map and version tracker for
ForTenantsessions. That was correct for conjoined documents — where the same id means a different document per tenant — but it was applied per session rather than per document type, so it also isolated document types that are tenancy-neutral and must be shared.Sharing is now decided per document type. A nested
ForTenantsession shares the parent's identity-map and version-tracker entry for a type only when the storage is identity-mapped, the type is notConjoined, and the nested session's database is the same instance as the parent's (under database-per-tenant, the same id in another tenant's database is a different document even for a tenancy-neutral type). The isolation introduced by #4801 is preserved exactly — theBug_4801suite still passes, and the new tests include guard rails asserting conjoined documents stay isolated.Full changelog: JasperFx/marten@9.15.0...9.15.1
9.15.0
Closed issues
findOrAssignTenantDatabaseAsyncreturned early on an existing assignment row, skippingcreatePartitionsForTenant+ per-tenant event-sequence provisioning — so a tenant whose provisioning was interrupted (assignment committed, partitions missing) failed every write with23514forever. Both early-return paths (including a second race-window hole under the advisory lock) now run the same idempotent repair the explicitAddTenantToShardAsync(tenantId, databaseId)overload always ran, guarded to once per process per tenant via the resolution cache.Also in this release
JasperFx.Events.SourceGeneratoranalyzer (JasperFx/jasperfx#505) — CS1061 compile break for no-parameterless-ctor aggregates with instanceApplyreturning the aggregate.pg_inherits) for the #4943 provisioning-tool scenario.Verified against Wolverine (full solution + CoreTests/MartenTests/distribution/Http suites, zero failures) and CritterWatch before publishing. Thanks to @erdtsieck for the dump-verified root-cause analysis.
9.14.1
Marten 9.14.1 is a patch release focused on a substantial round of LINQ query-translation improvements, plus event-store partitioning, high-water, and AoT fixes, and refreshed Weasel/JasperFx dependencies.
LINQ query translation
This release significantly expands what the LINQ provider can push down to PostgreSQL instead of falling back to slower strategies or throwing:
Any(predicate)filters now translate to JSONPath and OR-of-containment strategies, and the old explode/ctidfallback has been replaced by a correlatedEXISTSstrategy.All()shapes and duplicated array fields moved onto the sameEXISTSstrategy. The net effect is correct, index-friendlier SQL for nested-collection predicates.Where()clauses is now supported (e.g.x.Children[0].Name == "...").Sum/Min/Max/Average— can now be used insideWhere()clauses.Regex.IsMatch()is translated inWhere()clauses.IComparable.CompareTo()now works for non-string comparables such asGuid(#4920), alongside broaderCompareTo()coverage,stringIsOneOfvia the?|operator, andCollectionIsEmptyviaICollectionAware.GinIndexJsonDataMember()was added for member-scoped expression GIN indexes.#4916 — subclass queries now use duplicated fields and the base id
Querying a document subclass and filtering on a
Duplicate()'d field or the base-class id previously emitted a JSONB filter (CAST(d.data ->> 'FarmId' as uuid)) instead of the real column, missing the duplicated column and the primary-key index:A subclass shares its parent's table, so the parent's column-backed members (duplicated fields, the id, the soft-delete flag) are now inherited by the subclass's query member resolution. Querying the parent type was already correct and is unchanged.
Event store, partitioning & daemon
UseTenantPartitionedEvents. Registering a tenant whose partition suffix contains a-(so every GUID tenant id) madeApplyAllConfiguredChangesToDatabaseAsync()throw42601because the per-tenantCREATE SEQUENCE/DROP SEQUENCEDDL emitted the identifier unquoted. The schema-apply statements are now quoted (matching the quick-append function and the imperative provisioning path), so hyphenated tenants migrate cleanly. Quote — not sanitize — so the append function can still resolve the sequence by its raw suffix.ObjectDisposedExceptionpath latches-and-rethrows so a HotCold cold node's leadership loop terminates instead of re-polling a disposed data source during shutdown.UseTenantPartitionedEventsthe store-global high-water agent was continuously runningselect max(seq_id) from mt_events, an unfiltered scan that fans out across every tenant partition on every poll. That store-global mark is not used to advance tenant projections (they advance per-tenant), so the recurring scan is now skipped under partitioning; tenant high water is driven by the per-tenant coordinator and poll timer.GetProjectionStatusesAsyncnow resolves the correct named database.AoT / trimming
AddEventType/QueryRawEventDataOnlygeneric-constraint tightening was reversed, and event-mapping construction now routes through the cachedGenericFactoryCachewhile preserving the trimming root (#4930).Dependencies
ShardState.DatabaseIdentifier(jasperfx#501).Closed issues
#4913, #4915, #4916, #4917, #4924, and jasperfx#502.
9.14.0
Marten 9.14.0 is the recommended upgrade for all 9.x users. It combines the LINQ SQL-injection security fix (first shipped in 9.13.0) with the fix for the projection-coordinator shutdown race in #4874 and the accompanying dependency updates.
Beyond the LINQ updates, this made the new Per-Tenant Event Partitioning much more robust as we're testing that in conjunction with a JasperFx client for ludicrous scalability.
🔒 Security — SQL injection in the LINQ provider (GHSA-rfx3-98h7-v3xp)
Several LINQ / tenant-management code paths interpolated a runtime, potentially attacker-influenced value into generated SQL as a single-quoted literal without escaping or parameterization. A value containing a single quote could break out of the literal and inject SQL. The primary vector — a
Dictionary<,>indexer key in aWherefilter (a common "filter by attribute name" / EAV pattern) — was reported privately with an executed proof-of-concept and enabled filter / multi-tenant authorization bypass and blind data exfiltration.Fixed sinks (#4911):
DictionaryItemMember— dictionary indexer key, e.g.Where(x => x.Attributes[key] == v)DictionaryContainsKeyFilter—Dictionary.ContainsKey(key)(Newtonsoft serializer + the Enum branch, which bypass System.Text.Json's quote escaping)SelectParser— a constant string projected throughSelect(x => new { L = runtimeString })DeleteAllForTenant— tenant id reaching per-tenant projection teardown (now parameterized)DatabaseScopedTenantPartitions— tenant id inlined into partition DDLEventLoader— per-tenant partition-pruning literal (defense-in-depth)Each sink now escapes embedded single quotes or binds the value as a parameter; regression tests lock down every vector, and a follow-up LINQ-wide audit cleared the rest of the query hot path (full-text search, string-method translations, comparisons,
IsOneOf/Contains/subset operators, and patching paths). Affected versions: 7.0.0 – 9.12.0. Also patched in 8.37.4 (8.x line) and 9.13.0.Reported responsibly by @svenclaesson — thank you. See advisory GHSA-rfx3-98h7-v3xp (CVE pending assignment).
🛠️ Reliability — projection-coordinator shutdown drain race (#4874)
On host shutdown, the native HotCold projection coordinator could abort with
ObjectDisposedException: 'Npgsql.PoolingDataSource'— the coordinator's leadership poll issued anOpenAsyncagainst an already-disposed data source while tenancy was tearing down. This is the "case B" ordering storm reported against #4874 (distinct from the async-tenancy foundation laid in #4907, which did not resolve it).The fix ships through the dependency updates below, with a Marten-side regression test (
Bug_4874_coordinator_drain_ordering, #4912):ProjectionCoordinatorBaseterminates the leadership loop on a disposed data source / wrapped cancellation instead of re-polling.AdvisoryLockguards against a disposedNpgsqlDataSourceduring shutdown (short-circuits while disposing and treats a disposed-poolObjectDisposedExceptionas a non-acquire rather than propagating).⬆️ Dependency updates
Full changelog since 9.13.0
9.13.0
Security release. Fixes SQL injection in the LINQ provider via unescaped string literals (#4911).
Several LINQ / tenant-management code paths interpolated a runtime, potentially attacker-influenced value into generated SQL as a single-quoted literal without escaping or parameterization; a value containing a single quote could break out and inject SQL. The primary vector — a
Dictionary<,>indexer key in aWherefilter — was reported privately with an executed proof-of-concept (filter / multi-tenant authorization bypass, blind exfiltration).Fixed sinks:
DictionaryItemMember— dictionary indexer keyDictionaryContainsKeyFilter—ContainsKeykey (Newtonsoft serializer + Enum branch)SelectParser— constant string projected viaSelect(...)DeleteAllForTenant— tenant id in per-tenant projection teardown (now parameterized)DatabaseScopedTenantPartitions— tenant id in partition DDLEventLoader— per-tenant partition-pruning literal (defense-in-depth)All 9.x users should upgrade. The 8.x line is fixed in 8.37.4. See advisory GHSA-rfx3-98h7-v3xp.
9.12.0
A couple significant bug fixes, and yet more support for CritterWatch
What's Changed
Full Changelog: JasperFx/marten@V9.11.0...V9.12.0
9.11.0
What's Changed
Full Changelog: JasperFx/marten@V9.10.0...V9.11.0
9.10.0
The new option might help the async daemon perform better in the face of concurrency exceptions on event appending with the QuickAppend option. It's opt in to avoid folks needing to do schema migrations
What's Changed
New Contributors
Full Changelog: JasperFx/marten@V9.9.1...V9.10.0
9.9.1
This will be a valuable upgrade for anyone who experiences a high degree of optimistic concurrency failures while using QuickAppend options, which is the default behavior in V9. This will help stop gaps in the event sequence, which in turn will make the Async Daemon healthier.
Also though, see Wolverine for help in preventing concurrent access in the first place
What's Changed
Full Changelog: JasperFx/marten@V9.9.0...V9.9.1
9.9.0
What's Changed
Full Changelog: JasperFx/marten@V9.8.2...V9.9.0
9.8.2
Couple bug reports related to the Daemon, one performance related for folks using the archived partitioning on the event store
What's Changed
Full Changelog: JasperFx/marten@V9.8.1...V9.8.2
9.8.1
This might impact folks migrating from Marten 8 to Marten 9. Strictly an issue with database migrations
What's Changed
Full Changelog: JasperFx/marten@V9.8.0...V9.8.1
9.8.0
This was pretty well 100% about CritterWatch. The new APIs are all to support CritterWatch
What's Changed
Full Changelog: JasperFx/marten@V9.7.5...V9.8.0
9.7.5
What's Changed
Full Changelog: JasperFx/marten@V9.7.4...V9.7.5
9.7.4
What's Changed
Full Changelog: JasperFx/marten@V9.7.3...V9.7.4
9.7.3
Small release. Couple fixes for daemon resiliency and CritterWatch administration actions
What's Changed
Full Changelog: JasperFx/marten@V9.7.2...V9.7.3
9.7.2
What's Changed
Full Changelog: JasperFx/marten@V9.7.1...V9.7.2
9.7.1
What's Changed
Full Changelog: JasperFx/marten@V9.7.0...V9.7.1
9.7.0
There's a few bug fixes, and the new functionality is really for CritterWatch.
What's Changed
Full Changelog: JasperFx/marten@V9.6.0...V9.7.0
9.6.0
There's a couple tenant aware APIs that are new, so this had to be a minor point bump. The majority of the work in this release was stress testing projection rebuilds and ensuring there was never any concurrent access of un-thread safe dictionaries inside of the async daemon that happened as a side effect of 9.0 changes.
What's Changed
Full Changelog: JasperFx/marten@V9.5.3...V9.6.0
9.5.3
This is a little optimization to the new 9.* code that eliminated the runtime codegen, and a fix for the daemon being a little vulnerable to concurrency in its internals -- which is also an optimization here.
What's Changed
Full Changelog: JasperFx/marten@9.5.2...V9.5.3
9.5.2
Bug fixes
mt_archive_streamemits explicit column lists in its INSERT…SELECT, survivingALTER TABLE ADD COLUMNmigrations that reorder the physical column layout (previously failed with42804after a column was added tomt_events).BulkInsertEventsAsyncwritesmt_streams.typefrom theStreamAction'sAggregateType, restoringUseMandatoryStreamTypeDeclarationsupport on the bulk path.AddMartenManagedTenantsAsyncno longer leaves a half-installed schema underAutoCreate.None. The admin call eagerly applies the events feature via a per-featureCreateMigrationAsync+ scopedCreateOrUpdateapply, so the next append succeeds end-to-end on a virgin schema (previously failed with42P01/42883).e.tenant_id = t.tenant_id, eliminating own-event duplication under per-tenant sequences withUseTenantPartitionedEvents.Test coverage
TenantPartitionedEventsTestsproject (~170 tests across 50 files) covering append / read / projections / admin / DCB / async daemon / regressions underUseTenantPartitionedEvents.FlatTableProjection), #4651 (DetermineActionAsync), #4652 (doc-tables-NOT-partitioned-by-default invariant).AutoCreate.CreateOnlycontinues to work via the lazy schema-apply path, by design (no SUT change needed).Known follow-up — NOT in this release
AddGlobalProjection × UseTenantPartitionedEventsfailsMT002because the global event decorator writes to the*DEFAULT*tenant slot, which can't be a Postgres partition suffix. Test pin is in master asserting the throw; the underlying fix requires either routing global-aggregate events through a sibling non-partitioned table or reserving a default-tenant partition suffix. Marked as an enhancement, deferred to a later release.🤖 Release notes assembled with Claude Code
9.5.1
What's Changed
Full Changelog: JasperFx/marten@V9.5.0...V9.5.1
9.5.0
The minor point bump here is because of some CritterWatch related features, otherwise this is all bug fixes
What's Changed
New Contributors
Full Changelog: JasperFx/marten@V9.4.0...V9.5.0
9.4.0
Marten 9.4.0
Per-tenant event partitioning and a tenant-aware async projection daemon (#4596 / CritterWatch#209). Built on JasperFx 2.5.0.
Highlights
opts.Events.UseTenantPartitionedEvents = true. On top of conjoined event tenancy, Marten partitionsmt_events/mt_streamsbytenant_id(native PostgreSQL LIST partitioning), gives each tenant its own event sequence (mt_events_sequence_{suffix}), and keysmt_event_progressionby(name, tenant_id). Removes the single shared event store as a scalability bottleneck across tenants.{Name}:Allshard.Constraints for per-tenant partitioning
Validated at
DocumentStoreconstruction:Events.TenancyStyle = TenancyStyle.Conjoined.EventAppendMode.Quick/QuickWithServerTimestamps);EventAppendMode.Richis out of scope.Events.UseArchivedStreamPartitioning(sub-partitioning by bothtenant_idandis_archivedis a planned follow-up).The flag defaults to
false; existing stores keep the global append path byte-for-byte.Dependencies
SubscriptionAgentoptimized-rebuild double-load fix).Documentation
9.3.5
What's Changed
Full Changelog: JasperFx/marten@V9.3.4...V9.3.5
9.3.4
What's Changed
New Contributors
Full Changelog: JasperFx/marten@V9.3.3...V9.3.4
9.3.3
What's Changed
Full Changelog: JasperFx/marten@V9.3.2...V9.3.3
9.3.2
What's Changed
Full Changelog: JasperFx/marten@V9.3.1...V9.3.2
9.3.1
Marten 9.3.1
Fix release — bumps all four
JasperFx.*dependencies to 2.2.1.JasperFxJasperFx.EventsJasperFx.Events.SourceGeneratorJasperFx.SourceGeneratorNo Marten-side code changes — straight dependency bump (#4585).
Full Changelog: JasperFx/marten@V9.3.0...V9.3.1
9.3.0
Marten 9.3.0
The big-ticket items in this release are binary event serialization (#4515) and the PostGIS + pgvector companion packages lifted into the Marten repo from CritterWatch.
Major
Binary event serialization for the event store (#4515 — landed across #4578, #4581, #4583, #4584). Opt individual event types into a binary wire format (MemoryPack out of the box, or any
IEventBinarySerializeryou bring) on a per-event-type basis. JSON-serialized and binary-serialized events coexist in the samemt_eventstable so the feature can be turned on in an existing system with no migration of existing data. Works on everyEventAppendMode(Rich + Quick + QuickWithServerTimestamps) and throughBulkEventAppender. New optional NuGet:Marten.MemoryPack. See the binary-serialization docs for the design, registration, and the versioned-event-types schema-evolution recommendation.PostGIS + pgvector companion packages (#4576). Two new optional NuGets imported from CritterWatch:
Marten.PostGIS—UsePostGIS()opt-in that enables thepostgisextension on every database Marten manages (multi-tenant aware), wires NetTopologySuite + GeoJSON serialization, and exposes four spatial query helpers (NearestToAsync,WithinDistanceAsync,ContainingAsync,IntersectingAsync). See the PostGIS docs.Marten.PgVector—UsePgVector()opt-in that enables thevectorextension on every database (also addresses #2515 — extensions in tenant databases).VectorSearchAsyncfor similarity search plus an embedding-awareVectorProjectionbase class. See the pgvector docs.Fixes
CreatedAt.MapTo()regression in v9 (#4577). The closed-shape storage rewrite ported every other metadata-column read-back but missedmt_created_at; this restores the v8 behavior where a[CreatedAt]-annotated /m.CreatedAt.MapTo(...)-mapped member is populated after a load.Build / Release
Pack target updated (#4582).
Marten.PostGIS,Marten.PgVector, andMarten.MemoryPackare now included in the NukePacktarget — without this they would silently never reach NuGet. 9 packages ship in 9.3.0 (up from 6):Marten,Marten.Newtonsoft,Marten.NodaTime,Marten.AspNetCore,Marten.EntityFrameworkCore,Marten.SourceGenerator,Marten.PostGIS,Marten.PgVector,Marten.MemoryPack.Weasel 9.0.2 dependency bump (JasperFx/weasel#299). Fixes
PostgresqlMigrator.executeWithConcurrencyRetryAsyncto reopen a Closed/Broken connection between retry attempts — eliminates the intermittentConnection is not openfailure surfaced under concurrent migration races.Documentation updates
Pages added or updated in 9.3.0:
Local docker
The local
docker-compose.yml(from #4576) layerspostgresql-17-postgis-3+postgresql-17-pgvectoron the official multi-archpostgres:17image so the Marten test suite can exercise the new extensions locally. PLv8 was dropped — Marten core SQL no longer requires it.Full Changelog: JasperFx/marten@V9.2.1...V9.3.0
9.2.1
What's Changed
Full Changelog: JasperFx/marten@V9.2.0...V9.2.1
9.2.0
Marten 9.2.0
Features & changes
IEventStore.AllDatabases()onDocumentStore(#4570, #4571). Implements the store-agnostic database accessor added toJasperFx.Events.IEventStore. Delegates straight toITenancy(mirroringIMartenStorage.AllDatabases()) and projects toIEventDatabase, so store-neutral monitoring/tooling can reach every database to call the read abstractions (AllProjectionProgress,FetchDeadLetterCountsAsync/CountDeadLetterEventsAsync) even when onlyIEventStoreis registered in DI.Dependencies
JasperFx.*packages to 2.2.0 (JasperFx,JasperFx.Events,JasperFx.Events.SourceGenerator,JasperFx.SourceGenerator).Full Changelog: JasperFx/marten@V9.0.2...V9.2.0
9.0.2
Marten 9.0.2
A patch release that fixes #4557 — self-aggregating projections failing for consumers that reference only the
Martenpackage.Fixes
#4557 — Self-aggregating projections now work out of the box. Marten 9 dispatches conventional
Apply/Create/ShouldDeleteprojection methods through the compile-timeJasperFx.Events.SourceGeneratorand has no runtime fallback, but the generator shipped as aDevelopmentDependencyand never flowed to a consumer that only referenced theMartenpackage — surfacing asInvalidProjectionException: No source-generated dispatcher found ...atDocumentStore.For(...). Marten now bundles the analyzer in its own NuGet package, so a plain<PackageReference Include="Marten" />runs the generator automatically. (#4558)Self-aggregating
recordaggregates work without aSnapshot<T>call site and withoutpartial. BumpedJasperFx.Events/JasperFx.Events.SourceGeneratorto 2.1.1 (JasperFx/jasperfx#367): the generator now emits a self-aggregating evolver for arecordfrom its own declaration (parity with classes), which also fixes the cross-assembly case where the aggregate type is defined in a different assembly than its registration.Docs. Corrected the migration guide's projection section, which incorrectly stated Marten falls back to a runtime evolver lookup for non-
partialconvention projections; documented that self-aggregatingSnapshot<T>types do not need to bepartial(only projection subclasses do).Dependency bumps
JasperFx.Events2.1.0 → 2.1.1JasperFx.Events.SourceGenerator2.1.0 → 2.1.1No public API changes from 9.0.1.
9.0.1
Marten 9.0.1
A patch release on the Critter Stack 2026 foundation, rolling up the latest JasperFx 2.0.1 / JasperFx.Events 2.1.0 / Weasel 9.0.1 dependencies along with several source-generator and reliability fixes.
Foundation bumps
Fixes
requiredmembers on self-aggregating snapshot types no longer break generated evolver construction;default!is emitted only when a public parameterless constructor exists, otherwiseRuntimeHelpers.GetUninitializedObjectis used.[ReadAggregate]aggregate parameters generate correctly.IEventDatabasedead-letter count reads (CountDeadLetterEventsAsync/FetchDeadLetterCountsAsync) are implemented onMartenDatabasevia LINQ over theDeadLetterEventdocument.SystemTextJsonSerializer.UseTypeInfoResolver) for AOT/trimming-friendly metadata.feature_flag_positiveadvisory-lock contention (distinctApplyChangesLockId, #4553) and the conjoined multi-tenantquery_before_savingXX000: tuple concurrently updatedmigration-DDL race (resolved upstream in Weasel 9.0.1 / weasel#293).No public API breaking changes from 9.0.0.
RestoreV8Defaults()continues to revert the 9.0 default flips.9.0.0
Marten 9.0.0 — Critter Stack 2026
The headline release of the Critter Stack 2026 wave, on the final JasperFx 2.0 + Weasel 9.0 foundation.
Highlights
net9.0;net10.0.JasperFx.RuntimeCompileris no longer a dependency. Document/event storage is hand-written closed-shape; compiled queries useMarten.SourceGenerator. Nocodegen writestep for Marten.Staticmode; lazy document-mapping materialization; per-query handler-factory caching.IStorageOperationrebased onWeasel.Core; async-daemon distributor concretes consumed fromJasperFx.Events.Daemon;OperationRole/BulkInsertModerelocated toWeasel.Core.QuickWithServerTimestampsappend mode, advanced async tracking, bigint events, lightweight default sessions, System.Text.Json default — all revertable viaRestoreV8Defaults().IRevisioned.Versionstaysint(V8-compatible); newILongVersioned(long) forMultiStreamProjectiondocuments.FetchForWritingByTags<T>for identity-less boundary aggregates.See the migration guide (
docs/migration-guide.md). Master plan: marten#4349. Ships in lockstep with Polecat 4.0.8.37.4
Security release. Fixes SQL injection in the LINQ provider via unescaped string literals.
Several LINQ code paths interpolated a runtime, potentially attacker-influenced value into generated SQL as a single-quoted literal without escaping or parameterization; a value containing a single quote could break out and inject SQL. The primary vector — a
Dictionary<,>indexer key in aWherefilter — was reported privately with an executed proof-of-concept (filter / multi-tenant authorization bypass, blind exfiltration).Fixed sinks (this 8.x line):
DictionaryItemMember— dictionary indexer keyDictionaryContainsKeyFilter—ContainsKeykey (Newtonsoft serializer + Enum branch)SelectParser— constant string projected viaSelect(...)All users on 8.x should upgrade. A GitHub Security Advisory (with CVE) is being coordinated.
Back-port of #4911 (9.x).
8.37.3
Maintenance release on the 8.0 line.
Fixes
#4718 —
projections rebuildmust skip subscriptions. When an event subscription was registered (e.g. Wolverine'sPublishEventsToWolverine(...)withSubscribeFromPresent()),dotnet run -- projections rebuildthrewNo registered projection matches the name '...'. A subscription isAsync, so its name was fed into the rebuild path →RebuildProjectionAsync→TryFindProjection(which only searches projections). The rebuild path now skips event subscriptions andLive-lifecycle projections. Subscriptions still run continuously and still appear inprojections list; only rebuild skips them, and a subscription name passed explicitly to rebuild is a clean no-op.Backported to the JasperFx 1.x line in JasperFx.Events 1.36.2 (JasperFx/jasperfx#460, tracked by JasperFx/jasperfx#459).
Dependencies
1.35.0→1.36.21.29.1→1.31.08.37.2
Patch release containing #4599:
EnumerableContains.Parsecrash on programmatically-builtContains()receivers (e.g. HotChocolate's[UseFiltering]inoperator) when the wrapper type overridesToString(). See #4600 (master) and #4601 (8.0 backport).8.37.1
What's Changed
Full Changelog: JasperFx/marten@V8.37.0...V8.37.1
Commits viewable in compare view.
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)