@@ -10,6 +10,14 @@ mod warnings {
1010}
1111pub use warnings:: Warning ;
1212
13+ #[ cfg( feature = "tracing" ) ]
14+ pub trait RadioChannel < T > : ' static + PartialEq + Eq + Clone + Hash + std:: fmt:: Debug + Ord {
15+ fn derive_channel ( self , _radio : & T ) -> Vec < Self > {
16+ vec ! [ self ]
17+ }
18+ }
19+
20+ #[ cfg( not( feature = "tracing" ) ) ]
1321pub trait RadioChannel < T > : ' static + PartialEq + Eq + Clone {
1422 fn derive_channel ( self , _radio : & T ) -> Vec < Self > {
1523 vec ! [ self ]
9098 pub ( crate ) fn notify_listeners ( & self , channel : & Channel ) {
9199 let mut listeners = self . listeners . write_unchecked ( ) ;
92100
101+ #[ cfg( feature = "tracing" ) ]
102+ tracing:: info!( "Notifying {channel:?}" ) ;
103+
93104 // Remove dropped listeners
94105 dioxus_lib:: prelude:: warnings:: copy_value_hoisted:: allow ( || {
95106 listeners. retain ( |_, listener| listener. drop_signal . try_write ( ) . is_ok ( ) ) ;
@@ -123,6 +134,30 @@ where
123134 pub fn peek ( & self ) -> ReadableRef < Signal < Value > > {
124135 self . value . peek ( )
125136 }
137+
138+ #[ cfg( not( feature = "tracing" ) ) ]
139+ pub fn print_metrics ( & self ) { }
140+
141+ #[ cfg( feature = "tracing" ) ]
142+ pub fn print_metrics ( & self ) {
143+ use itertools:: Itertools ;
144+ use tracing:: { info, span, Level } ;
145+
146+ let mut channels_subscribers = HashMap :: < & Channel , usize > :: new ( ) ;
147+
148+ let listeners = self . listeners . peek ( ) ;
149+
150+ for sub in listeners. values ( ) {
151+ * channels_subscribers. entry ( & sub. channel ) . or_default ( ) += 1 ;
152+ }
153+
154+ let span = span ! ( Level :: DEBUG , "Radio Station Metrics" ) ;
155+ let _enter = span. enter ( ) ;
156+
157+ for ( channel, count) in channels_subscribers. iter ( ) . sorted ( ) {
158+ info ! ( " {count} subscribers for {channel:?}" )
159+ }
160+ }
126161}
127162
128163pub struct RadioAntenna < Value , Channel >
@@ -181,6 +216,9 @@ where
181216 for channel in & mut self . channels {
182217 self . antenna . peek ( ) . station . notify_listeners ( channel)
183218 }
219+ if !self . channels . is_empty ( ) {
220+ self . antenna . peek ( ) . station . print_metrics ( ) ;
221+ }
184222 }
185223}
186224
@@ -353,57 +391,36 @@ where
353391 /// Example:
354392 ///
355393 /// ```rs
356- /// radio.write_with_map_channel (|value| {
394+ /// radio.write_with_channel_selection (|value| {
357395 /// // Modify `value`
358396 /// if value.cool {
359- /// Channel::Whatever
397+ /// ChannelSelection::Select( Channel::Whatever)
360398 /// } else {
361- /// Channel::SomethingElse
399+ /// ChannelSelection::Silence
362400 /// }
363401 /// });
364402 /// ```
365- pub fn write_with_map_channel ( & mut self , cb : impl FnOnce ( & mut Value ) -> Channel ) {
366- let value = self . antenna . peek ( ) . station . value . write_unchecked ( ) ;
367- let mut guard = RadioGuard {
368- channels : Vec :: default ( ) ,
369- antenna : self . antenna ,
370- value,
371- } ;
372- let channel = cb ( & mut guard. value ) ;
373- for channel in channel. derive_channel ( & guard. value ) {
374- self . antenna . peek ( ) . station . notify_listeners ( & channel)
375- }
376- }
377-
378- /// Get a mutable reference to the current state value, inside a callback that returns the channel to be used or none (will use the [Radio]'s one then).
379- ///
380- /// Example:
381- ///
382- /// ```rs
383- /// radio.write_with_map_optional_channel(|value| {
384- /// // Modify `value`
385- /// if value.cool {
386- /// Some(Channel::Whatever)
387- /// } else {
388- /// None
389- /// }
390- /// });
391- /// ```
392- pub fn write_with_map_optional_channel (
403+ pub fn write_with_channel_selection (
393404 & mut self ,
394- cb : impl FnOnce ( & mut Value ) -> Option < Channel > ,
405+ cb : impl FnOnce ( & mut Value ) -> ChannelSelection < Channel > ,
395406 ) {
396407 let value = self . antenna . peek ( ) . station . value . write_unchecked ( ) ;
397408 let mut guard = RadioGuard {
398409 channels : Vec :: default ( ) ,
399410 antenna : self . antenna ,
400411 value,
401412 } ;
402- let channel = cb ( & mut guard. value ) ;
413+ let channel_selection = cb ( & mut guard. value ) ;
414+ let channel = match channel_selection {
415+ ChannelSelection :: Current => Some ( self . antenna . peek ( ) . channel . clone ( ) ) ,
416+ ChannelSelection :: Silence => None ,
417+ ChannelSelection :: Select ( c) => Some ( c) ,
418+ } ;
403419 if let Some ( channel) = channel {
404420 for channel in channel. derive_channel ( & guard. value ) {
405421 self . antenna . peek ( ) . station . notify_listeners ( & channel)
406422 }
423+ self . antenna . peek ( ) . station . print_metrics ( ) ;
407424 }
408425 }
409426
@@ -421,6 +438,35 @@ where
421438 }
422439}
423440
441+ impl < Channel > Copy for ChannelSelection < Channel > where Channel : Copy { }
442+
443+ #[ derive( Clone ) ]
444+ pub enum ChannelSelection < Channel > {
445+ /// Notify the channel associated with the used [Radio].
446+ Current ,
447+ /// Notify a given [Channel].
448+ Select ( Channel ) ,
449+ /// No subscriber will be notified.
450+ Silence ,
451+ }
452+
453+ impl < Channel > ChannelSelection < Channel > {
454+ /// Change to [ChannelSelection::Current]
455+ pub fn current ( & mut self ) {
456+ * self = Self :: Current
457+ }
458+
459+ /// Change to [ChannelSelection::Select]
460+ pub fn select ( & mut self , channel : Channel ) {
461+ * self = Self :: Select ( channel)
462+ }
463+
464+ /// Change to [ChannelSelection::Silence]
465+ pub fn silence ( & mut self ) {
466+ * self = Self :: Silence
467+ }
468+ }
469+
424470/// Consume the state and subscribe using the given `channel`
425471/// Any mutation using this radio will notify other subscribers to the same `channel`,
426472/// unless you explicitely pass a custom channel using other methods as [`Radio::write_channel()`]
@@ -462,7 +508,7 @@ pub trait DataReducer {
462508 type Channel ;
463509 type Action ;
464510
465- fn reduce ( & mut self , action : Self :: Action ) -> Self :: Channel ;
511+ fn reduce ( & mut self , action : Self :: Action ) -> ChannelSelection < Self :: Channel > ;
466512}
467513
468514pub trait RadioReducer {
@@ -480,7 +526,7 @@ impl<
480526 type Action = Action ;
481527
482528 fn apply ( & mut self , action : Action ) {
483- self . write_with_map_channel ( |data| data. reduce ( action) ) ;
529+ self . write_with_channel_selection ( |data| data. reduce ( action) ) ;
484530 }
485531}
486532
@@ -492,7 +538,7 @@ pub trait DataAsyncReducer {
492538 async fn async_reduce (
493539 _radio : & mut Radio < Self , Self :: Channel > ,
494540 _action : Self :: Action ,
495- ) -> Self :: Channel
541+ ) -> ChannelSelection < Self :: Channel >
496542 where
497543 Self :: Channel : RadioChannel < Self > ,
498544 Self : Sized ;
@@ -521,7 +567,7 @@ impl<
521567 let mut radio = * self ;
522568 spawn ( async move {
523569 let channel = Data :: async_reduce ( & mut radio, action) . await ;
524- radio. write_with_map_channel ( |_| channel) ;
570+ radio. write_with_channel_selection ( |_| channel) ;
525571 } ) ;
526572 }
527573}
0 commit comments