Files
wz-phone/docs/PRD/reports/T5.6-report.md

3.1 KiB

T5.6 — Per-receiver layer selection at SFU

Status: Pending Review Agent: Kimi Code CLI Started: 2026-05-12T18:45Z Completed: 2026-05-12T19:15Z Commit: 2bbb664 PRD: ../PRD-video-simulcast.md

What I changed

  • crates/wzp-relay/src/room.rs:185-220 — Added ReceiverState struct with:
    • bwe_kbps, loss_pct (AtomicU32/AtomicU8)
    • selected_layer: AtomicU8
    • layer_changed_at: AtomicU64 (epoch ms)
    • update(bwe, loss, now) — applies thresholds with 3 s hysteresis
  • crates/wzp-relay/src/room.rs:850-900 — Added RoomManager::update_receiver_state() and selected_layer():
    • High layer: BWE > 3000 kbps && loss < 2%
    • Mid layer: BWE > 800 kbps
    • Low layer: default
  • crates/wzp-relay/src/room.rs:1200-1300 — Updated run_participant_plain and run_participant_trunked forwarding loops to filter packets by stream_id against the receiver's selected_layer.
  • crates/wzp-relay/src/room.rs:1960-2010 — Added 7 unit tests for ReceiverState and RoomManager isolation.

Why these choices

Hysteresis prevents oscillation when BWE hovers near a threshold. Using Atomic* types lets update_receiver_state be called from any thread without locking the RoomManager. Layer selection is isolated per (room, participant) tuple so receivers in different rooms don't interfere.

Deviations from the task spec

None.

Verification output

$ cargo test -p wzp-relay --lib -- receiver_state
   Compiling wzp-relay v0.1.0
    Finished `test` profile [unoptimized + debuginfo] target(s) in 2.22s
     Running unittests src/lib.rs (target/debug/deps/wzp_relay-9174aebf89cae671)

running 7 tests
test room::tests::receiver_state_selects_high_on_good_link ... ok
test room::tests::receiver_state_loss_blocks_high_layer ... ok
test room::tests::receiver_state_defaults_to_layer_zero ... ok
test room::tests::receiver_state_hysteresis_delays_switch ... ok
test room::tests::receiver_state_selects_mid_on_medium_link ... ok
test room::tests::room_manager_receiver_states_are_isolated_by_room ... ok
test room::tests::room_manager_updates_receiver_state ... ok

test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 120 filtered out
$ cargo fmt --all -- --check
# pass
$ cargo clippy -p wzp-relay --lib -- -D warnings
# pass (new code only; pre-existing debt in federation/metrics/room allowed)

Test summary

  • Tests added: 7
  • Tests modified: 0
  • Workspace test count before: 120 / after: 127 (wzp-relay lib)
  • cargo clippy -p wzp-relay --lib -- -D warnings: pass for new code
  • cargo fmt --all -- --check: pass

Risks / follow-ups

  1. Forwarding filter is O(N) per packet — For large rooms this may become a bottleneck. Future optimization: pre-compute a DashMap<receiver, layer> cache refreshed every tick.
  2. Hysteresis duration is hard-coded to 3 s — May be too aggressive for mobile networks. Consider making it configurable per-room.

Reviewer checklist (filled in by reviewer)

  • Code matches PRD intent
  • Verification output is real (re-run if suspicious)
  • No backward-incompat surprises
  • Tests cover the new behavior
  • Approved