Skip to content

Bump the nuget-minor-patch group with 9 updates - #172

Open
dependabot[bot] wants to merge 2 commits into
mainfrom
dependabot/nuget/nuget-minor-patch-aaba841bf6
Open

Bump the nuget-minor-patch group with 9 updates#172
dependabot[bot] wants to merge 2 commits into
mainfrom
dependabot/nuget/nuget-minor-patch-aaba841bf6

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 1, 2026

Copy link
Copy Markdown
Contributor

Updated AndreGoepel.Core from 1.0.0 to 1.0.1.

Release notes

Sourced from AndreGoepel.Core's releases.

1.0.1

What's Changed

New Contributors

Full Changelog: andregoepel/core@v1.0.0...v1.0.1

Commits viewable in compare view.

Updated AndreGoepel.Marten.Identity.Blazor from 1.8.0 to 1.9.0.

Release notes

Sourced from AndreGoepel.Marten.Identity.Blazor's releases.

1.9.0

What's Changed

Full Changelog: andregoepel/marten-identity@v1.8.1...v1.9.0

1.8.1

What's Changed

Full Changelog: andregoepel/marten-identity@v1.8.0...v1.8.1

Commits viewable in compare view.

Updated Marten from 9.19.0 to 9.22.2.

Release notes

Sourced from Marten's releases.

9.22.1

Security release. Upgrade is recommended for anyone using sharded tenancy together with Events.UseTenantPartitionedEvents.

A tenant id was interpolated into a double-quoted PostgreSQL identifier without doubling an embedded double quote, so a tenant id containing one could terminate the identifier and execute additional SQL statements. This is a different class from the two advisories previously published on this repository, both of which were the single-quoted string-literal class; neither of those fixes addressed this.

You are affected only if you use sharded tenancy, have UseTenantPartitionedEvents enabled, and your application passes attacker-influenced input as a tenant id. Note that the reachable surface includes ordinary session resolution, not just administrative provisioning calls — GetTenantAsync / FindOrCreateDatabase auto-provision an unknown tenant. Applications using tenant ids from a trusted fixed set are not exploitable.

Affected versions: 9.4.0 through 9.22.0.

Full details, including remediation guidance for existing data, are in the security advisory: GHSA-3vp4-34pf-2rcw

What changed

  • PerTenantEventSequences.QuotedSequenceName escapes embedded quotes, matching quote_ident/%I so the name still resolves to the same object the quick-append function finds. Covers the create, drop, schema-apply and cleanup paths.
  • BulkEventAppender no longer builds an unquoted sequence name from a suffix read back out of the tenants table. This also fixes a functional bug: PreserveSourceSequence bulk imports previously failed with 42601 for hyphenated and GUID tenant ids under sharded tenancy.
  • ShardedTenancy validates tenant ids destined for DDL, closing a long-standing asymmetry with the DefaultTenancy provisioning path. It is a narrow denylist rather than the existing identifier allowlist, so hyphenated and GUID tenant ids keep working.

Dependency

