@@ -484,40 +484,40 @@ impl std::future::Future for InfoPending {
484484/// SUBSCRIBE_OK). It implements [`Future`], so `.await` it to get the
485485/// [`TrackSubscriber`] (or an error). Poll-based callers can instead drive it
486486/// with [`Self::poll_ok`] inside a `kio` poll loop.
487- pub struct TrackPending {
488- inner : TrackPendingInner ,
487+ pub struct SubscribePending {
488+ inner : SubscribePendingInner ,
489489 /// Kept alive between `Future::poll` calls so its registration in the
490490 /// resolver channel stays valid until the next poll replaces it.
491491 waiter : Option < kio:: Waiter > ,
492492}
493493
494- enum TrackPendingInner {
494+ enum SubscribePendingInner {
495495 /// Resolved synchronously: the track already existed, or it failed immediately.
496496 Ready ( Result < TrackSubscriber , Error > ) ,
497497 /// Waiting for the publisher to accept or deny via the dynamic handler.
498498 Waiting ( kio:: Consumer < PendingSlot > ) ,
499499}
500500
501- impl TrackPending {
501+ impl SubscribePending {
502502 fn ready ( result : Result < TrackSubscriber , Error > ) -> Self {
503503 Self {
504- inner : TrackPendingInner :: Ready ( result) ,
504+ inner : SubscribePendingInner :: Ready ( result) ,
505505 waiter : None ,
506506 }
507507 }
508508
509509 fn waiting ( consumer : kio:: Consumer < PendingSlot > ) -> Self {
510510 Self {
511- inner : TrackPendingInner :: Waiting ( consumer) ,
511+ inner : SubscribePendingInner :: Waiting ( consumer) ,
512512 waiter : None ,
513513 }
514514 }
515515
516516 /// Poll for the resolved [`TrackSubscriber`], without blocking.
517517 pub fn poll_ok ( & self , waiter : & kio:: Waiter ) -> Poll < Result < TrackSubscriber , Error > > {
518518 match & self . inner {
519- TrackPendingInner :: Ready ( result) => Poll :: Ready ( result. clone ( ) ) ,
520- TrackPendingInner :: Waiting ( consumer) => match consumer. poll ( waiter, |slot| match & * * slot {
519+ SubscribePendingInner :: Ready ( result) => Poll :: Ready ( result. clone ( ) ) ,
520+ SubscribePendingInner :: Waiting ( consumer) => match consumer. poll ( waiter, |slot| match & * * slot {
521521 Some ( result) => Poll :: Ready ( result. clone ( ) ) ,
522522 None => Poll :: Pending ,
523523 } ) {
@@ -533,7 +533,7 @@ impl TrackPending {
533533 }
534534}
535535
536- impl std:: future:: Future for TrackPending {
536+ impl std:: future:: Future for SubscribePending {
537537 type Output = Result < TrackSubscriber , Error > ;
538538
539539 fn poll ( self : std:: pin:: Pin < & mut Self > , cx : & mut std:: task:: Context < ' _ > ) -> Poll < Self :: Output > {
@@ -727,38 +727,38 @@ impl BroadcastConsumer {
727727 ///
728728 /// This is a cheap, synchronous lookup that returns a [`TrackConsumer`] bound
729729 /// to `name`. Nothing is sent to the publisher yet: call
730- /// [`TrackConsumer::subscribe`] to open a live subscription (blocking on
731- /// SUBSCRIBE_OK) , or hold the handle and subscribe later.
730+ /// [`TrackConsumer::subscribe`] to open a live subscription, [`TrackConsumer::info`]
731+ /// to resolve its properties , or hold the handle and act later.
732732 pub fn consume_track ( & self , name : & str ) -> TrackConsumer {
733733 TrackConsumer {
734734 broadcast : self . clone ( ) ,
735- name : name . to_string ( ) ,
735+ info : Track :: new ( name ) ,
736736 }
737737 }
738738
739- /// Register a subscription for `name` and return a [`TrackPending `] that
739+ /// Register a subscription for `name` and return a [`SubscribePending `] that
740740 /// resolves once the publisher accepts it.
741741 ///
742742 /// Reuses a live producer if one is already publishing the track (the pending
743743 /// resolves right away), otherwise queues a dynamic request served via
744744 /// [`BroadcastDynamic::requested_track`] and [`TrackRequest::accept`] (for the
745745 /// wire this is SUBSCRIBE_OK). Resolves to [`Error::NotFound`] if no dynamic
746746 /// producer exists to handle the request.
747- fn request_subscribe ( & self , name : & str , subscription : Subscription ) -> TrackPending {
747+ fn request_subscribe ( & self , name : & str , subscription : Subscription ) -> SubscribePending {
748748 // Upgrade to a temporary producer so we can modify the state.
749749 let Some ( producer) = self . state . produce ( ) else {
750750 let err = self . state . read ( ) . abort . clone ( ) . unwrap_or ( Error :: Dropped ) ;
751- return TrackPending :: ready ( Err ( err) ) ;
751+ return SubscribePending :: ready ( Err ( err) ) ;
752752 } ;
753753 let mut state = match modify ( & producer) {
754754 Ok ( state) => state,
755- Err ( err) => return TrackPending :: ready ( Err ( err) ) ,
755+ Err ( err) => return SubscribePending :: ready ( Err ( err) ) ,
756756 } ;
757757
758758 // Reuse a live producer if one is already publishing the track.
759759 if let Some ( weak) = state. tracks . get ( name) {
760760 if !weak. is_closed ( ) {
761- return TrackPending :: ready ( Ok ( weak. subscribe ( subscription) ) ) ;
761+ return SubscribePending :: ready ( Ok ( weak. subscribe ( subscription) ) ) ;
762762 }
763763 // Drop the stale entry and fall through to a fresh request.
764764 state. tracks . remove ( name) ;
@@ -771,7 +771,7 @@ impl BroadcastConsumer {
771771 // Coalesce onto an in-flight request for the same name.
772772 pending. resolvers . push ( ( subscription, slot) ) ;
773773 } else if state. dynamic == 0 {
774- return TrackPending :: ready ( Err ( Error :: NotFound ) ) ;
774+ return SubscribePending :: ready ( Err ( Error :: NotFound ) ) ;
775775 } else {
776776 state. requests . insert (
777777 name. to_string ( ) ,
@@ -783,7 +783,7 @@ impl BroadcastConsumer {
783783 state. request_order . push_back ( name. to_string ( ) ) ;
784784 }
785785
786- TrackPending :: waiting ( consumer)
786+ SubscribePending :: waiting ( consumer)
787787 }
788788
789789 /// Resolve a track's immutable info, returning an [`InfoPending`].
@@ -872,47 +872,57 @@ impl BroadcastConsumer {
872872
873873/// A handle to a single track within a broadcast.
874874///
875- /// Obtained from [`BroadcastConsumer::consume_track`]. Holding it sends nothing
876- /// to the publisher; it just names a track you can [`subscribe`](Self::subscribe)
877- /// to (a live, ongoing stream of groups) later. The same handle can be subscribed
878- /// to multiple times, and clones are cheap.
875+ /// Obtained from [`BroadcastConsumer::consume_track`]. Holding it sends nothing to
876+ /// the publisher; it just names a track you can [`subscribe`](Self::subscribe) to
877+ /// (a live, ongoing stream of groups) or resolve [`info`](Self::info) for later.
878+ /// Clones are cheap and concurrent operations on the same name coalesce onto one
879+ /// request.
880+ ///
881+ /// Only the track's `name` is known up front (available via `Deref`); every other
882+ /// property is resolved on demand via [`info`](Self::info), since for a relay it
883+ /// comes from upstream.
879884// TODO: add `fetch` for one-shot retrieval of a past group range.
880885#[ derive( Clone ) ]
881886pub struct TrackConsumer {
882887 broadcast : BroadcastConsumer ,
883- name : String ,
888+ /// Name-only [`Track`]: `Deref` exposes `name`; the other fields are
889+ /// placeholders until [`Self::info`] resolves the real values.
890+ info : Track ,
884891}
885892
886- impl TrackConsumer {
887- /// The track name this handle is bound to.
888- pub fn name ( & self ) -> & str {
889- & self . name
893+ impl Deref for TrackConsumer {
894+ type Target = Track ;
895+
896+ fn deref ( & self ) -> & Self :: Target {
897+ & self . info
890898 }
899+ }
891900
901+ impl TrackConsumer {
892902 /// Open a live subscription.
893903 ///
894- /// Returns a [`TrackPending `] that resolves once the publisher accepts the
895- /// subscription (SUBSCRIBE_OK on the wire) . `.await` it for the
896- /// [`TrackSubscriber`], which carries the publisher's [`Track`] and reads its
897- /// groups; or drive it with [`TrackPending ::poll_ok`] from a poll loop.
904+ /// Returns a [`SubscribePending `] that resolves once the publisher accepts the
905+ /// subscription. `.await` it for the [`TrackSubscriber`], which carries the
906+ /// publisher's [`Track`] and reads its groups; or drive it with
907+ /// [`SubscribePending ::poll_ok`] from a poll loop.
898908 ///
899909 /// `subscription` is this subscriber's preferences and feeds the producer's
900910 /// [`TrackProducer::subscription`] aggregate; pass `None` for
901911 /// [`Subscription::default`]. Concurrent subscribers to the same name coalesce
902912 /// onto one request.
903- pub fn subscribe ( & self , subscription : impl Into < Option < Subscription > > ) -> TrackPending {
913+ pub fn subscribe ( & self , subscription : impl Into < Option < Subscription > > ) -> SubscribePending {
904914 self . broadcast
905- . request_subscribe ( & self . name , subscription. into ( ) . unwrap_or_default ( ) )
915+ . request_subscribe ( & self . info . name , subscription. into ( ) . unwrap_or_default ( ) )
906916 }
907917
908- /// Resolve this track's immutable [`Track`] info without subscribing .
918+ /// Resolve this track's immutable [`Track`] info.
909919 ///
910920 /// Returns an [`InfoPending`] that resolves to the publisher's properties
911921 /// (timescale, compression, cache). Warm (cached or a live producer exists) it
912922 /// resolves with no round trip; cold it triggers a single TRACK lookup. Reused
913923 /// across every subscribe and fetch of the track.
914924 pub fn info ( & self ) -> InfoPending {
915- self . broadcast . request_info ( & self . name )
925+ self . broadcast . request_info ( & self . info . name )
916926 }
917927}
918928
@@ -932,7 +942,7 @@ mod test {
932942 use super :: * ;
933943
934944 /// Subscribe and assert the result hasn't resolved yet (it stays pending until
935- /// a publisher accepts). Returns the [`TrackPending `] to resolve after accepting.
945+ /// a publisher accepts). Returns the [`SubscribePending `] to resolve after accepting.
936946 macro_rules! subscribe_pending {
937947 ( $consumer: expr, $name: expr) => { {
938948 let pending = $consumer. consume_track( $name) . subscribe( None ) ;
0 commit comments