Skip to main content
Pass a StreamObserver via NexusConfig.stream_observer to receive structured callbacks for every SSE lifecycle transition. The observer is the canonical way to wire SDK state into ops dashboards, custom telemetry, or load-test tooling - far more reliable than scraping NexusLogger output by substring match. The observer is opt-in. When NexusConfig.stream_observer is None the SDK uses NOOP_STREAM_OBSERVER at zero overhead.

The interface

The protocol is structural - any object with the matching method signatures qualifies. Methods are looked up via getattr, so consumers may omit any method they don’t care about (the SDK handles missing-attribute cases gracefully).

Hook semantics

on_fallback reasons

rate-limited semantics (v0.3.1+). This reason now fires in both of these situations:
  • Server included a parseable Retry-After header. The SDK fires on_fallback(FALLBACK_REASON_RATE_LIMITED), sleeps the indicated delay clamped to [5, 300] seconds, and then reconnects automatically. The 429 does not count against _MAX_STREAM_ERRORS. Expect a matching on_connected() shortly after the sleep window.
  • No parseable Retry-After. Legacy behaviour: the SDK fires on_fallback(FALLBACK_REASON_RATE_LIMITED), closes the stream, and stays on TTL polling. No automatic reconnect - connect_stream() is required to recover.

Threading contract

For the synchronous NexusClient, observer methods are called synchronously from the SDK’s stream thread. For the async AsyncNexusClient, observer methods are called synchronously from the asyncio task running the stream - they are NOT awaited even if you define them as coroutines.
In both cases observer methods MUST return promptly. The SDK does not protect against blocking observers.
If your observer does anything substantial (network I/O, lock contention, disk writes), copy the argument and dispatch the work to your own thread / task before returning:

If your observer raises

Changed in v0.11.0. An exception from an observer method is caught and absorbed - a faulty observer can never break the stream, stall a sync, or propagate into your own code paths. It is also logged. The SDK reports it through NexusLogger at error level, naming the hook that failed and attaching the original exception as the cause:
Before v0.11.0 the exception was discarded with no trace anywhere, so an observer that threw on every event was indistinguishable from one that was never called. If you set no logger the fault is still absorbed - it just goes unreported, as before.
This follows the OpenTelemetry error-handling specification, which covers the same situation from both sides: “API methods that accept external callbacks MUST handle all errors”, and “whenever the library suppresses an error that would otherwise have been exposed to the user, the library SHOULD log the error”. A missing hook is not a fault - the observer protocol is partial by design. Implement only the callbacks you need; the rest are skipped silently.

Counter pattern

Active-connection gauge pattern

on_fallback is included because after the 3-strike FALLBACK_REASON_MAX_ERRORS case the SDK will not reconnect - the gauge should stay False until you call connect_stream() again. For FALLBACK_REASON_RATE_LIMITED with a Retry-After (v0.3.1+) the SDK does reconnect on its own; the gauge will flip back to True on the next on_connected().