Skip to content

feat: tick-scoped notice buffer flushed after wait message - #574

Merged
biodrone merged 3 commits into
stagingfrom
cursor/tick-notice-buffer-4c96
Jun 30, 2026
Merged

feat: tick-scoped notice buffer flushed after wait message#574
biodrone merged 3 commits into
stagingfrom
cursor/tick-notice-buffer-4c96

Conversation

@biodrone

@biodrone biodrone commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Fixes #573

Summary

Adds an interim notification surface for StreamDL: user-facing warnings and errors are buffered during each tick and flushed after the Waiting … until next check line, so docker compose logs surfaces actionable messages at the bottom of each idle period — without requiring debug log level or a full TUI.

Changes

Go client

  • New Noticer interface and tick-scoped notice buffer (notice.go)
  • End-of-tick flush after Currently Live Users summary and INFO-level wait line
  • Dedup within a tick and across ticks until channel state changes (ClearChannel on live session end)
  • Routes GetStream failures, format fallback warnings, VOD resolve failures, and FFmpeg failures through the notice buffer
  • Propagates gRPC status messages and x-streamdl-warning metadata to the client

Python server

  • Human-readable message field on GetStream errors (quality mismatch, offline, format failure)
  • Maps error 414 (quality not available) with available Streamlink keys
  • Sends format fallback warnings via gRPC initial metadata on success

Tests

  • Go unit tests: notice buffer flush order, dedup, error levels
  • Python unit tests: GetStream message formatting (Twitch/Streamlink + Kick/yt-dlp paths)
  • Integration Phase 6a: Twitch invalid quality notice (skip if no live channel)
  • Integration Phase 6b: Kick offline/error notice (deterministic)
  • CI: run pytest tests/ alongside existing bandit scan

Example output (INFO level)

INFO  Currently Live Users:
INFO  Waiting 60s until next check...
INFO  --- notices ---
WARN  [day9tv] Requested quality '1080p60' not available. Available: 720p, 480p, best
WARN  [nonexistent_user_12345] Channel 'nonexistent_user_12345' is offline

Testing plan

Layer Twitch (twitch.tv) Kick (kick.com)
Go unit Mocked flush/dedup
Python unit Streamlink 414/404 messages yt-dlp offline + format fallback
Integration 6a/6b Invalid quality on live channel Offline channel notice

Follow-ups (out of scope)

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added user-facing notices for stream and VOD issues, including warnings, errors, and tick-based message flushing.
    • Stream responses can now include non-fatal warning messages alongside download URLs.
    • Improved VOD stream ID handling for better URL resolution.
  • Bug Fixes

    • Made stream and VOD failures report clearer, more actionable messages.
    • Improved handling of rate limits, missing qualities, offline streams, and fallback downloads.
  • Tests

    • Expanded test coverage for notice deduplication and stream error/warning messages.
    • Added integration checks for the new notice behavior.

Add an in-memory notice buffer in the Go client that collects user-facing
warnings and errors during each tick and flushes them after the wait line,
so docker compose logs show actionable messages at the bottom of each cycle.

Improve GetStream error propagation from the Python server with clear messages
for quality mismatches (414), format failures (415), and offline channels (450).
Format fallback warnings are sent via gRPC metadata.

Includes Go and Python unit tests plus integration test phases 6a (Twitch)
and 6b (Kick).

Closes #573

Co-authored-by: Josh J <josh@joshjacobs.net>
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0f02ee6d-5aa5-4558-b57f-82f6bb6b57f3

📥 Commits

Reviewing files that changed from the base of the PR and between afaa245 and 8e1eb97.

📒 Files selected for processing (12)
  • .github/workflows/test.yml
  • download_stream.go
  • grpc_client.go
  • grpc_client_test.go
  • notice.go
  • notice_test.go
  • streamdl.go
  • streamdl_proto_srv.py
  • tests/integration/docker-compose.integration.yml
  • tests/integration/run.sh
  • tests/test_get_stream_messages.py
  • vod_stream_test.go

📝 Walkthrough

Walkthrough

