gateway: the SSE tap renders every event, bytes included - #113
Merged
Conversation
The tap forwards whatever a plugin published, and plugin payloads are not required to be JSON. A `bytes` payload -- a raw stream event, for one -- killed the frame with `TypeError: Object of type bytes is not JSON serializable`: one dropped notification per event, one logged `tap callback failed` each, 292 of them in a 45s digital-twin run, and an SSE consumer which sees nothing while the broker looks busy. The SSE feed is a monitoring tier, so the invariant is that it renders every event rather than that every payload round-trips: anything JSON cannot encode now falls back to `str()`. A consumer which wants the payload itself still has the plugin's own channel; the tap only has to say that the event happened. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
One line plus a regression test.
Gateway._sse_framewas a barejson.dumps, but the event tap forwards whatever a plugin published, and plugin payloads are not required to be JSON. Abytespayload (a raw stream event from the digital-twin plugin, in the case that found this) raisedTypeError: Object of type bytes is not JSON serializableper event — one dropped SSE notification and onetap callback failedlog line each, 292 of them in a 45 s run — while every JSON-clean event flowed normally, so the feed looked healthy unless you were waiting for exactly those events.The SSE feed is a monitoring tier: the invariant worth having is that it renders every event, not that every payload round-trips. Anything JSON cannot encode now falls back to
str(). Consumers that want the payload itself have the plugin's own channel; the tap only has to say the event happened. A typed encoder (e.g. base64 for bytes) would let SSE consumers decode payloads client-side — deliberately out of scope for this fix, noted here in case it's ever wanted.Verified: new
test_sse_frame_survives_non_json_payloads(bytes render, JSON-clean payloads unchanged), plus the existing SSE suite — 4 passed locally. flake8 clean.🤖 Generated with Claude Code