test(streaming): add empty-monitors edge case for stream_alerts#44
test(streaming): add empty-monitors edge case for stream_alerts#44KhaledSalhab-Develeap wants to merge 8 commits into
Conversation
Add opentelemetry-api>=1.20 as an optional runtime dep under [otel]. Add opentelemetry-api and opentelemetry-sdk to [dev] so tests can use TracerProvider and InMemorySpanExporter without requiring users to install the SDK.
…ransport Add _otel.py with get_tracer, start_request_span, start_rpc_span, and record_error helpers. Each client and transport stores self._tracer at construction time. The _request loop (sync and async) is wrapped in a start_request_span context; call_tool (sync and async) is wrapped in a start_rpc_span context. Errors are recorded with record_error on the active span before re-raising. All helpers are no-ops when opentelemetry-api is not installed, so install hyperping[otel] to enable tracing. Closes #6f36bd (PY-11)
Several files introduced in earlier commits did not pass ruff format --check. Format them so the full src/ + tests/ tree is consistently formatted. Co-Authored-By: Khaled Salhab <khaled.salhab@develeap.com>
Add poll-based async streaming helpers for alert and incident monitoring. Introduce Alert/AlertType provisional models derived from the monitors endpoint, and AsyncStreamingMixin with stream_alerts and stream_incident_updates. Wire the mixin into AsyncHyperpingClient and export Alert/AlertType from the public API. Rate-limit note: default 30s interval uses 2 req/min per stream_alerts call, approximately 0.67% of the 300 req/min account limit. Co-Authored-By: Khaled Salhab <khaled.salhab@develeap.com>
…(PY-10) 17 tests covering the Alert model (frozen, extra fields, aliases, enum values) and both streaming helpers (first-poll baseline, state transitions, dedup, invalid UUID, not-found propagation, and poll_interval forwarding). Co-Authored-By: Khaled Salhab <khaled.salhab@develeap.com>
…470) Guard the path where stream_alerts receives an empty monitors list on first poll: verify nothing is yielded, asyncio.sleep is still called (the loop continues), and monitors appearing on the second poll set the baseline without triggering transition alerts.
CI Status CheckVerdict: INCONCLUSIVE - CI checks did not trigger. Findings
Root CauseGitHub Actions workflows configured with Local VerificationThree new tests added in this commit all pass locally:
Total: 3 passed in 0.05s Next StepsTo proceed with CI validation, either:
(Note: The draft PR requirement prevented option 1 per stage requirements.) |
|
Reviewer context (not a merge request): Despite sharing a branch name with #42, this PR targets Where to focus review: The httpx2 swap ( Risks / verify: Large bundled scope makes review hard; consider splitting. CI status: No checks triggered. Not red. Notes: Duplicate-by-branch of #42, but NOT equivalent: #42 (base |
|
Update (conflict resolution): Merged Note: this PR and #42 share the exact same head branch ( |
Same as the parent async-streaming branch: _otel.py and test_otel.py require the PY-11 client wiring that is not present here, so they were dead code plus a failing standalone test. Remove them and the opentelemetry deps. OTel is delivered solely by the PY-11 PR.
|
Resolved: the red is fixed. Same OTel-scaffolding removal applied to |
Add three unit tests to
TestStreamAlertsintests/unit/test_streaming.pycovering the edge case wherestream_alerts()is called and the monitors list returned by the API is empty.What changed
tests/unit/test_streaming.py: three new tests added toTestStreamAlerts:test_stream_alerts_empty_monitors_yields_nothing-- empty list on the first poll yields no alertstest_stream_alerts_empty_monitors_sleep_still_called--asyncio.sleepis still invoked when monitors is empty (the loop does not exit early)test_stream_alerts_empty_then_monitors_appear_no_transition-- monitors present on the second poll after an empty first poll set the baseline without emitting a transition alert, because there is no prior state to diff againstWhy this shape
The three tests each pin a distinct observable behaviour of the empty path: no yield, no early exit, and correct baseline initialisation. Splitting them makes each failure message self-describing. No production code changes are required; the existing implementation already handles this path correctly.
Coverage
hyperping._async_streaming_mixinhyperping.models._alert_modelsNote: Production code has 0% changes; this PR is test-only.
Verification
pytest tests/unit/test_streaming.py --no-covAcceptance criteria
stream_alerts()with an empty monitors list correctly yields nothing