Bump WolverineFx from 6.36.0 to 6.38.0 - #569
Open
dependabot[bot] wants to merge 1 commit into
Open
dependabot[bot] wants to merge 1 commit into
dependabot[bot] wants to merge 1 commit into
Conversation
--- updated-dependencies: - dependency-name: WolverineFx dependency-version: 6.38.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]>
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 WolverineFx from 6.36.0 to 6.38.0.
Release notes
Sourced from WolverineFx's releases.
6.38.0
Eight issues, no breaking changes.
This is a correctness and operability release. Most of it is one shape of bug — something resolved against the wrong scope, which looked right only because two defaults usually coincide — plus the two remaining halves of recurring-schedule operability.
Multi-store and multi-tenancy
The multi-tenanted message store no longer swallows batch failures (#4435). A durable batch spanning several tenants was split across stores, but
RetryBlocknever rethrows — so a store that refused its share failed silently while the receiver acknowledged the whole batch. Messages no store had accepted were acked and lost. The batch is now split by the resolved store and a failure propagates.Natural keys resolve through the store the chain is routed to (#4439).
Identity types resolve through the store the chain is routed to (#4441).
These two are a matched pair: a saga's natural key and its identity type are facts about the store, not about the application. A modular monolith with an ancillary store per module resolved both against the main store, so a saga in module B was looked up with module A's rules.
A Wolverine service name reaches JasperFx, so the Event Model canvas stays whole (#4448).
WolverineOptions.ServiceNameandJasperFxOptions.ServiceNameboth name the one running service, but the value only ever travelled one way — so the documented way to name a Wolverine service left the JasperFx side on its default, the entry assembly name. The visible damage was an Event Model canvas splitting in two: Wolverine's source named its model one thing, a store's source named it another, and neither canvas held both halves. It only ever looked correct when a host's assembly name and service name happened to coincide, which is exactly why no test caught it.Recurring schedules
The remaining core operability gaps from #4437, which is closed by these two. (Durable last-run state, #4447, stays closed as not-planned: run state lives in OpenTelemetry, and the operability view belongs in CritterWatch.)
Non-UTC recurring schedules now record their tracking row (#4436). Cronos returns each occurrence carrying the schedule's offset, and Npgsql's
timestamptzbinder refuses any non-zero offset — so every tick of every zoned schedule threw on the bookkeeping write. Delivery was never affected; only the tracking row was missing. Normalizing inRecurringMessageRecord'sinitaccessors fixes it in one place for all four relational providers.Occurrences carry their schedule and their firing instant (#4445). The schedule name already reached the handler span. The occurrence instant did not:
ScheduledTimeis cleared by the scheduled machinery at fire time, so a handler could only learn which firing it was serving by string-parsing the deduplication id. Occurrences now carry arecurring-occurrenceheader, surfaced as thewolverine.schedule.occurrencetrace tag.Metrics also gained a
schedule.nametag, so the success, failure and effective-time counters can finally be sliced per cron job. It is read off the envelope header rather than set locally, because the metric tag list is never serialized — an occurrence published on one node and handled on another would otherwise reach the counters with no attribution at all. The occurrence instant is deliberately trace-only: one distinct value per firing would make those series unbounded in cardinality.IRecurringScheduleControl.TriggerAsyncruns a schedule once, on demand (#4446). Previously an operator's only option was hand-publishing the message type out of band, which bypasses the occurrence and deduplication machinery entirely. The request is recorded on the schedule's durable tracking row and the agent publishes one occurrence for it on its next pass, so it works from any node — the same reason pause already goes through the store.A manual run carries its own deduplication id, so a "run now" issued in the same instant as a scheduled firing is never silently collapsed into it. Triggering a paused schedule is refused: pausing says the schedule must not fire. A trigger is extra rather than a replacement — it leaves the cron cadence and the pending occurrence untouched, and it fires even for a fixed-date schedule whose occurrences have run out.
gRPC
[WolverineGrpcService]on the interface (#4396). A contract you do not own — or one carrying only[ServiceContract]— could not be registered at all.AddWolverineGrpc(grpc => grpc.IncludeCodeFirstContract<IMyService>())now registers it explicitly. Thanks to @erikshafer for the PR.6.37.0
Eight issues, one of them breaking.
ServiceCapabilities.EventModelis now anEventModelSetDescriptorrather than a singleEventModelDescriptor(#4424). A host can legitimately assemble several Event Models — each store names its own throughStoreOptions.EventModelName, and a modular monolith registers an ancillary store per module — and the export used to fold them all into one named for the service, losing a model's name outright and reporting nothing.This is a compile break for anything reading that property, and the capabilities wire shape changes with it. A consumer that can only render one model asks
.Sole, or folds explicitly with.Collapse()and gets aModelCollapsehotspot recording what it lost. CritterWatch consumes this shape and has the equivalent fold still to follow.Everything else in the public surface is additive.
Event Modeling
FinishModelcarried a private copy of the cross-slice join; it is re-based onEventModelDescriptor.Links, so the pattern Wolverine derives and the arrow a viewer draws cannot disagree. A slice triggered by another slice's event throughTriggerType— not onlyCommandType— is now classified too.ReadsFromis split out ofReadModelTypes(#4419).[ReadModel]and[Entity]parameters are things a slice reads;IStorageAction<T>returns are what it produces. They shared one list, which meant the Automation input edge — Event → Read Model → ⚙ Command — could not be drawn at all.Origin(#4425). Wolverine registers two sources on theDerivedrung, so a disagreement between them used to render asDerived claims X; Derived claims Y, naming neither file. It now readsevent-model://wolverineagainstevent-model://wolverine-http.Native AOT
codegen writeemits its own[DynamicDependency]rooting (#4426). Every Native AOT application had to hand-write a rooting block covering the generated registry, every generated handler, every handler class, every message type, andMessageRouter<T>/EmptyMessageRouter<T>closed over each one. Codegen now emits anAotRootscompanion anchored by[ModuleInitializer]— an unconditional ILC root — so there is no app-side code at all. Verified by a realPublishAotbinary booting and dispatching with the hand-written roots deleted.Bug fixes
Envelope.Storedoes not survive persistence, so the acknowledgement fell back to the main store — the ancillary row survived, and the message was recovered, sent and handled again on every restart. Thanks to @raypet-visma for the diagnosis and the fix sketch._consumer.Close()is a synchronous P/Invoke that can block forever against a degraded broker, soIHost.StopAsyncnever completed — observed wedged 20+ minutes, past bothDrainTimeoutandShutdownTimeout. It now runs under the drain budget on a dedicated thread, and an abandoned teardown suppresses the consumerDisposerather than destroying a handle another thread still owns.OnExceptionreturningOutgoingMessagescompiles again (#4416). It failed code generation with "Frame chain is being re-arranged" while the same method on a middleware class worked. Thanks to @uniquelau for the report and for locating the exact divergence. The error-handling docs gained an example of using the hook to publish messages when the original message fails.Build & dependencies
codegen writeoutput is regenerated and aCICodegenDriftgate now guards it — meaningful only now that the emitted statement order is deterministic. Regenerating surfaced real staleness rather than the expected reordering: six orphaned handler files and four missing registry files.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)