Requires Weasel.Postgresql 9.21.1, which escapes partition bound values (JasperFx/weasel#​416). Both halves are needed; the dependency is pulled in automatically.

Credit to Barak Srour (Apiiro) for the report.

9.22.0

The partitioning feature is new, but otherwise this was all about CritterWatch improvements for a huge installation

What's Changed

Full Changelog: JasperFx/marten@V9.21.0...V9.22.0

9.21.0

Highlights

A small, low-risk release: two bug fixes reported against 9.20.x, a LINQ ordering fix, a Newtonsoft serialization fix, and a new health-check overload for Wolverine-managed daemon distribution.

[!NOTE]
There is a change to the mt_quick_append_events PostgreSQL function in this release, and applying it is NOT mandatory or required.

You do not need to patch your database, schedule a migration, or coordinate a deployment window to take 9.21.0. The client-side half of the #​5062 fix ships in the assembly, so upgrading the NuGet package alone is sufficient — 9.21.0 is correct against the function version you already have deployed.

Under the default AutoCreate.CreateOrUpdate the function is simply refreshed the next time Marten ensures event storage exists (a CREATE OR REPLACE FUNCTION, no lock on your event data). If you run AutoCreate.None with db-patch / db-apply, your next patch will contain one extra CREATE OR REPLACE FUNCTION … mt_quick_append_events statement — apply it whenever it suits your normal cadence. See the migration guide for details.

Bug Fixes

mt_quick_append_events returned {NULL} for an empty event array (#​5062, #​5088)

array_length('{}', 1) is NULL in PostgreSQL rather than 0, so calling the bulk append function with no events returned a bigint[] whose single element was NULL. Npgsql could not read that into long[], and the resulting InvalidCastException was thrown from the batch's post-processing loop — where it displaced whatever exception had actually made the append fail. Callers were left with an unrelated, non-retryable error instead of the real one; for the reporter that dead-lettered Wolverine messages which would otherwise have been retried.

Fixed on three fronts:

  • The function now COALESCEs the array length, so an empty append means what it says: zero events appended, final version unchanged.
  • The append operation no longer reads the returned array when the batch carries no events — this is what makes the fix effective without any database change.
  • The one code path in Marten that could reach the function with empty arrays (ProjectionUpdateBatch.WaitForCompletion, for an Append side effect that ended up with no events) no longer issues the call.

OrderBy against a dictionary indexer dropped the key (#​5063, #​5073)

OrderBy(x => x.SomeDictionary["key"]) generated SQL that ignored the indexer key, so the ordering was wrong (or arbitrary) rather than failing loudly.

Lazy LINQ sequences serialized as objects under Newtonsoft (#​5076, #​5080)

A document property holding a deferred-execution sequence (Select(...), Where(...) without a materializing call) was written by Newtonsoft as an iterator object rather than a JSON array, so it would not round-trip. These are now written as plain arrays.

IMessageBatch is called concurrently (#​5065, #​5085)

Not a behavior change, but a documentation fix worth flagging if you implement IMessageBatch yourself: the async daemon raises projection side effects from multiple threads at once (measured at up to 8 concurrent publishers across 10 threads for a single-stream projection catching up). The interface previously said nothing about this. An implementation that appends to an unsynchronized collection will silently drop messages — the same hazard, in a real outbox, that showed up here as a "flaky" test.

New

Provider-aware databaseFilter for the high-water health check (#​5061, #​5089)

AddMartenHighWaterHealthCheck's databaseFilter is captured at registration time, so it cannot resolve services — which makes it unable to express "the databases this node currently owns" when ownership is runtime state. That is precisely the case under Wolverine-managed daemon distribution, where agents are assigned per (database, tenant) and rebalanced over a node's lifetime.

There is now an overload whose filter receives the IServiceProvider and is re-evaluated on every probe:

Services.AddHealthChecks().AddMartenHighWaterHealthCheck(
    (services, database) => services.GetRequiredService<IWolverineRuntime>()
        .Agents.AllLocallyOwnedDatabaseIds()
        .Any(id => id.Name.EqualsIgnoreCase(database.Identifier)),
    staleThreshold: TimeSpan.FromSeconds(30),
    includeExternallyManaged: true);
 ... (truncated)

## 9.20.2

## What's Changed
* Fix NgramIndex to match NgramSearch's unaccent-aware mt_grams_vector expression by @​dat-honguyen in https://github.com/JasperFx/marten/pull/5060

## New Contributors
* @​dat-honguyen made their first contribution in https://github.com/JasperFx/marten/pull/5060

**Full Changelog**: https://github.com/JasperFx/marten/compare/V9.20.1...V9.20.2

## 9.20.1

Two real improvements:
1. Less log noise and faster/cleaner shutdowns at production time
2. Adjustments to the "high water mark" detection to ignore idle transactions from advisory locks in advancing the high water mark. This was a side effect of the extra work we did in 9.18 to try to stop event skipping from slow transactions

## What's Changed
* fix(#​4953): allocation fence keeps idle advisory-lock sessions from holding gap skips forever by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5057
* Adopt JasperFx.Events 2.36.2: clear resolved daemons on coordinator stop, idempotent AddAsyncDaemon by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5058


**Full Changelog**: https://github.com/JasperFx/marten/compare/V9.20.0...V9.20.1

## 9.20.0

Bug fixes around permutations of the natural key usage, new convenience mechanisms for querying for event store data

## What's Changed
* chore(deps-dev): bump find-my-way from 9.5.0 to 9.7.0 by @​dependabot[bot] in https://github.com/JasperFx/marten/pull/5045
* chore(deps-dev): bump postcss from 8.5.14 to 8.5.23 by @​dependabot[bot] in https://github.com/JasperFx/marten/pull/5046
* Retire the previous natural key row when the key changes (#​5041) by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5049
* Add FetchStreamStatePlan + FetchStreamPlan: raw event stream fetches as batchable query plans by @​uniquelau in https://github.com/JasperFx/marten/pull/5043
* StreamEventState + StreamEvents result types for Marten.AspNetCore by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5053
* Natural key table: scope the FK guard, and land the partitioned-FK repro (#​5044) by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5050
* Adopt JasperFx.Events 2.36.0: shard failure classification, drain timeout docs, natural key extraction by @​jeremydmiller in https://github.com/JasperFx/marten/pull/5054


**Full Changelog**: https://github.com/JasperFx/marten/compare/V9.19.0...V9.20.0

Commits viewable in [compare view](https://github.com/JasperFx/marten/commits).
</details>

Updated [Npgsql](https://github.com/npgsql/npgsql) from 9.0.4 to 9.0.5.

<details>
<summary>Release notes</summary>

_Sourced from [Npgsql's releases](https://github.com/npgsql/npgsql/releases)._

## 9.0.5

v9.0.5 contains several minor bug fixes.

[Milestone issues](https://github.com/npgsql/npgsql/milestone/131?closed=1)

**Full Changelog**: https://github.com/npgsql/npgsql/compare/v9.0.4...v9.0.5

Commits viewable in [compare view](https://github.com/npgsql/npgsql/compare/v9.0.4...v9.0.5).
</details>

Updated [Quartz.Extensions.Hosting](https://github.com/quartznet/quartznet) from 3.18.2 to 3.19.1.

<details>
<summary>Release notes</summary>

_Sourced from [Quartz.Extensions.Hosting's releases](https://github.com/quartznet/quartznet/releases)._

## 3.19.1

Quartz.NET 3.19.1 is a small bug fix release with two targeted fixes: `DailyTimeIntervalTrigger` no longer gets stuck in an infinite fire loop on DST spring-forward days, and `StdSchedulerFactory.GetScheduler(schedName)` now creates the scheduler when the name asked for is its own. There are no API or schema changes, so it is a drop-in upgrade from 3.19.0.

## Highlights

- **`DailyTimeIntervalTrigger` no longer spins on DST transition days** — `GetFireTimeAfter` could return a time at or before the one it was given, which makes `QuartzSchedulerThread` fire the trigger, compute the same next fire time, and fire again — pinning a CPU core and flooding the log. Two independent causes, both on a spring-forward day: the DST correction added for #​1114 was applied to every interval size and in either direction (so every interval of an hour or less was affected, in every DST time zone), and the daily rollover to `StartTimeOfDay` reused whatever UTC offset the previous fire time carried (so in time zones that move the clock at midnight, such as Chile, `StartTimeOfDay` 00:00 resolved to an instant *before* the transition — the same instant that was passed in). Verified across 3024 combinations of 12 time zones, both transitions, 21 intervals and 6 start times: 468 combinations produced non-advancing fire times before, none do now. (#​3190, fixes #​332)
  - **Behavior change worth noting:** the same fix stops sub-hour triggers silently dropping the last hour of a **fall-back** day. A 5-minute trigger now fires 300 times through the 25-hour day, ending at 23:55 local, instead of 288 times ending at 22:55.
- **`StdSchedulerFactory.GetScheduler(schedName)` creates its own scheduler** — asking a factory for the scheduler it is configured to produce returned `null` until somebody had called `GetScheduler()` first. It now creates it. Any other name stays a pure lookup, so probing for a scheduler somebody else owns still has no side effects, and the name comparison is case-insensitive to match how `SchedulerRepository` indexes names. The DI factory has behaved this way since #​2845; this brings the property-configured factory in line. (#​3188, reported in #​2786, originally proposed in #​360)

## What's Changed
* Create the scheduler when it is looked up by its own name (#​360) by @​lahma in https://github.com/quartznet/quartznet/pull/3188
* Fix DailyTimeIntervalTrigger infinite fire loop during DST spring-forward (#​332) by @​lahma in https://github.com/quartznet/quartznet/pull/3190


**Full Changelog**: https://github.com/quartznet/quartznet/compare/v3.19.0...v3.19.1


## 3.19.0

Quartz.NET 3.19.0 is a feature release: it adds node affinity for clustered scheduling, a fluent cron-expression builder, and richer `L`/`LW` day-of-month expressions, plus clock-jump resilience and a modernized build and publishing pipeline. The public API is unchanged (all additions are additive), so it is a drop-in upgrade — with two things to note: the new node-affinity columns are an **optional** schema migration (the feature degrades gracefully without them), and a handful of previously-broken `L`/`LW`/`W` cron expressions now fire correctly (see below).

## Highlights

- **Node affinity for clustered trigger pinning** — pin a trigger to a preferred node with `TriggerBuilder.WithPreferredNode(...)`; the node is preferred for acquisition but the trigger is still stolen on failover so it is never stranded if that node goes down. Adds optional `PREFERRED_NODE` / `PREFERRED_NODE_AUTO` columns for ADO.NET job stores (`database/schema_30_add_preferred_node.sql`); when the columns are absent the scheduler logs a warning and behaves exactly as before. (#​3013, #​3144)
- **Fluent `CronExpressionBuilder`** — compose cron expressions programmatically, one field at a time, instead of hand-writing the string — handy when a schedule is assembled from user input such as a scheduling UI. (#​3139)
- **`L` and `LW` combinable with other day-of-month values** — the day-of-month field now accepts expressions such as `1,15,L` and the new `LW-n` / `L-nW` grammar. This also corrects several previously-buggy edge cases: `29W`/`31W` no longer silently skip short months, `L-30W` no longer throws mid-schedule, and `1,15W` now applies `W` to each day rather than only the first. **These corrections change the fire times of a few expressions that were previously broken** — review any stored `L`/`LW`/`W` day-of-month expressions. (#​2759)
- **Resilience to system clock jumps** — the misfire handler and cluster manager now clamp their sleep intervals after the system clock jumps forward or backward, so a clock step no longer causes a busy-spin or an absurdly long sleep. (#​3147, fixes #​1508)
- **Modernized build & publishing** — the build orchestrator moved from the unmaintained NUKE to Fallout (#​3163), and packages now publish to nuget.org via GitHub OIDC **trusted publishing** rather than a stored API key. Dependencies were also refreshed (#​3151).

**Note for `CronScheduleBuilder` users:** `AtHourAndMinuteOnGivenDaysOfWeek` / `WeeklyOnDayAndHourAndMinute` now emit textual day-of-week names (e.g. `MON,WED` rather than `2,4`). The schedules are identical, but the generated `CRON_EXPRESSION` string differs — relevant only if you compare stored cron strings byte-for-byte.

## What's Changed
* Serve Blazor plumbing under custom DashboardPath for prefix-forwarding reverse proxies (3.x) (#​3134) by @​lahma in https://github.com/quartznet/quartznet/pull/3137
* Add fluent CronExpressionBuilder for building cron expressions programmatically (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3139
* Support for specifying 'L' and 'LW' with other days in day-of-month field by @​lahma in https://github.com/quartznet/quartznet/pull/2759
* Add preferred node (node affinity) for cluster trigger pinning by @​lahma in https://github.com/quartznet/quartznet/pull/3013
* Store auto-pin as a flag column instead of an "auto:" name prefix by @​lahma in https://github.com/quartznet/quartznet/pull/3144
* Clamp misfire handler and cluster manager sleeps after system clock jumps (#​1508) by @​lahma in https://github.com/quartznet/quartznet/pull/3147
* Update packages and cleanup by @​lahma in https://github.com/quartznet/quartznet/pull/3151
* Migrate the build from NUKE to Fallout (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3163
* Exclude the build orchestrator from SonarQube analysis (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3166
* Prepare v3.19.0 release by @​lahma in https://github.com/quartznet/quartznet/pull/3169


**Full Changelog**: https://github.com/quartznet/quartznet/compare/v3.18.2...v3.19.0


Commits viewable in [compare view](https://github.com/quartznet/quartznet/compare/v3.18.2...v3.19.1).
</details>

Updated [Quartz.Serialization.SystemTextJson](https://github.com/quartznet/quartznet) from 3.18.2 to 3.19.1.

<details>
<summary>Release notes</summary>

_Sourced from [Quartz.Serialization.SystemTextJson's releases](https://github.com/quartznet/quartznet/releases)._

## 3.19.1

Quartz.NET 3.19.1 is a small bug fix release with two targeted fixes: `DailyTimeIntervalTrigger` no longer gets stuck in an infinite fire loop on DST spring-forward days, and `StdSchedulerFactory.GetScheduler(schedName)` now creates the scheduler when the name asked for is its own. There are no API or schema changes, so it is a drop-in upgrade from 3.19.0.

## Highlights

- **`DailyTimeIntervalTrigger` no longer spins on DST transition days** — `GetFireTimeAfter` could return a time at or before the one it was given, which makes `QuartzSchedulerThread` fire the trigger, compute the same next fire time, and fire again — pinning a CPU core and flooding the log. Two independent causes, both on a spring-forward day: the DST correction added for #​1114 was applied to every interval size and in either direction (so every interval of an hour or less was affected, in every DST time zone), and the daily rollover to `StartTimeOfDay` reused whatever UTC offset the previous fire time carried (so in time zones that move the clock at midnight, such as Chile, `StartTimeOfDay` 00:00 resolved to an instant *before* the transition — the same instant that was passed in). Verified across 3024 combinations of 12 time zones, both transitions, 21 intervals and 6 start times: 468 combinations produced non-advancing fire times before, none do now. (#​3190, fixes #​332)
  - **Behavior change worth noting:** the same fix stops sub-hour triggers silently dropping the last hour of a **fall-back** day. A 5-minute trigger now fires 300 times through the 25-hour day, ending at 23:55 local, instead of 288 times ending at 22:55.
- **`StdSchedulerFactory.GetScheduler(schedName)` creates its own scheduler** — asking a factory for the scheduler it is configured to produce returned `null` until somebody had called `GetScheduler()` first. It now creates it. Any other name stays a pure lookup, so probing for a scheduler somebody else owns still has no side effects, and the name comparison is case-insensitive to match how `SchedulerRepository` indexes names. The DI factory has behaved this way since #​2845; this brings the property-configured factory in line. (#​3188, reported in #​2786, originally proposed in #​360)

## What's Changed
* Create the scheduler when it is looked up by its own name (#​360) by @​lahma in https://github.com/quartznet/quartznet/pull/3188
* Fix DailyTimeIntervalTrigger infinite fire loop during DST spring-forward (#​332) by @​lahma in https://github.com/quartznet/quartznet/pull/3190


**Full Changelog**: https://github.com/quartznet/quartznet/compare/v3.19.0...v3.19.1


## 3.19.0

Quartz.NET 3.19.0 is a feature release: it adds node affinity for clustered scheduling, a fluent cron-expression builder, and richer `L`/`LW` day-of-month expressions, plus clock-jump resilience and a modernized build and publishing pipeline. The public API is unchanged (all additions are additive), so it is a drop-in upgrade — with two things to note: the new node-affinity columns are an **optional** schema migration (the feature degrades gracefully without them), and a handful of previously-broken `L`/`LW`/`W` cron expressions now fire correctly (see below).

## Highlights

- **Node affinity for clustered trigger pinning** — pin a trigger to a preferred node with `TriggerBuilder.WithPreferredNode(...)`; the node is preferred for acquisition but the trigger is still stolen on failover so it is never stranded if that node goes down. Adds optional `PREFERRED_NODE` / `PREFERRED_NODE_AUTO` columns for ADO.NET job stores (`database/schema_30_add_preferred_node.sql`); when the columns are absent the scheduler logs a warning and behaves exactly as before. (#​3013, #​3144)
- **Fluent `CronExpressionBuilder`** — compose cron expressions programmatically, one field at a time, instead of hand-writing the string — handy when a schedule is assembled from user input such as a scheduling UI. (#​3139)
- **`L` and `LW` combinable with other day-of-month values** — the day-of-month field now accepts expressions such as `1,15,L` and the new `LW-n` / `L-nW` grammar. This also corrects several previously-buggy edge cases: `29W`/`31W` no longer silently skip short months, `L-30W` no longer throws mid-schedule, and `1,15W` now applies `W` to each day rather than only the first. **These corrections change the fire times of a few expressions that were previously broken** — review any stored `L`/`LW`/`W` day-of-month expressions. (#​2759)
- **Resilience to system clock jumps** — the misfire handler and cluster manager now clamp their sleep intervals after the system clock jumps forward or backward, so a clock step no longer causes a busy-spin or an absurdly long sleep. (#​3147, fixes #​1508)
- **Modernized build & publishing** — the build orchestrator moved from the unmaintained NUKE to Fallout (#​3163), and packages now publish to nuget.org via GitHub OIDC **trusted publishing** rather than a stored API key. Dependencies were also refreshed (#​3151).

**Note for `CronScheduleBuilder` users:** `AtHourAndMinuteOnGivenDaysOfWeek` / `WeeklyOnDayAndHourAndMinute` now emit textual day-of-week names (e.g. `MON,WED` rather than `2,4`). The schedules are identical, but the generated `CRON_EXPRESSION` string differs — relevant only if you compare stored cron strings byte-for-byte.

## What's Changed
* Serve Blazor plumbing under custom DashboardPath for prefix-forwarding reverse proxies (3.x) (#​3134) by @​lahma in https://github.com/quartznet/quartznet/pull/3137
* Add fluent CronExpressionBuilder for building cron expressions programmatically (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3139
* Support for specifying 'L' and 'LW' with other days in day-of-month field by @​lahma in https://github.com/quartznet/quartznet/pull/2759
* Add preferred node (node affinity) for cluster trigger pinning by @​lahma in https://github.com/quartznet/quartznet/pull/3013
* Store auto-pin as a flag column instead of an "auto:" name prefix by @​lahma in https://github.com/quartznet/quartznet/pull/3144
* Clamp misfire handler and cluster manager sleeps after system clock jumps (#​1508) by @​lahma in https://github.com/quartznet/quartznet/pull/3147
* Update packages and cleanup by @​lahma in https://github.com/quartznet/quartznet/pull/3151
* Migrate the build from NUKE to Fallout (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3163
* Exclude the build orchestrator from SonarQube analysis (3.x) by @​lahma in https://github.com/quartznet/quartznet/pull/3166
* Prepare v3.19.0 release by @​lahma in https://github.com/quartznet/quartznet/pull/3169


**Full Changelog**: https://github.com/quartznet/quartznet/compare/v3.18.2...v3.19.0


Commits viewable in [compare view](https://github.com/quartznet/quartznet/compare/v3.18.2...v3.19.1).
</details>

Updated [Radzen.Blazor](https://github.com/radzenhq/radzen-blazor) from 11.1.7 to 11.2.0.

<details>
<summary>Release notes</summary>

_Sourced from [Radzen.Blazor's releases](https://github.com/radzenhq/radzen-blazor/releases)._

## 11.2.0

# 11.2.0 - 2026-07-30

### Fixes
- **RadzenUpload** - no longer throws `NullReferenceException` in `OnAfterRenderAsync` when re-rendered or disposed while its JS handlers are being recreated, and no longer raises `Complete` twice for a single upload. Fixes #​2635.
- **RadzenDataGrid, RadzenDatePicker, RadzenDropDown, RadzenFileInput** - no longer leak a .NET JS interop proxy every time their JS handlers are recreated.
- **RadzenAccordion, RadzenAutoComplete, RadzenCarousel, RadzenFormField, RadzenGoogleMap, RadzenHtmlEditor, RadzenMask, RadzenMenu, RadzenNumeric, RadzenProfileMenu, RadzenSecurityCode, RadzenSignaturePad, RadzenSlider, RadzenSplitButton** - protected against the same JS handler race that could throw `NullReferenceException` or attach duplicate JS event handlers.

## 11.1.8

# 11.1.8 - 2026-07-27

### Fixes
- **RadzenTextBox, RadzenTextArea, RadzenMask, RadzenPassword, RadzenAutoComplete** - bound inputs no longer reset their displayed value when used inside a `RenderFragment` created by another component - most commonly inline dialog content passed to `DialogService.OpenAsync`. Such fragments never re-flow parameters, so the component kept a stale value and wiped the typed text from the input on blur while the bound variable kept it. The local value assignment is now unconditional, matching Blazor's own `InputBase` behavior.
- **Popups** - popups no longer get permanently stuck open when the closing animation never runs or is canceled - e.g. app-level CSS such as reduced-motion resets with `animation: none`. Closing now hides the popup immediately when no close animation is actually running, and the `ClosePopup()` API reliably recovers a stuck popup. Fixes #​2601.
- **RadzenDialog** - opening a nested dialog no longer breaks resize and drag handling of the outer dialog. Each dialog now has its own resize observer and titlebar drag handler instead of sharing a single global slot. Thanks to @​I-Info!
- **RadzenUpload** - the `Method` and `Stream` parameters are now honored when uploading via the `Upload()` method with `Auto=false`. The manual upload path always sent a POST multipart request regardless of the configured method.


Commits viewable in [compare view](https://github.com/radzenhq/radzen-blazor/compare/v11.1.7...v11.2.0).
</details>

Updated [WolverineFx.Marten](http://github.com/jasperfx/wolverine) from 6.22.0 to 6.24.2.

<details>
<summary>Release notes</summary>

_Sourced from [WolverineFx.Marten's releases](http://github.com/jasperfx/wolverine/releases)._

## 6.24.2

## What's Changed
* Fix the chronic CISqlServer red: give the DLQ expiration suite its own schema by @​jeremydmiller in https://github.com/JasperFx/wolverine/pull/3743
* Stop one bad property getter from killing the whole capabilities snapshot (GH-3740) by @​jeremydmiller in https://github.com/JasperFx/wolverine/pull/3741
* Fix InvalidCastException starting a NATS listener with a dead-letter subject (GH-3739) by @​jeremydmiller in https://github.com/JasperFx/wolverine/pull/3742


**Full Changelog**: https://github.com/JasperFx/wolverine/compare/V6.24.1...V6.24.2

## 6.24.1

Patch release. Four reported issues, all with reproductions from production clusters.

## Fixes

**[#​3701](https://github.com/JasperFx/wolverine/issues/3701) — `wolverine_node_records` grows without bound** ([#​3734](https://github.com/JasperFx/wolverine/pull/3734))

A reporting cluster reached 36,135,221 rows / 16 GB in five days on a diagnostic table nothing on the hot path reads. Three distinct defects:

- `INodeAgentPersistence.DeleteOldNodeRecordsAsync` was implemented for every relational store and never invoked outside tests.
- The pruning that *did* run bounds the table by **age only** (`NodeEventRecordExpirationTime`, 5 days), which is no ceiling at all at high write rates — every one of those 36M rows was inside the window.
- That age sweep's hourly throttle was dead. Its backing field was never assigned (the `CS0649` suppression on it said so), so a full-table delete went out on **every recovery cycle** — every 5 seconds by default.

New `Durability.NodeRecordRetention` (default 10,000 rows) and `Durability.NodeRecordPruningPeriod` (default hourly). `MultiTenantedMessageStore` now delegates the trim to the main store instead of inheriting a no-op default, and Sqlite, MySQL and Oracle gained implementations they had also been missing.

**[#​3697](https://github.com/JasperFx/wolverine/issues/3697) — no supported force-catch-up under Wolverine-managed event subscription distribution** ([#​3735](https://github.com/JasperFx/wolverine/pull/3735))

Wolverine already implemented the coordinator-driven catch-up path, but only exposed it as a `TrackActivity()` stage. Adds the standalone entry point on `IHost` and `IServiceProvider`, plus `<T>` ancillary-store variants:

```csharp
await host.PauseThenCatchUpOnMartenDaemonActivityAsync();
await host.PauseThenCatchUpOnMartenDaemonActivityAsync(CatchUpMode.AndDoNothing);
await host.PauseThenCatchUpOnMartenDaemonActivityAsync<IMyStore>();

It never calls IProjectionDaemon.CatchUpAsync — doing so under a live coordinator is what produces the ProgressionProgressOutOfOrderException and pk_mt_event_progression duplicate-key errors suites have been retrying around. Resuming the agents that already own the shards means there is only ever one writer.

#​3733 — a comma in an agent Uri voided a whole batch confirmation (#​3736)

AgentsStarted, StartAgents, AgentsStopped and StopAgents joined their Uri[] on a comma, which RFC 3986 permits unescaped in a path segment. Agent URIs embed tenant ids and projection names, so one comma shattered an agent into fragments — and because the read side built the array in a single projection, the resulting throw took out the confirmation for the entire batch. Newline is the delimiter now, and entries are parsed individually so a bad one names itself.

The comma remains the default on the wire for payloads that do not contain one, so rolling upgrades keep working in both directions.

#​3706 — RabbitMQ acks were cumulative (#​3737)

Every ack went out as BasicAckAsync(tag, multiple: true), acknowledging every lower delivery tag on the channel. That is only correct when completions happen in delivery order, and they do not with ConsumerDispatchConcurrency > 1 — acking one message silently acknowledged deliveries whose handlers were still running, and a crash at that moment lost them.

Acks are now per message. Two dead-letter paths that relied on the cumulative sweep settle themselves, most importantly the un-mappable-message branch in WorkerQueueMessageConsumer, which dead-lettered and returned without touching the delivery at all. This unblocks the planned native-ack parallel endpoint mode.

Also included

  • #​3730 — compliance coverage for a pause and node loss landing on in-flight assignments (GH-3698)
  • #​3732 — seed the departed node's inbox rows as already owned (GH-3729)

6.24.0

Two data-loss fixes — but for unusual usages

This release closes two bugs that silently destroyed data rather than failing loudly. Both are worth reading before you skip the rest of these notes.

Durable inbox rows were orphaned when a circuit breaker tripped (#​3680). DurableReceiver checked its latched flag before calling MarkReceived. The latched path still persists each envelope to the inbox as a safety net — but on an envelope that never went through MarkReceived, Status is the enum default (Outgoing) and Destination is null. Both are filter columns for inbox recovery, so the rows were written in a state no recovery sweep on any node could ever see. The null Listener also skipped the nack back to the broker, and the broker's redelivery after restart hit DuplicateIncomingEnvelopeException — which acks and drops. Net result: genuine message loss under a durable inbox any time a circuit breaker trip latched the receiver mid-flight. Measured on the circuit-breaker suite, 9 of 1,200 messages were lost per run.

Dropping one tenant from a shared partition bucket destroyed its co-tenants' data (#​3686). Found alongside #​3683. Tenant bucketing — registering several small tenants against one partition suffix so they share a physical partition — is documented and exposed through PartitionPerTenant(p => p.AllowPartitionSharing = true), and it did not work on either engine. It had no test coverage, because the doc sample demonstrating it is compile-only and never executed.

Global partitioning

Part of the GlobalPartitioning epic (#​3482).

  • Global partitioning topologies for PostgreSQL and SQL Server queues (#​3468, #​3469)
  • End-to-end sharded-processing suites for Azure Service Bus, GCP Pub/Sub, NATS, Redis Streams and Pulsar (#​3467). The scenario is lifted into Wolverine.ComplianceTests.Partitioning.ShardedProcessing, so a new transport costs one small test class
  • Native-mode design comparison and per-transport native alternatives documented (#​3481)

The new suites immediately found two real bugs:

  • NATS global partitioning had never worked at all. The topology forces EndpointMode.Durable on every slot, and a NatsEndpoint only supports Durable when JetStream-backed — so every UseShardedNatsSubjects() call threw at configuration time. The topology now enables JetStream on its own endpoints and declares a work-queue stream per shard, without which the listener died at startup on stream not found
  • Pulsar named its companion local queues off the full topic path, producing queues like global-persistent://public/default/orders1. They now use the topic's short name, matching every other transport

Multi-tenancy and persistence

  • EF Core tenant partition back-fill (#​3496). Routine migration deltas deliberately leave Weasel-managed partitions alone, so a table joining an existing managed set — a newly deployed service, or a newly mapped ITenanted entity — had no partition for any tenant registered before that table existed. IConjoinedTenantPartitions<T>.MigrateTenantPartitionsAsync() reconciles every partitioned table against the full registered tenant set, with per-table TenantPartitionResult reporting
  • Conjoined tenant partition bucketing actually works now, on both PostgreSQL and SQL Server (#​3683, and see #​3686 above)
  • Exclusive listener inbox recovery is now covered for RavenDb (#​3595) and CosmosDb (#​3596)

Transports

  • RabbitMQ: deliveries are settled against the channel they arrived on (#​3687). Acking a delivery on a torn-down channel threw a NullReferenceException
  • NATS: auto-provisioned JetStream durable consumers are filtered to their own subject (#​3676). FilterSubject was only assigned when ConsumerName was empty, so every durable consumer on a stream received every message. The fix needs a FilterSubjects multi-filter — a single filter cannot cover both {subject} and {subject}.scheduled, and a work-queue stream discards an uncovered control message
  • MQTT: the v5 authentication method name is configurable (#​3588). It was hardcoded to "OAUTH2-JWT". Azure Event Grid's custom JWT authentication requires CUSTOM-JWT, so those brokers could not be reached through Wolverine's authentication support at all. You could already set the method by hand through MqttClientOptionsBuilder.WithAuthentication(), but that gave up Wolverine's token refresh loop — the whole reason to use MqttJwtAuthenticationOptions. You no longer have to choose
  • The HTTP transport can send to a destination nobody pre-registered (#​3681, reported as ProductSupport#​34). WolverineHttpTransportClient used the endpoint's OutboundUri purely as an IHttpClientFactory client name, then posted to that client's BaseAddress — so operator commands sent back over the HTTP transport failed with An invalid request URI was provided

Performance

  • RabbitMQ consumer dispatch concurrency is now per-endpoint (#​3492). The client default of 1 was the bottleneck. Simulated handler, 2,000 msg/s offered load, 30s measured window:

    ConsumerDispatchConcurrency Throughput Transit p50
    1 (client default) 163.7/s — (nothing from the measured window was consumed before the run ended)
    5 828/s 22,871.9 ms
    20 1,999.1/s 1.486 ms (p95 2.54, p99 3.22)

    The 5.1x and 12.2x multiples understate it — at 1 and 5 the listener never catches up at all.

  • Amazon SQS batches message deletions and chunks outgoing batches on the 256KB request size limit (#​3493)

  • Azure Service Bus session listeners are no longer quadratic — the n² session loops are now n. MaxConcurrentCalls is surfaced, and a batched defer settles the original message (#​3494)

HTTP and gRPC

... (truncated)

6.23.1

Agent distribution

TL;DR: if you pause a projection from CritterWatch on 6.23.0, restarting it appears to do nothing for a full minute. This fixes that.

  • A paused projection or subscription agent now resumes immediately when you restart it (#​3663). On 6.23.0 the restart was accepted, the pause restriction was cleared, and then nothing happened until the pending-assignment ledger's TTL expired — 2 × CheckAssignmentPeriod, so 60 seconds with the defaults. Long enough that an operator reasonably concludes the agent is never coming back.

    The ledger introduced in 6.23.0 (#​3622) only counted an assignment as confirmed if a later evaluation saw the agent running and still assigned to the same node. A pause makes those two conditions mutually exclusive: the first evaluation that can observe the delivered assignment is the same one that detaches the agent. The entry was never confirmed, nothing on the stop path cleared it, and the restart's AssignAgent was suppressed as a duplicate still in flight. Delivery alone now confirms the entry, which is the only question the ledger was ever asking.

  • Pausing an agent no longer briefly starts it first (#​3666). ApplyRestrictionsAsync kickstarted a health check before persisting the operator's restriction change, so that evaluation ran against the old restrictions and could act against the very intent being applied — for a pause, re-assigning and starting the agent one beat before the merged evaluation stopped it again. Besides the wasted daemon start/stop cycle, this is what armed the stale ledger entry behind #​3663.

PostgreSQL

  • Advisory-lock sessions stay invisible to Marten's async-daemon gap detection (#​3664). Marten 9.16.1+ will not skip a stale event-sequence gap while any session whose open transaction predates that gap is still alive (marten#​4953). A session parked in an open transaction for the life of the process therefore reads as a permanent "possible reserver" and can hold the high-water mark — and every async projection — behind a gap that is genuinely dead.

    Wolverine's long-held locks were already shaped correctly: leader election and node coordination hold session-scoped advisory locks on a dedicated connection with no transaction, so they show up as state='idle' with a NULL xact_start. Those sessions are now also tagged application_name = 'wolverine-advisory-lock:<database>', which turns a pg_stat_activity investigation from guesswork into something you can read at a glance. The constraints are pinned in tests and in the Postgres durability docs, including the trap worth knowing in your own code: never add a keepalive query inside a long-lived open transaction — it bumps state_change, makes the session look active, and re-promotes it to candidate reserver.

    Note for combined Marten + Wolverine deployments: older guidance suggested Postgres's idle_in_transaction_session_timeout as a dead-gap backstop. Prefer upgrading Marten and using SkipStaleGapsDespiteLiveTransactionsAfter instead.

6.23.0

Projection & agent distribution

TL;DR: this prevents Wolverine from going into a panic doing agent assignments and churning crazily hard during Kubernetes rollouts or cluster starts and that's a very good thing

The bulk of this release. A wave of fixes (WO-1..8) to the agent assignment plane that together remove the re-assignment churn and livelock that could leave projection agents flapping or wedged.

  • Node heartbeats no longer block behind command execution (#​3620)
  • Node resurrection restores the node's real identity rather than a skeleton record (#​3621)
  • A pending-assignment ledger suppresses duplicate AssignAgent floods (#​3622)
  • Agent batch starts are chunked and bounded-parallel, so they stay safe at scale (#​3623)
  • Ejection hysteresis plus leader protection (#​3624)
  • The assignment row is re-upserted for agents that are already running (#​3619)
  • Local agents drain with bounded parallelism on shutdown (#​3636)
  • Paused shards now say why. IEventSubscriptionAgent.Failure surfaces a ShardFailure — category, the failing event's sequence and type, and the root exception type — through health checks and a new IWolverineObserver.AgentPaused hook plus a NodeRecordType.AgentPaused record. Failures bound to a specific event (ApplyEvent, EventSerialization, UnknownEventType) or to two processes racing one shard (ProgressionOutOfOrder) are no longer auto-restarted, since they would die on the identical event every time (#​3637, #​3638)
  • Agent starts retry locally, bounded by Durability.AgentStartRetryAttempts / AgentStartRetryDelay, instead of idling a full CheckAssignmentPeriod after a startup race (#​3519)
  • Store-scoped FindAgentUriAsync overload (#​3647) and a store-aware TryRebuildRegisteredProjectionAsync overload (#​3618)

Bumps JasperFx.Events to 2.36.1, Marten to 9.20.0 and Polecat to 5.7.0.

HTTP

  • Endpoints that advertise a request body their HTTP method cannot carry now fail fast at startup instead of silently 404ing out of the route matcher (#​3648)
  • A missing Content-Type on an [AcceptsContentType] route returns 415 rather than 404 (#​3649)
  • Query-only [AsParameters] endpoints no longer advertise a form body, which had been dropping them from route matching entirely (#​3630)
  • Explicitly-routed chains — PublishMessage<T> and SendMessage<T> — now describe the message they read from the body. They had been advertising no request body at all in OpenAPI (#​3646)
  • Enum values in query strings and form posts parse case-insensitively (#​3629)
  • Compiled queries returned as a Wolverine.Http resource no longer execute twice (#​3625)

Transports

  • Conventional routing respects named brokers (#​3633)
  • Google Pub/Sub: named-broker support for sharded and partitioned topics (#​3632), and ListenToPubsubSubscriptionOnNamedBroker (#​3631)
  • Kafka: topic-already-exists error codes are handled rather than thrown (#​3640)
  • Redis: scheduled retries survive an unreadable timestamp (#​3613), and scheduled entries that repeatedly fail to deserialize are dead-lettered instead of looping (#​3644)
  • EnvelopeMapper reads both timestamp header formats (#​3645)
  • NServiceBus interop: the EnclosedMessageTypes header is split before the message type is resolved, so interop works across Azure Service Bus, SNS, SQS and the database transports (#​3628)

Persistence

  • Oracle runs the durability agent through the shared batching mechanics (#​3614). Note that ODP.NET exposes no DbBatch, so the work splits per statement.

Other

  • Resource discovery no longer eager-connects broker transports (#​3617)

Contributors

Thank you to everyone who contributed to this release:

... (truncated)

Commits viewable in compare view.

Updated WolverineFx.RuntimeCompilation from 6.22.0 to 6.24.2.

Release notes

Sourced from WolverineFx.RuntimeCompilation's releases.

6.24.2

What's Changed

Full Changelog: JasperFx/wolverine@V6.24.1...V6.24.2

6.24.1

Patch release. Four reported issues, all with reproductions from production clusters.

Fixes

#​3701wolverine_node_records grows without bound (#​3734)

A reporting cluster reached 36,135,221 rows / 16 GB in five days on a diagnostic table nothing on the hot path reads. Three distinct defects:

  • INodeAgentPersistence.DeleteOldNodeRecordsAsync was implemented for every relational store and never invoked outside tests.
  • The pruning that did run bounds the table by age only (NodeEventRecordExpirationTime, 5 days), which is no ceiling at all at high write rates — every one of those 36M rows was inside the window.
  • That age sweep's hourly throttle was dead. Its backing field was never assigned (the CS0649 suppression on it said so), so a full-table delete went out on every recovery cycle — every 5 seconds by default.

New Durability.NodeRecordRetention (default 10,000 rows) and Durability.NodeRecordPruningPeriod (default hourly). MultiTenantedMessageStore now delegates the trim to the main store instead of inheriting a no-op default, and Sqlite, MySQL and Oracle gained implementations they had also been missing.

#​3697 — no supported force-catch-up under Wolverine-managed event subscription distribution (#​3735)

Wolverine already implemented the coordinator-driven catch-up path, but only exposed it as a TrackActivity() stage. Adds the standalone entry point on IHost and IServiceProvider, plus <T> ancillary-store variants:

await host.PauseThenCatchUpOnMartenDaemonActivityAsync();
await host.PauseThenCatchUpOnMartenDaemonActivityAsync(CatchUpMode.AndDoNothing);
await host.PauseThenCatchUpOnMartenDaemonActivityAsync<IMyStore>();

It never calls IProjectionDaemon.CatchUpAsync — doing so under a live coordinator is what produces the ProgressionProgressOutOfOrderException and pk_mt_event_progression duplicate-key errors suites have been retrying around. Resuming the agents that already own the shards means there is only ever one writer.

#​3733 — a comma in an agent Uri voided a whole batch confirmation (#​3736)

AgentsStarted, StartAgents, AgentsStopped and StopAgents joined their Uri[] on a comma, which RFC 3986 permits unescaped in a path segment. Agent URIs embed tenant ids and projection names, so one comma shattered an agent into fragments — and because the read side built the array in a single projection, the resulting throw took out the confirmation for the entire batch. Newline is the delimiter now, and entries are parsed individually so a bad one names itself.

The comma remains the default on the wire for payloads that do not contain one, so rolling upgrades keep working in both directions.

#​3706 — RabbitMQ acks were cumulative (#​3737)

Every ack went out as BasicAckAsync(tag, multiple: true), acknowledging every lower delivery tag on the channel. That is only correct when completions happen in delivery order, and they do not with ConsumerDispatchConcurrency > 1 — acking one message silently acknowledged deliveries whose handlers were still running, and a crash at that moment lost them.

Acks are now per message. Two dead-letter paths that relied on the cumulative sweep settle themselves, most importantly the un-mappable-message branch in WorkerQueueMessageConsumer, which dead-lettered and returned without touching the delivery at all. This unblocks the planned native-ack parallel endpoint mode.

Also included

  • #​3730 — compliance coverage for a pause and node loss landing on in-flight assignments (GH-3698)
  • #​3732 — seed the departed node's inbox rows as already owned (GH-3729)

6.24.0

Two data-loss fixes — but for unusual usages

This release closes two bugs that silently destroyed data rather than failing loudly. Both are worth reading before you skip the rest of these notes.

Durable inbox rows were orphaned when a circuit breaker tripped (#​3680). DurableReceiver checked its latched flag before calling MarkReceived. The latched path still persists each envelope to the inbox as a safety net — but on an envelope that never went through MarkReceived, Status is the enum default (Outgoing) and Destination is null. Both are filter columns for inbox recovery, so the rows were written in a state no recovery sweep on any node could ever see. The null Listener also skipped the nack back to the broker, and the broker's redelivery after restart hit DuplicateIncomingEnvelopeException — which acks and drops. Net result: genuine message loss under a durable inbox any time a circuit breaker trip latched the receiver mid-flight. Measured on the circuit-breaker suite, 9 of 1,200 messages were lost per run.

Dropping one tenant from a shared partition bucket destroyed its co-tenants' data (#​3686). Found alongside #​3683. Tenant bucketing — registering several small tenants against one partition suffix so they share a physical partition — is documented and exposed through PartitionPerTenant(p => p.AllowPartitionSharing = true), and it did not work on either engine. It had no test coverage, because the doc sample demonstrating it is compile-only and never executed.

Global partitioning

Part of the GlobalPartitioning epic (#​3482).

  • Global partitioning topologies for PostgreSQL and SQL Server queues (#​3468, #​3469)
  • End-to-end sharded-processing suites for Azure Service Bus, GCP Pub/Sub, NATS, Redis Streams and Pulsar (#​3467). The scenario is lifted into Wolverine.ComplianceTests.Partitioning.ShardedProcessing, so a new transport costs one small test class
  • Native-mode design comparison and per-transport native alternatives documented (#​3481)

The new suites immediately found two real bugs:

  • NATS global partitioning had never worked at all. The topology forces EndpointMode.Durable on every slot, and a NatsEndpoint only supports Durable when JetStream-backed — so every UseShardedNatsSubjects() call threw at configuration time. The topology now enables JetStream on its own endpoints and declares a work-queue stream per shard, without which the listener died at startup on stream not found
  • Pulsar named its companion local queues off the full topic path, producing queues like global-persistent://public/default/orders1. They now use the topic's short name, matching every other transport

Multi-tenancy and persistence

  • EF Core tenant partition back-fill (#​3496). Routine migration deltas deliberately leave Weasel-managed partitions alone, so a table joining an existing managed set — a newly deployed service, or a newly mapped ITenanted entity — had no partition for any tenant registered before that table existed. IConjoinedTenantPartitions<T>.MigrateTenantPartitionsAsync() reconciles every partitioned table against the full registered tenant set, with per-table TenantPartitionResult reporting
  • Conjoined tenant partition bucketing actually works now, on both PostgreSQL and SQL Server (#​3683, and see #​3686 above)
  • Exclusive listener inbox recovery is now covered for RavenDb (#​3595) and CosmosDb (#​3596)

Transports

  • RabbitMQ: deliveries are settled against the channel they arrived on (#​3687). Acking a delivery on a torn-down channel threw a NullReferenceException
  • NATS: auto-provisioned JetStream durable consumers are filtered to their own subject (#​3676). FilterSubject was only assigned when ConsumerName was empty, so every durable consumer on a stream received every message. The fix needs a FilterSubjects multi-filter — a single filter cannot cover both {subject} and {subject}.scheduled, and a work-queue stream discards an uncovered control message
  • MQTT: the v5 authentication method name is configurable (#​3588). It was hardcoded to "OAUTH2-JWT". Azure Event Grid's custom JWT authentication requires CUSTOM-JWT, so those brokers could not be reached through Wolverine's authentication support at all. You could already set the method by hand through MqttClientOptionsBuilder.WithAuthentication(), but that gave up Wolverine's token refresh loop — the whole reason to use MqttJwtAuthenticationOptions. You no longer have to choose
  • The HTTP transport can send to a destination nobody pre-registered (#​3681, reported as ProductSupport#​34). WolverineHttpTransportClient used the endpoint's OutboundUri purely as an IHttpClientFactory client name, then posted to that client's BaseAddress — so operator commands sent back over the HTTP transport failed with An invalid request URI was provided

Performance

  • RabbitMQ consumer dispatch concurrency is now per-endpoint (#​3492). The client default of 1 was the bottleneck. Simulated handler, 2,000 msg/s offered load, 30s measured window:

    ConsumerDispatchConcurrency Throughput Transit p50
    1 (client default) 163.7/s — (nothing from the measured window was consumed before the run ended)
    5 828/s 22,871.9 ms
    20 1,999.1/s 1.486 ms (p95 2.54, p99 3.22)

    The 5.1x and 12.2x multiples understate it — at 1 and 5 the listener never catches up at all.

  • Amazon SQS batches message deletions and chunks outgoing batches on the 256KB request size limit (#​3493)

  • Azure Service Bus session listeners are no longer quadratic — the n² session loops are now n. MaxConcurrentCalls is surfaced, and a batched defer settles the original message (#​3494)

HTTP and gRPC

... (truncated)

6.23.1

Agent distribution

TL;DR: if you pause a projection from CritterWatch on 6.23.0, restarting it appears to do nothing for a full minute. This fixes that.

  • A paused projection or subscription agent now resumes immediately when you restart it (#​3663). On 6.23.0 the restart was accepted, the pause restriction was cleared, and then nothing happened until the pending-assignment ledger's TTL expired — 2 × CheckAssignmentPeriod, so 60 seconds with the defaults. Long enough that an operator reasonably concludes the agent is never coming back.

    The ledger introduced in 6.23.0 (#​3622) only counted an assignment as confirmed if a later evaluation saw the agent running and still assigned to the same node. A pause makes those two conditions mutually exclusive: the first evaluation that can observe the delivered assignment is the same one that detaches the agent. The entry was never confirmed, nothing on the stop path cleared it, and the restart's AssignAgent was suppressed as a duplicate still in flight. Delivery alone now confirms the entry, which is the only question the ledger was ever asking.

  • Pausing an agent no longer briefly starts it first (#​3666). ApplyRestrictionsAsync kickstarted a health check before persisting the operator's restriction change, so that evaluation ran against the old restrictions and could act against the very intent being applied — for a pause, re-assigning and starting the agent one beat before the merged evaluation stopped it again. Besides the wasted daemon start/stop cycle, this is what armed the stale ledger entry behind #​3663.

PostgreSQL

  • Advisory-lock sessions stay invisible to Marten's async-daemon gap detection (#​3664). Marten 9.16.1+ will not skip a stale event-sequence gap while any session whose open transaction predates that gap is still alive (marten#​4953). A session parked in an open transaction for the life of the process therefore reads as a permanent "possible reserver" and can hold the high-water mark — and every async projection — behind a gap that is genuinely dead.

    Wolverine's long-held locks were already shaped correctly: leader election and node coordination hold session-scoped advisory locks on a dedicated connection with no transaction, so they show up as state='idle' with a NULL xact_start. Those sessions are now also tagged application_name = 'wolverine-advisory-lock:<database>', which turns a pg_stat_activity investigation from guesswork into something you can read at a glance. The constraints are pinned in tests and in the Postgres durability docs, including the trap worth knowing in your own code: never add a keepalive query inside a long-lived open transaction — it bumps state_change, makes the session look active, and re-promotes it to candidate reserver.

    Note for combined Marten + Wolverine deployments: older guidance suggested Postgres's idle_in_transaction_session_timeout as a dead-gap backstop. Prefer upgrading Marten and using SkipStaleGapsDespiteLiveTransactionsAfter instead.

6.23.0

Projection & agent distribution

TL;DR: this prevents Wolverine from going into a panic doing agent assignments and churning crazily hard during Kubernetes rollouts or cluster starts and that's a very good thing

The bulk of this release. A wave of fixes (WO-1..8) to the agent assignment plane that together remove the re-assignment churn and livelock that could leave projection agents flapping or wedged.

  • Node heartbeats no longer block behind command execution (#​3620)
  • Node resurrection restores the node's real identity rather than a skeleton record (#​3621)
  • A pending-assignment ledger suppresses duplicate AssignAgent floods (#​3622)
  • Agent batch starts are chunked and bounded-parallel, so they stay safe at scale (#​3623)
  • Ejection hysteresis plus leader protection (#​3624)
  • The assignment row is re-upserted for agents that are already running (#​3619)
  • Local agents drain with bounded parallelism on shutdown (#​3636)
  • Paused shards now say why. IEventSubscriptionAgent.Failure surfaces a ShardFailure — category, the failing event's sequence and type, and the root exception type — through health checks and a new IWolverineObserver.AgentPaused hook plus a NodeRecordType.AgentPaused record. Failures bound to a specific event (ApplyEvent, EventSerialization, UnknownEventType) or to two processes racing one shard (ProgressionOutOfOrder) are no longer auto-restarted, since they would die on the identical event every time (#​3637, #​3638)
  • Agent starts retry locally, bounded by Durability.AgentStartRetryAttempts / AgentStartRetryDelay, instead of idling a full CheckAssignmentPeriod after a startup race (#​3519)
  • Store-scoped FindAgentUriAsync overload (#​3647) and a store-aware TryRebuildRegisteredProjectionAsync overload (#​3618)

Bumps JasperFx.Events to 2.36.1, Marten to 9.20.0 and Polecat to 5.7.0.

HTTP

  • Endpoints that advertise a request body their HTTP method cannot carry now fail fast at startup instead of silently 404ing out of the route matcher (#​3648)
  • A missing Content-Type on an [AcceptsContentType] route returns 415 rather than 404 (#​3649)
  • Query-only [AsParameters] endpoints no longer advertise a form body, which had been dropping them from route matching entirely (#​3630)
  • Explicitly-routed chains — PublishMessage<T> and SendMessage<T> — now describe the message they read from the body. They had been advertising no request body at all in OpenAPI (#​3646)
  • Enum values in query strings and form posts parse case-insensitively (#​3629)
  • Compiled queries returned as a Wolverine.Http resource no longer execute twice (#​3625)

Transports

  • Conventional routing respects named brokers (#​3633)
  • Google Pub/Sub: named-broker support for sharded and partitioned topics (#​3632), and ListenToPubsubSubscriptionOnNamedBroker (#​3631)
  • Kafka: topic-already-exists error codes are handled rather than thrown (#​3640)
  • Redis: scheduled retries survive an unreadable timestamp (#​3613), and scheduled entries that repeatedly fail to deserialize are d...

Description has been truncated

Bumps AndreGoepel.Core from 1.0.0 to 1.0.1
Bumps AndreGoepel.Marten.Identity.Blazor from 1.8.0 to 1.9.0
Bumps Marten from 9.19.0 to 9.22.2
Bumps Npgsql from 9.0.4 to 9.0.5
Bumps Quartz.Extensions.Hosting from 3.18.2 to 3.19.1
Bumps Quartz.Serialization.SystemTextJson from 3.18.2 to 3.19.1
Bumps Radzen.Blazor from 11.1.7 to 11.2.0
Bumps WolverineFx.Marten from 6.22.0 to 6.24.2
Bumps WolverineFx.RuntimeCompilation from 6.22.0 to 6.24.2

---
updated-dependencies:
- dependency-name: AndreGoepel.Core
  dependency-version: 1.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nuget-minor-patch
- dependency-name: AndreGoepel.Marten.Identity.Blazor
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: Marten
  dependency-version: 9.22.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: Npgsql
  dependency-version: 9.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: nuget-minor-patch
- dependency-name: Quartz.Extensions.Hosting
  dependency-version: 3.19.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: Quartz.Serialization.SystemTextJson
  dependency-version: 3.19.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: Radzen.Blazor
  dependency-version: 11.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: WolverineFx.Marten
  dependency-version: 6.24.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
- dependency-name: WolverineFx.RuntimeCompilation
  dependency-version: 6.24.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: nuget-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added .NET Pull requests that update .NET code dependencies Pull requests that update a dependency file labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file .NET Pull requests that update .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants