Repository navigation
Wolverine 6.59.1
This is a patch release with two fixes. Upgrading is a package bump only: there is no schema change and no API change.
SQL Server: the inbox and outbox seek on their indexes again
- GH-5292 (#5294): Several of the SQL Server message store's per-envelope statements were scanning the whole envelope table. That cost grows with the size of the inbox and outbox, and those statements run once per message. The cause was how two kinds of value were bound as parameters.
- Envelope ids went out as
sql_variant. The statements that mark envelopes as handled, reassign them, delete them and move them to the dead letter queue all filter on the envelope id. Weasel's generic command builder has no mapping forGuid, so it bound each id asDbType.Object, which SqlClient sends assql_variant. SQL Server then had to compareCONVERT_IMPLICIT(sql_variant, [id])on every row, which rules out a seek on theuniqueidentifierprimary key. Ids are now bound asuniqueidentifier, so each statement is a primary key seek. - Envelope addresses went out as
nvarchar.received_aton the inbox anddestinationon the outbox arevarchar(250)columns, but statements that filter on them bound the address asnvarchar. Under a SQL collation such asSQL_Latin1_General_CP1_CI_AS, the default on Azure SQL, that converts the column and defeats the index. The statements affected are the per-envelope updates and deletes, inbox recovery's page load, outbox loads by destination, the scheduled message updates and the duplicate check. They now bind the address asvarchar. DateTimeparameters kept only the date. The same generic mapping typedDateTimeasDbType.Date. The message store now lets SqlClient type both values itself.- The new test checks SQL Server's plan cache after running each of these statements. It requires that no plan contains
sql_variantand that no plan converts an indexed envelope column. The fullSqlServerTestssuite passes (721 tests, 2 skipped). - PostgreSQL, MySQL, SQLite and Oracle bind exactly as they did before.
- The underlying Weasel mappings are tracked as JasperFx/weasel#758 (
Guidassql_variant) and JasperFx/weasel#759 (DateTimeasdate). Wolverine works around both on its own, so this release doesn't wait for a Weasel release.
- Envelope ids went out as
The run command no longer blocks a thread pool thread
- JasperFx 2.96.2 (JasperFx/jasperfx#1093, fixes JasperFx/jasperfx#1092): Wolverine now depends on JasperFx 2.96.2. Before this release, the
runcommand waited for shutdown by blocking a thread pool thread for the whole life of the application. That matters when a container's CPU limit is below one core.ProcessorCountis then 1, so the thread pool's minimum is one thread, and theruncommand held it. After that, every burst of work had to wait for the pool to add a thread, about 500 ms each time. The reporter saw a 200 msTask.Delayloop wake up as much as about 950 ms late on Azure Container Apps.- The
runcommand now awaits shutdown instead of blocking. It still listens for the same three signals:ApplicationStopping, Ctrl+C, and the assembly load context unloading. - When the host is already started (the
AutoStartHost/WebApplicationFactorypath),RunJasperFxCommands()used to block the calling thread. It now returns a task that completes when the host shuts down. - This applies to every application started with
RunJasperFxCommands()orRunWolverineCommands(), whatever its persistence or transport.
- The
Full Changelog: V6.59.0...V6.59.1