Catch all Historian sink exceptions in EventEmitter.emit (#90) - #98
Merged
randileeharper merged 1 commit intoJun 28, 2026
Merged
Conversation
Historian delivery is best-effort: a failed delivery must never fail the surrounding user-facing music operation. EventEmitter.emit only caught HistorianDeliveryError, but HttpHistorianSink._request re-raises other exceptions -- httpx.HTTPStatusError on a 4xx response, ValueError on malformed JSON, httpx.RequestError after exhausting retries -- which then propagated out of emit and broke the operation (issue #90). Broaden emit's except: HistorianDeliveryError is still logged at warning level; any other exception is now caught, logged at error level with a traceback (exc_info=True), and never propagated. This makes the best-effort contract a hard boundary while keeping genuine sink bugs visible in logs (addressing the visibility concern from issue #47 that originally narrowed the catch to HistorianDeliveryError). Also hoists the per-call `import logging` to a module-level `_log` logger. The issue #47 regression test, which asserted unexpected sink errors propagate, is updated to assert the new behavior: the operation succeeds and the unexpected error is logged at error level. A new test covers the specific httpx.HTTPStatusError (4xx) scenario from issue #90. Closes #90
randileeharper
deleted the
fix/historian-sink-exceptions-break-operations
branch
June 28, 2026 16:42
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.
Summary
Fixes #90.
EventEmitter.emitonly caughtHistorianDeliveryError, butHttpHistorianSink._requestre-raises other exceptions —httpx.HTTPStatusErroron a 4xx response,ValueErroron malformed JSON,httpx.RequestErrorafter exhausting retries — which then propagated out ofemitand failed the surrounding user-facing music operation. This violated the design rule that Historian delivery is best-effort.Change
Broadened
emit'sexceptso the best-effort contract is a hard boundary:HistorianDeliveryError→ logged atwarning(unchanged behavior)Exception→ caught, logged aterrorwith a traceback (exc_info=True), and never propagatedThis keeps genuine sink bugs visible in logs (the visibility concern from issue #47 that originally narrowed the catch to
HistorianDeliveryError) while ensuring a Historian outage or bug can never break apause()/play()/ etc. call.Also hoisted the per-call
import loggingto a module-level_loglogger.Test changes
test_unexpected_sink_error_propagates_instead_of_being_swallowed→test_unexpected_sink_error_is_logged_and_does_not_break_operations): it now asserts the operation succeeds and theRuntimeErroris logged at error level with a traceback, instead of asserting it propagates.test_http_status_error_from_sink_does_not_break_operations: covers the specifichttpx.HTTPStatusError(4xx) scenario from issue Non-delivery exceptions from Historian sink can break operations #90 flowing throughEventEmitter.emit.Verification
Exact commands run (per
AGENTS.md, using the project virtualenv):Closes #90.