Adds a deduplicating in-memory tick notice buffer (notice.go) that collects user-facing warnings/errors during each Go client tick and flushes them after the wait message. The Python gRPC server is enriched to return structured error messages and a warning field; the Go gRPC client propagates this warning via x-streamdl-warning response header into StreamURLs.Warning. All download/VOD/live-probe failure paths are routed through tickNotices. Unit and integration tests are added throughout.

Changes

Tick Notice Buffer and gRPC Warning Propagation

Layer / File(s) Summary
Notice buffer type, interface, and flush logic
notice.go
Defines TickNotice struct, Noticer interface, and noticeBuffer with deduplication, ClearChannel, Flush, and a global tickNotices instance.
Notice buffer unit tests
notice_test.go
Tests flush ordering, within-tick deduplication, post-surface suppression, ClearChannel reset, error log level, and empty-input guard.
Python server: structured error messages and warning metadata
streamdl_proto_srv.py
get_stream returns richer {error, message} dicts for quality mismatches, offline, yt-dlp errors, and format-fallback warning; GetStream sends x-streamdl-warning header and derives detail from res["message"].
Python server message tests
tests/test_get_stream_messages.py, .github/workflows/test.yml
Unit tests for quality-mismatch 414 message, offline 404, yt-dlp offline 450, and yt-dlp format-fallback warning; CI workflow now runs pytest tests/ -v.
Go gRPC client: Warning field, header capture, streamResolveError
grpc_client.go, grpc_client_test.go
StreamURLs gains Warning string; getStream captures x-streamdl-warning and refactors error handling via new streamResolveError helper; tests cover helper behavior and errors.Is compatibility.
Tick loop and download wiring through tickNotices
streamdl.go, download_stream.go, vod_stream_test.go
Routes VOD/live probe failures, rate-limit retries, FFmpeg failures, and probeResult.Warning through tickNotices.Warn/Error; adds per-tick Flush call and vodStreamUser helper with table-driven test.
Integration test suite hardening
tests/integration/run.sh, tests/integration/docker-compose.integration.yml
Adds FAILED accumulation, start_client/run_notice_tests helpers, log-order assertions for offline Kick and invalid-quality Twitch, hardened live mp4 and VOD validation, and unconditional notice test execution at end of run.

Sequence Diagram(s)

sequenceDiagram
    participant TickLoop as streamdl.go tick loop
    participant GoGRPC as getStream (grpc_client.go)
    participant PySrv as StreamServicer (streamdl_proto_srv.py)
    participant Buffer as tickNotices (noticeBuffer)

    TickLoop->>GoGRPC: getStream(site, user, quality)
    GoGRPC->>PySrv: GetStream RPC (grpc.Header capture)
    PySrv-->>GoGRPC: x-streamdl-warning header + StreamResponse or gRPC error with detail
    GoGRPC-->>TickLoop: StreamURLs{Video, Audio, Warning} or error
    TickLoop->>Buffer: Warn/Error(channel, message)
    Note over Buffer: deduplicates by channel|message key
    TickLoop->>Buffer: Flush(tickTime)
    Buffer-->>TickLoop: logs notices at warn/error level after wait line
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • dangeroustech/StreamDL#551: Touches VOD download failure handling in download_stream.go and VOD URL resolution in streamdl.go, both of which are modified by this PR's notice wiring and vodStreamUser helper.
  • dangeroustech/StreamDL#557: Introduced the downloadVOD implementation in download_stream.go that this PR now extends with tickNotices.Warn on FFmpeg failure.

Poem

🐇 Hop hop, the notices queue,
No more messages lost in the log stew!
Each tick I flush them, neat in a row,
After the "Waiting..." — that's where they go.
Deduplicated, clean, and bright,
Your stream warnings surface just right! ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/tick-notice-buffer-4c96

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

biodrone added 2 commits June 30, 2026 16:34
Recreate only the client with --no-deps so Phase 6 notice checks still run
after a VOD failure, and fix Compose v5 healthcheck quoting.
yt-dlp returns IDs like v2807766672; prepending videos/ produced
twitch.tv/videos/v2807766672 which fails resolution.
@biodrone
biodrone marked this pull request as ready for review June 30, 2026 16:05
@biodrone
biodrone merged commit da96854 into staging Jun 30, 2026
9 checks passed
@biodrone
biodrone deleted the cursor/tick-notice-buffer-4c96 branch June 30, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants