fix(streaming): v8.0.30 audit follow-ups + 8.0.32 bump (closes #498)#499
Merged
Conversation
…498) Closes seven hygiene gaps surfaced by the v8.0.30 review: - Dispatcher drain loop now wraps user-callback invocation in catch_unwind. A panic from user code (Rust closure / PyO3 callable / napi ThreadsafeFunction / C extern fn) no longer kills the dispatcher thread; panics are counted on a new panic_count AtomicU64 (exposed via StreamingDispatcher::panic_count) and logged at error level, then the loop continues. SSOT: every binding inherits this behavior, no per-binding panic handling. - FPSS C ABI handle gains a permanent state field (Fresh / Active / Shutdown). tdx_fpss_set_callback / _set_inline_callback / _reconnect / _shutdown now enforce one-shot registration and terminal shutdown; post-shutdown calls return -1 with a clear tdx_last_error() string. - Unified C ABI: tdx_unified_set_callback after stop is documented as REPLACEMENT (high-level path supports stop+restart). Contract divergence from FPSS one-shot is intentional and now explicit in rustdoc + thetadx.h. - thetadx.h documents ctx lifetime + queued-vs-inline thread affinity on every set_callback / set_inline_callback declaration, mirrored in the thetadx.hpp doxygen blocks. - Python dropped_event_count rustdoc, README, and test corrected to the actual reset-on-reconnect / zero-after-stop semantics. Counter lives on the live StreamingDispatcher; reconnect rebuilds it and resets to 0. Snapshot before reconnect for cross-session accumulation. Matches the TypeScript binding. - Dispatcher dropped counter is now strictly queue-full (TrySendError::Full). TrySendError::Disconnected (rare; happens during shutdown races) feeds a separate disconnected_count so the user-facing drop metric is not inflated by lifecycle noise. - TypeScript index.d.ts regenerated from the corrected napi-rs rustdoc so the JS-visible doc matches the Rust source. Version 8.0.30 -> 8.0.31 via scripts/bump_version.py. Closes #498 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3980546 to
c72d6f6
Compare
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
Closes the seven hygiene gaps identified in the v8.0.30 streaming review (issue #498). One squashable commit; no dispatcher / FFI behavior change for users on the happy path, only on previously-undefined error paths.
catch_unwind. A panic from user code (Rust closure / PyO3 callable / napiThreadsafeFunction/ Cextern "C" fn) no longer kills the dispatcher thread; panics are counted on a newpanic_countAtomicU64(exposed viaStreamingDispatcher::panic_count()) and logged aterrorlevel. SSOT: every binding inherits this behavior; no per-binding panic handling added.TdxFpssHandlegets a permanentstate: AtomicU8field.tdx_fpss_set_callback/_set_inline_callback/_reconnect/_shutdownenforce the documented one-shot registration and terminal-shutdown rules. Post-shutdown ops return -1 with a cleartdx_last_error()string instead of silently re-using a torn-down handle.tdx_unified_set_callbackaftertdx_unified_stop_streamingis now documented (rustdoc +thetadx.h) as REPLACEMENT, not error. The high-level unified path supports stop+restart as a normal user flow (tdx_unified_reconnectis built on top of it). The contract divergence from FPSS one-shot is intentional and explicit in both header docs.ctxlifetime + thread affinity documented in everytdx_*_set_callback/_set_inline_callbackdeclaration inthetadx.h, mirrored inthetadx.hppdoxygen.dropped_event_count()doc + test corrected to the actual reset-on-reconnect / zero-after-stop semantics. Counter lives on the live dispatcher;reconnect()rebuilds it. Matches the TypeScript binding's contract.droppedcounter is strictly queue-full.TrySendError::Disconnected(rare; shutdown race) feeds a newdisconnected_countso the user-facing drop metric is not inflated by lifecycle noise.index.d.tsregenerated from the corrected napi-rs rustdoc so the JS-visible doc matches the Rust source.Version 8.0.30 -> 8.0.31 via
scripts/bump_version.py. Changelog mirrored todocs-site/docs/changelog.md.Closes #498
Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspacecargo deny checkcargo run -p thetadatadx --bin generate_sdk_surfaces --features config-file -- --checkcargo check --manifest-path tools/mcp/Cargo.toml --lockedcargo clippy --manifest-path tools/mcp/Cargo.toml --all-targets -- -D warningscargo test --manifest-path tools/mcp/Cargo.toml --no-runcargo check --manifest-path tools/server/Cargo.toml --lockedcargo check --manifest-path sdks/python/Cargo.toml --lockedcargo check --manifest-path sdks/typescript/Cargo.toml --lockedpython3 scripts/check_version_sync.pycmake -S sdks/cpp -B build/cpp && cmake --build build/cpp --target thetadatadx_cppcmake --build build/cpp --target thetadatadx_fpss_smokedispatcher_survives_panicking_callbackincrates/thetadatadx/src/fpss/dispatcher.rsexercises three guaranteed-panic events followed by three successful ones, assertspanic_count == 3anddropped_count == 0.fpss_state_gate_rejects_after_shutdowninffi/src/streaming.rsexercises every state-gate transition without needing a live FPSS connection.