Skip to content

Lock in custom-serializer-on-send guarantee (CritterWatch#261 H1 analysis)#3012

Merged
jeremydmiller merged 1 commit into
mainfrom
verify-custom-serializer-send
Jun 3, 2026
Merged

Lock in custom-serializer-on-send guarantee (CritterWatch#261 H1 analysis)#3012
jeremydmiller merged 1 commit into
mainfrom
verify-custom-serializer-send

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Pre-release verification for the H1 hypothesis in CritterWatch#261: "Wolverine SQS endpoint not honoring the rule-level DefaultSerializer."

Conclusion: the framework honors custom serializers

Traced the send path end to end — the mechanism is sound, no production bug:

  1. x.To(uri).DefaultSerializer(custom)SubscriberConfiguration delays e.DefaultSerializer = custom, whose setter RegisterSerializer(custom)s it (keyed by custom.ContentType) and stores it on the Endpoint.
  2. Endpoint.Compile() uses DefaultSerializer ??= runtime.Options.DefaultSerializer — so an endpoint-level custom serializer is not overwritten by the global STJ default.
  3. MessageRoute captures Serializer = endpoint.DefaultSerializer, and CreateForSending sets envelope.Serializer = Serializer + envelope.ContentType = Serializer.ContentType. The sending agent then writes the wire bytes via envelope.Serializer.Write(envelope).

So a custom IMessageSerializer (e.g. a Brotli-compressing one) is the serializer that produces the wire payload — provided the rule lands on the endpoint the message routes to.

On the URI-mismatch sub-hypothesis (H2)

AmazonSqsTransport.findEndpointByUri falls back to Queues[uri.OriginalString.Split("//")[1].TrimEnd('/')], so sqs://critterwatch and sqs://critterwatch/ resolve to the same queue endpoint — the trailing-slash difference seen in the logs does not split the serializer onto a phantom endpoint at the framework level.

The #261 symptom is therefore most likely on the CritterWatch-extension / host-config side (H3 host-level DefaultSerializer override after AddCritterWatchMonitoring, H4 Wolverine.CritterWatch 0.7.0 version regression, or H5 strip not running) — the diagnostic logging in that comment will localize it. Not a Wolverine framework defect.

What this PR adds

The existing serialization_configuration tests only assert the serializer is attached to the endpoint. This adds a send-path regression test that routes a message through runtime.RoutingFor(...).RouteForSend(...) and asserts:

  • the outgoing envelope for the overridden endpoint carries the custom serializer + its content type,
  • envelope.Serializer.Write(envelope) is what produces the payload,
  • a sibling endpoint with no override stays on the global SystemTextJsonSerializer.

No production code change — this locks in the guarantee so a future regression (e.g. a Compile() ordering change that lets the global default clobber an endpoint override) is caught. serialization_configuration suite green (8/8).

🤖 Generated with Claude Code

…he send path

Verification for CritterWatch#261 (H1): a custom IMessageSerializer attached at the
rule/endpoint level via .To(uri).DefaultSerializer(custom) must actually produce the
outgoing envelope (and therefore the wire bytes), not be silently replaced by the
global System.Text.Json default.

The existing serialization_configuration tests only assert the serializer is *attached*
to the endpoint (endpoint.DefaultSerializer.ShouldBeSameAs(...)). This adds a send-path
assertion: route a message via runtime.RoutingFor(...).RouteForSend(...) and confirm the
outgoing envelope for the overridden endpoint carries the custom serializer + content
type and that envelope.Serializer.Write(envelope) is what produces the payload — while a
sibling endpoint with no override stays on the global STJ default.

This locks in the framework guarantee analyzed for the release: the rule-level
DefaultSerializer survives Endpoint.Compile()'s `??=` global fallback and is selected by
MessageRoute on the send path. No production code change — the mechanism already works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit 58be69a into main Jun 3, 2026
22 of 23 checks passed
This was referenced Jun 3, 2026
This was referenced Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant