wayle_network/core/settings/
monitoring.rs1use std::sync::{Arc, Weak};
2
3use futures::StreamExt;
4use tokio_util::sync::CancellationToken;
5use tracing::{debug, warn};
6use wayle_core::remove_and_cancel;
7use wayle_traits::{ModelMonitoring, Reactive};
8use zbus::zvariant::OwnedObjectPath;
9
10use super::Settings;
11use crate::{
12 core::settings_connection::{ConnectionSettings, ConnectionSettingsParams},
13 error::Error,
14 proxy::settings::SettingsProxy,
15};
16
17impl ModelMonitoring for Settings {
18 type Error = Error;
19
20 async fn start_monitoring(self: Arc<Self>) -> Result<(), Self::Error> {
21 let Some(ref cancellation_token) = self.cancellation_token else {
22 return Err(Error::MissingCancellationToken);
23 };
24
25 let settings_proxy = SettingsProxy::new(&self.zbus_connection).await?;
26 let cancel_token = cancellation_token.clone();
27 let weak_self = Arc::downgrade(&self);
28
29 tokio::spawn(async move {
30 if let Err(e) = monitor(weak_self, settings_proxy, cancel_token).await {
31 warn!(error = %e, "cannot start settings monitor");
32 }
33 });
34
35 Ok(())
36 }
37}
38
39#[allow(clippy::cognitive_complexity)]
40async fn monitor(
41 weak_settings: Weak<Settings>,
42 settings_proxy: SettingsProxy<'_>,
43 cancellation_token: CancellationToken,
44) -> Result<(), Error> {
45 let mut connection_removed = settings_proxy.receive_connection_removed().await;
46 let mut connection_added = settings_proxy.receive_new_connection().await;
47 let mut hostname_changed = settings_proxy.receive_hostname_changed().await;
48 let mut can_modify_changed = settings_proxy.receive_can_modify_changed().await;
49 let mut version_id_changed = settings_proxy.receive_version_id_changed().await;
50
51 loop {
52 let Some(settings) = weak_settings.upgrade() else {
53 return Ok(());
54 };
55
56 tokio::select! {
57 _ = cancellation_token.cancelled() => {
58 debug!("SettingsMonitor cancelled");
59 return Ok(());
60 }
61 Some(event) = async { connection_added.as_mut().ok()?.next().await }, if
62 connection_added.is_ok() => {
63 if let Ok(args) = event.args() {
64 let _ = add_connection(args.connection, &settings).await;
65 }
66 }
67 Some(event) = async { connection_removed.as_mut().ok()?.next().await }, if
68 connection_removed.is_ok() => {
69 if let Ok(args) = event.args() {
70 let _ = remove_connection(args.connection, &settings).await;
71 }
72 }
73 Some(change) = hostname_changed.next() => {
74 if let Ok(new_hostname) = change.get().await {
75 settings.hostname.set(new_hostname);
76 }
77 }
78 Some(change) = can_modify_changed.next() => {
79 if let Ok(new_can_modify) = change.get().await {
80 settings.can_modify.set(new_can_modify);
81 }
82
83 }
84 Some(change) = version_id_changed.next() => {
85 if let Ok(new_version_id) = change.get().await {
86 settings.version_id.set(new_version_id);
87 }
88 }
89 else => {
90 warn!("All property streams ended for Settings");
91 break;
92 }
93 }
94 }
95
96 Ok(())
97}
98
99async fn add_connection(
100 connection_path: OwnedObjectPath,
101 settings: &Arc<Settings>,
102) -> Result<(), Error> {
103 let new_connection = ConnectionSettings::get(ConnectionSettingsParams {
104 connection: &settings.zbus_connection,
105 path: connection_path.clone(),
106 })
107 .await?;
108
109 let mut current_connections = settings.connections.get();
110
111 let found_connection = current_connections
112 .iter()
113 .find(|connection| connection.object_path == connection_path);
114
115 if found_connection.is_none() {
116 current_connections.push(new_connection);
117 settings.connections.set(current_connections);
118 }
119
120 Ok(())
121}
122
123async fn remove_connection(
124 connection_path: OwnedObjectPath,
125 settings: &Arc<Settings>,
126) -> Result<(), Error> {
127 remove_and_cancel!(settings.connections.clone(), connection_path);
128 Ok(())
129}