feat(client): subscribe and wait_for (#6) #24
No reviewers
Labels
No labels
area:assertions
area:cli
area:client
area:harness
area:meta
area:reporting
area:runner
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/ws-rpc-test!24
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/6-subscribe-wait-for"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #6. Stacked on #23.
Summary
Adds the user-facing event API on top of #5's notification buffer.
subscribe
subscribe(events: &[&str])sends{"method":"subscribe","params":{"events":[...]}}and awaits success.wait_for
wait_for(method, predicate, timeout) -> Result<Value, TestError>whereF: Fn(&Value) -> bool + Send + Sync.broadcast::Receiver::recvuntil match / deadline / connection close. On a broadcast hit, atomically claims the match from the buffer viatry_drain_notificationso concurrent waiters can't double-deliver (first waiter wins, per spec).RecvError::Laggedby re-scanning the buffer.TestError::Timeout { event: method.into(), duration }.Drops the
#[allow(dead_code)]markers introduced in #5 —try_drain_notificationandsubscribe_notificationsare now used bywait_for.Checklist (from issue #6)
subscribe
{"method":"subscribe","params":{"events":[...]}}and awaits successwait_for
Fn(&Value) -> bool + Send + Syncparamson hitTestError::Timeout { event: method, duration }wait_forcalls safe — first matching waiter winsTest plan (6 new tests)
subscribe_sends_subscribe_request_with_eventswait_for_returns_buffered_notification(notification arrives before wait_for)wait_for_picks_up_future_notification(wait_for spawned before notification — exercises broadcast path)wait_for_times_out_on_no_matchwait_for_filters_by_predicate— 3 notifications, predicate selects 1, asserts other 2 stay bufferedwait_for_skips_non_matching_method— noise on a different method does not wake the waiterjust qagreen locally — 40/40 unit testsNotes for the reviewer
wait_for_picks_up_future_notification) that fails reliably if you swap the order.if let Some(claimed)check.Laggedis treated as "broadcast queue is full, so we may have missed something — rescan the persistent buffer". The persistent buffer is the source of truth.subscribefalls through to the default echo branch which returns a successful response, which is all thatsubscribe()needs.Review — subscribe et wait_for (#6)
Race-free design
C'est exactement le bon ordre. Le commentaire l'explique clairement. Excellent.
Gestion de
RecvError::LaggedQuand le receiver a trop pris de retard, le code rescanne le buffer — correct. Si plusieurs notifications sont arrivées pendant le lag, on en retourne une seule (la première match dans le buffer) et on abandonne les autres au buffer. Comportement attendu.
"Double-claim" race entre waiters concurrents
Le
try_drainaprès réception du broadcast est le mécanisme qui empêche deux waiters de retourner la même notification. Propre.subscribe()— sémantique replace-not-additiveBien documenté dans le doc-comment. La sémantique dépend du serveur, pas du client — le client envoie juste l'appel RPC. La doc est correcte sur ce point.
Tests
wait_for_returns_buffered_notification: vérifie le fast-path buffer.wait_for_picks_up_future_notification: vérifie le slow-path broadcast.wait_for_filters_by_predicate: vérifie que les non-matchants restent en buffer pour d'autres waiters.Aucun bloquant.
✅ Pas de bloquant —
wait_forest correctement race-free, gestion duLaggedpropre, tests exhaustifs.