@@ -12,7 +12,9 @@ use moq_transport::{
1212} ;
1313use tokio:: sync:: Semaphore ;
1414
15- use crate :: { metrics:: GaugeGuard , Coordinator , Locals , Producer , RemoteManager , SessionContext } ;
15+ use crate :: {
16+ metrics:: GaugeGuard , Coordinator , Locals , Producer , RemoteManager , SessionContext , TrackRequest ,
17+ } ;
1618
1719const MAX_INBOUND_PUBLISH_TRACKS_PER_SESSION : usize = 1024 ;
1820
@@ -254,11 +256,11 @@ impl Consumer {
254256 tracing:: info!( namespace = %ns, "PUBLISH_NAMESPACE closed" ) ;
255257 return Ok ( ( ) ) ;
256258 } ,
257- Some ( track ) = requests. recv( ) => {
259+ Some ( TrackRequest { writer , lease } ) = requests. recv( ) => {
258260 let mut subscriber = self . subscriber. clone( ) ;
259261
260262 tasks. push( async move {
261- let info = track . clone( ) ;
263+ let info = writer . info . clone( ) ;
262264 let namespace = info. namespace. to_utf8_path( ) ;
263265 let track_name = info. name. clone( ) ;
264266 tracing:: info!(
@@ -267,15 +269,47 @@ impl Consumer {
267269 "forwarding subscribe: {:?}" , info
268270 ) ;
269271
270- if let Err ( err) = subscriber. subscribe( track) . await {
271- tracing:: warn!(
272- namespace = %namespace,
273- track = %track_name,
274- error = %err,
275- "failed forwarding subscribe: {:?}" , info
276- )
272+ // Hold the subscription explicitly rather than using
273+ // `subscribe()`, so it can be dropped — sending
274+ // UNSUBSCRIBE — once downstream interest goes away.
275+ let subscribe = match subscriber. subscribe_open( writer) . await {
276+ Ok ( subscribe) => subscribe,
277+ Err ( err) => {
278+ tracing:: warn!(
279+ namespace = %namespace,
280+ track = %track_name,
281+ error = %err,
282+ "failed forwarding subscribe: {:?}" , info
283+ ) ;
284+ return Ok ( ( ) ) ;
285+ }
286+ } ;
287+
288+ tokio:: select! {
289+ res = subscribe. closed( ) => {
290+ if let Err ( err) = res {
291+ tracing:: warn!(
292+ namespace = %namespace,
293+ track = %track_name,
294+ error = %err,
295+ "failed forwarding subscribe: {:?}" , info
296+ )
297+ }
298+ }
299+ // The cached track went unwatched long enough to be
300+ // evicted, so stop pulling it. Dropping `subscribe`
301+ // below sends UNSUBSCRIBE upstream.
302+ _ = lease. released( ) => {
303+ tracing:: info!(
304+ namespace = %namespace,
305+ track = %track_name,
306+ "releasing upstream subscription for idle cached track"
307+ ) ;
308+ }
277309 }
278310
311+ drop( subscribe) ;
312+
279313 Ok ( ( ) )
280314 } . boxed( ) ) ;
281315 } ,
@@ -352,13 +386,13 @@ impl Consumer {
352386 }
353387
354388 tracing:: debug!(
355- namespace = %namespace. to_utf8_path ( ) ,
389+ namespace = %namespace,
356390 track = %track_name,
357391 "PUBLISH registered as exact local track"
358392 ) ;
359393
360394 publish. closed ( ) . await ?;
361- tracing:: info!( namespace = %namespace. to_utf8_path ( ) , track = %track_name, "PUBLISH closed" ) ;
395+ tracing:: info!( namespace = %namespace, track = %track_name, "PUBLISH closed" ) ;
362396
363397 Ok ( ( ) )
364398 }
0 commit comments