@@ -388,6 +388,23 @@ impl OpenAiSpokespersonRuntime {
388388 }
389389}
390390
391+ impl Drop for OpenAiSpokespersonRuntime {
392+ fn drop ( & mut self ) {
393+ let _ = self . commands . send ( SpokespersonCommand :: Shutdown ) ;
394+ if let Some ( worker) = self . worker . take ( ) {
395+ reap_spokesperson_worker ( worker) ;
396+ }
397+ }
398+ }
399+
400+ fn reap_spokesperson_worker ( worker : thread:: JoinHandle < ( ) > ) {
401+ let _ = thread:: Builder :: new ( )
402+ . name ( "berd-voice-spokesperson-reaper" . into ( ) )
403+ . spawn ( move || {
404+ let _ = worker. join ( ) ;
405+ } ) ;
406+ }
407+
391408#[ cfg( test) ]
392409async fn run (
393410 config : OpenAiSpokespersonConfig ,
@@ -1366,6 +1383,49 @@ mod tests {
13661383 server. await . unwrap ( ) ;
13671384 }
13681385
1386+ #[ tokio:: test]
1387+ async fn dropping_runtime_signals_and_reaps_its_worker ( ) {
1388+ let listener = TcpListener :: bind ( "127.0.0.1:0" ) . await . unwrap ( ) ;
1389+ let endpoint = format ! ( "ws://{}/" , listener. local_addr( ) . unwrap( ) ) ;
1390+ let server = tokio:: spawn ( async move {
1391+ let ( stream, _) = listener. accept ( ) . await . unwrap ( ) ;
1392+ let mut socket = accept_hdr_async ( stream, require_test_authorization)
1393+ . await
1394+ . unwrap ( ) ;
1395+ let update = receive_json ( & mut socket) . await ;
1396+ acknowledge_initial_session ( & mut socket, & update, "test-model" ) . await ;
1397+ let silence = receive_json ( & mut socket) . await ;
1398+ assert_eq ! ( silence[ "type" ] , "input_audio_buffer.append" ) ;
1399+ assert ! ( matches!(
1400+ socket. next( ) . await ,
1401+ Some ( Ok ( Message :: Close ( _) ) ) | None
1402+ ) ) ;
1403+ } ) ;
1404+
1405+ let ( runtime, events) = OpenAiSpokespersonRuntime :: spawn_observed ( test_config (
1406+ endpoint,
1407+ "test-voice" ,
1408+ 1.0 ,
1409+ Vec :: new ( ) ,
1410+ ) )
1411+ . unwrap ( ) ;
1412+ tokio:: task:: spawn_blocking ( move || {
1413+ loop {
1414+ if matches ! (
1415+ events. recv_timeout( Duration :: from_secs( 2 ) ) . unwrap( ) ,
1416+ SpokespersonEvent :: Ready
1417+ ) {
1418+ break ;
1419+ }
1420+ }
1421+ drop ( runtime) ;
1422+ } )
1423+ . await
1424+ . unwrap ( ) ;
1425+
1426+ server. await . unwrap ( ) ;
1427+ }
1428+
13691429 #[ tokio:: test]
13701430 async fn replacement_seed_accepts_current_and_legacy_provider_acknowledgements ( ) {
13711431 let listener = TcpListener :: bind ( "127.0.0.1:0" ) . await . unwrap ( ) ;
0 commit comments