feat: client-server mode

This commit is contained in:
electria 2026-08-16 12:15:46 -07:00
commit a689366324
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs
7 changed files with 119 additions and 28 deletions

View file

@ -1,28 +1,63 @@
use std::env;
use iced::{
Task,
futures::{self, SinkExt},
stream,
};
use smol::Timer;
use ron::de;
use smol::{Timer, unblock};
use crate::sysinfo_snapshot::SysinfoSnapshot;
use crate::{app, sysinfo_snapshot::SysinfoSnapshot};
pub fn create() -> impl futures::Stream<Item = SysinfoSnapshot> {
stream::channel(
1,
async |mut sender: futures::channel::mpsc::Sender<SysinfoSnapshot>| {
let mut sys = sysinfo::System::new();
let refreshes = sysinfo::RefreshKind::nothing()
.with_memory(sysinfo::MemoryRefreshKind::everything())
.with_cpu(sysinfo::CpuRefreshKind::nothing().with_cpu_usage());
pub fn create() -> Task<app::Message> {
if env::args()
.nth(1)
.is_some_and(|command| command == "client")
{
Task::run(
stream::channel(
1,
async |mut sender: futures::channel::mpsc::Sender<SysinfoSnapshot>| {
let mut buf = String::new();
loop {
buf = unblock(move || {
std::io::stdin().read_line(&mut buf).unwrap();
buf
})
.await;
sys.refresh_specifics(refreshes);
Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await;
match de::from_str(&buf) {
Ok(info) => sender.send(info).await.unwrap(),
Err(e) => eprintln!("{e}"),
}
buf.clear();
}
},
),
app::Message::Info,
)
} else {
Task::run(
stream::channel(
1,
async |mut sender: futures::channel::mpsc::Sender<SysinfoSnapshot>| {
let mut sys = sysinfo::System::new();
let refreshes = sysinfo::RefreshKind::nothing()
.with_memory(sysinfo::MemoryRefreshKind::everything())
.with_cpu(sysinfo::CpuRefreshKind::nothing().with_cpu_usage());
loop {
sys.refresh_specifics(refreshes);
sender.send(SysinfoSnapshot::from(&sys)).await.unwrap();
Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await;
}
},
)
sys.refresh_specifics(refreshes);
Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await;
loop {
sys.refresh_specifics(refreshes);
sender.send(SysinfoSnapshot::from(&sys)).await.unwrap();
Timer::after(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL).await;
}
},
),
app::Message::Info,
)
}
}

View file

@ -1,6 +1,6 @@
use std::time::Duration;
use iced::{Color, Element, Length, Renderer, Task, Theme, application, theme, widget};
use iced::{Color, Element, Error, Length, Renderer, Task, Theme, application, theme, widget};
use crate::{app::graph::Graph, sysinfo_snapshot::SysinfoSnapshot};
@ -23,10 +23,7 @@ struct State {
impl State {
fn new() -> (Self, Task<Message>) {
(
Self::default(),
Task::run(info_stream::create(), Message::Info),
)
(Self::default(), info_stream::create())
}
fn update(&mut self, message: Message) -> Task<Message> {
match message {
@ -95,7 +92,7 @@ impl State {
}
}
pub fn run() -> Result<(), impl std::error::Error> {
pub fn run() -> Result<(), Error> {
application(State::new, State::update, State::view)
.title(State::title)
.theme(theme::Theme::custom(

View file

@ -1,6 +1,15 @@
use std::env;
mod app;
mod server;
mod sysinfo_snapshot;
fn main() -> Result<(), impl std::error::Error> {
app::run()
fn main() {
match env::args().nth(1).as_deref() {
Some("server") => server::run().unwrap(),
None | Some("client") => app::run().unwrap(),
Some(s) => panic!("invalid argument: {s}"),
}
}

23
src/server/mod.rs Normal file
View file

@ -0,0 +1,23 @@
use std::{io::Write, thread};
use ron::{Error, ser};
use crate::sysinfo_snapshot::SysinfoSnapshot;
pub fn run() -> Result<(), Error> {
let mut sys = sysinfo::System::new();
let refreshes = sysinfo::RefreshKind::nothing()
.with_memory(sysinfo::MemoryRefreshKind::everything())
.with_cpu(sysinfo::CpuRefreshKind::nothing().with_cpu_usage());
sys.refresh_specifics(refreshes);
thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
let mut stdout = std::io::stdout();
loop {
sys.refresh_specifics(refreshes);
stdout.write_all((ser::to_string(&SysinfoSnapshot::from(&sys))? + "\n").as_bytes())?;
thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
}
}

View file

@ -1,6 +1,6 @@
use std::time::Duration;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct SysinfoSnapshot {
uptime: u64,