wayle-sysinfo 0.1.2

CPU, memory, disk, and network metrics
Documentation
use std::time::Duration;

use sysinfo::Disks;
use tokio::time::interval;
use tokio_util::sync::CancellationToken;
use tracing::debug;
use wayle_core::Property;

use crate::types::DiskData;

pub(crate) fn spawn(
    token: CancellationToken,
    disks: Property<Vec<DiskData>>,
    poll_interval: Duration,
) {
    tokio::spawn(async move {
        let mut sysinfo_disks = Disks::new_with_refreshed_list();
        let mut ticker = interval(poll_interval);

        loop {
            if !disks.has_subscribers() {
                tokio::select! {
                    _ = token.cancelled() => {
                        debug!("Disk polling cancelled");
                        return;
                    }
                    _ = disks.wait_for_subscribers() => {}
                }
                ticker.reset();
            }

            if !disks.has_subscribers() {
                continue;
            }

            sysinfo_disks.refresh(false);

            let data: Vec<DiskData> = sysinfo_disks
                .iter()
                .map(|disk| {
                    let total = disk.total_space();
                    let available = disk.available_space();
                    let used = total.saturating_sub(available);

                    let usage_percent = if total > 0 {
                        (used as f32 / total as f32) * 100.0
                    } else {
                        0.0
                    };

                    DiskData {
                        mount_point: disk.mount_point().to_path_buf(),
                        filesystem: disk.file_system().to_string_lossy().to_string(),
                        total_bytes: total,
                        used_bytes: used,
                        available_bytes: available,
                        usage_percent,
                    }
                })
                .collect();

            disks.set(data);

            tokio::select! {
                _ = token.cancelled() => {
                    debug!("Disk polling cancelled");
                    return;
                }
                _ = ticker.tick() => {}
            }
        }
    });
}