@@ -6,9 +6,9 @@ use futures::channel::mpsc::UnboundedReceiver;
66use futures:: stream:: { FuturesUnordered , SelectAll } ;
77use futures:: StreamExt ;
88use log:: { debug, error, warn} ;
9- use shvclient:: clientapi:: { CallRpcMethodErrorKind , RpcCall , RpcCallDirExists , RpcCallLsList , Subscriber } ;
9+ use shvclient:: clientapi:: { CallRpcMethodErrorKind , RpcCall , RpcCallDirExists , RpcCallLsList , ShvApiVersion , Subscriber } ;
1010use shvclient:: clientnode:: { METH_DIR , SIG_CHNG } ;
11- use shvclient:: { ClientCommandSender , ClientEventsReceiver } ;
11+ use shvclient:: { ClientCommandSender , ClientEvent , ClientEventsReceiver } ;
1212use shvproto:: { DateTime , RpcValue } ;
1313use shvrpc:: rpcmessage:: RpcError ;
1414use shvrpc:: typeinfo:: TypeInfo ;
@@ -29,6 +29,10 @@ pub(crate) enum SiteOnlineStatus {
2929 Online = 2 ,
3030}
3131
32+ pub ( crate ) enum SitesCommand {
33+ ReloadSites ,
34+ }
35+
3236#[ derive( Clone , Default ) ]
3337pub ( crate ) struct SitesData {
3438 pub ( crate ) sites_info : Arc < BTreeMap < String , SiteInfo > > ,
@@ -337,9 +341,46 @@ pub(crate) async fn sites_task(
337341 client_cmd_tx : ClientCommandSender ,
338342 client_evt_rx : ClientEventsReceiver ,
339343 app_state : Arc < State > ,
344+ mut sites_cmd_rx : UnboundedReceiver < SitesCommand > ,
340345)
341346{
342- let mut client_evt_rx = client_evt_rx. fuse ( ) ;
347+ enum Event {
348+ ClientEvent ( shvclient:: ClientEvent ) ,
349+ SitesCommand ( SitesCommand , ShvApiVersion ) ,
350+ }
351+
352+ let ( evt_tx, mut evt_rx) = futures:: channel:: mpsc:: unbounded :: < Event > ( ) ;
353+
354+ let channel_combiner = tokio:: spawn ( async move {
355+ let mut client_evt_rx = client_evt_rx. fuse ( ) ;
356+ let mut current_shv_api_version = None ;
357+ loop {
358+ futures:: select! {
359+ client_event = client_evt_rx. select_next_some( ) => {
360+ match & client_event {
361+ shvclient:: ClientEvent :: Connected ( shv_api_version) => {
362+ current_shv_api_version = Some ( shv_api_version. clone( ) ) ;
363+ } ,
364+ shvclient:: ClientEvent :: Disconnected => {
365+ current_shv_api_version = None ;
366+ } ,
367+ shvclient:: ClientEvent :: ConnectionFailed ( _) => ( ) ,
368+ }
369+
370+ evt_tx. unbounded_send( Event :: ClientEvent ( client_event) ) . expect( "channel_combiner must work" ) ;
371+ } ,
372+ sites_command = sites_cmd_rx. select_next_some( ) => {
373+ let Some ( current_shv_api_version) = & current_shv_api_version else {
374+ warn!( "Got a SitesCommand when disconnected" ) ;
375+ continue ;
376+ } ;
377+ evt_tx. unbounded_send( Event :: SitesCommand ( sites_command, current_shv_api_version. clone( ) ) ) . expect( "channel_combiner must work" ) ;
378+ } ,
379+ complete => break ,
380+ }
381+ }
382+ } ) ;
383+
343384 let mut mntchng_subscribers = SelectAll :: < Subscriber > :: default ( ) ;
344385 let mut subscribers = SelectAll :: < Subscriber > :: default ( ) ;
345386 let mut online_status_channels = BTreeMap :: new ( ) ;
@@ -394,8 +435,8 @@ pub(crate) async fn sites_task(
394435
395436 ' main_loop: loop {
396437 futures:: select! {
397- client_event = client_evt_rx . select_next_some( ) => match client_event {
398- shvclient:: ClientEvent :: Connected ( shv_api_version) => {
438+ event = evt_rx . select_next_some( ) => match event {
439+ Event :: SitesCommand ( SitesCommand :: ReloadSites , shv_api_version ) | Event :: ClientEvent ( shvclient:: ClientEvent :: Connected ( shv_api_version) ) => {
399440 log:: info!( "Getting sites info" ) ;
400441
401442 let ( sites_info, sub_hps) = ' sites_get_loop: loop {
@@ -597,8 +638,8 @@ pub(crate) async fn sites_task(
597638 . unbounded_send( PeriodicSyncCommand :: Enable )
598639 . unwrap_or_else( |e| log:: error!( "Cannot send periodic sync enable command: {e}" ) ) ;
599640
600- }
601- _ => {
641+ } ,
642+ Event :: ClientEvent ( ClientEvent :: Disconnected ) | Event :: ClientEvent ( ClientEvent :: ConnectionFailed ( _ ) ) => {
602643 subscribers. clear( ) ;
603644 mntchng_subscribers. clear( ) ;
604645 online_status_channels. clear( ) ;
@@ -692,6 +733,10 @@ pub(crate) async fn sites_task(
692733 } ;
693734 }
694735
736+ if let Err ( err) = channel_combiner. await {
737+ log:: error!( "Failed to join online_status_task: {err}" )
738+ }
739+
695740 log:: debug!( "sites task finished" ) ;
696741}
697742
@@ -971,7 +1016,8 @@ mod tests {
9711016 dirtylog_cmd_rx,
9721017 sync_cmd_rx,
9731018 } ;
974- let sites_task = tokio:: spawn ( sites_task ( ccs, cer, state) ) ;
1019+ let ( _sites_cmd_tx, sites_cmd_rx) = futures:: channel:: mpsc:: unbounded ( ) ;
1020+ let sites_task = tokio:: spawn ( sites_task ( ccs, cer, state, sites_cmd_rx) ) ;
9751021 ( sites_task, task_state)
9761022 } ,
9771023 |state| {
0 commit comments