Skip to content

Don't fail scatter-gather when remote instances omit required members (e.g. EndpointDetails.Host) - #5961

Draft
speedmind wants to merge 2 commits into
Particular:masterfrom
speedmind:fix/tolerate-missing-endpoint-host-in-remote-results
Draft

speedmind wants to merge 2 commits into
Particular:masterfrom
speedmind:fix/tolerate-missing-endpoint-host-in-remote-results

Conversation

@speedmind

Copy link
Copy Markdown

Summary

Since 6.20.0, the primary instance can silently drop an entire audit instance's results from scatter-gather queries (for example messages2, used by ServicePulse's "All messages" view and its endpoint filter). The response then carries X-Particular-Incomplete-Results: <instance>:error, and the primary logs Failed to query remote instance ... missing required properties including: 'host'.

This may be what's behind Particular/ServicePulse#3102.

Root cause

  • Enable nullable annotations in ServiceControl.Persistence #5774 (6.20.0) added nullable annotations and marked EndpointDetails.Name and EndpointDetails.Host as C# required.
  • System.Text.Json enforces required members on deserialization.
  • Audit instances serialize their API responses with DefaultIgnoreCondition = WhenWritingNull. The endpoint host is often null, for example when the NServiceBus.OriginatingMachine header is missing and the originating address has no @machine part, which is common on non-MSMQ transports. In that case host is omitted from the JSON.
  • When the primary deserializes that remote response (ScatterGatherApi), one such message throws. The catch then treats the whole instance as failed, so all of its results for that page are discarded.

On 6.19.x these properties weren't required, so the same payload deserialized fine.

Fix

SerializerOptions.Default (primary instance) now adds a JsonTypeInfo modifier that sets IsRequired = false on every property when reading JSON. C# required still enforces correct construction in our own code. JSON that comes from other instances, possibly running other versions, is read the same way as before 6.20.

Tests

  • Added RemoteEndpointDetailsDeserializationTests. It deserializes an EndpointDetails without host, and runs a scatter-gather against a remote audit response that omits host. Both tests fail on master without the fix: the first throws on the missing required property, and the second reports the remote instance as failed. Both pass with the fix.
  • Full ServiceControl.UnitTests suite: 453/453 passing locally. I haven't run the acceptance tests locally.

The change applies cleanly to release-6.21 if a patch release is wanted.

…nces

EndpointDetails.Name/Host became 'required' in Particular#5774 (6.20.0). System.Text.Json enforces
'required' on deserialization, while audit instances serialize with WhenWritingNull and omit
a null host. One such message made the primary fail the whole remote response, so the audit
instance's page was dropped from scatter-gather queries (X-Particular-Incomplete-Results).
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

2 participants