mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
refactor: simplify lact-client by removing ResponseBuffer
This commit is contained in:
@@ -19,8 +19,8 @@ pub fn run(args: CliArgs) -> Result<()> {
|
||||
}
|
||||
|
||||
async fn list_gpus(_: &CliArgs, client: &DaemonClient) -> Result<()> {
|
||||
let buffer = client.list_devices().await?;
|
||||
for entry in buffer.inner()? {
|
||||
let entries = client.list_devices().await?;
|
||||
for entry in entries {
|
||||
let id = entry.id;
|
||||
if let Some(name) = entry.name {
|
||||
println!("{id} ({name})");
|
||||
@@ -33,8 +33,7 @@ async fn list_gpus(_: &CliArgs, client: &DaemonClient) -> Result<()> {
|
||||
|
||||
async fn info(args: &CliArgs, client: &DaemonClient) -> Result<()> {
|
||||
for id in extract_gpu_ids(args, client).await {
|
||||
let info_buffer = client.get_device_info(&id).await?;
|
||||
let info = info_buffer.inner()?;
|
||||
let info = client.get_device_info(&id).await?;
|
||||
let pci_info = info.pci_info.context("GPU reports no pci info")?;
|
||||
|
||||
if let Some(ref vendor) = pci_info.device_pci_info.vendor {
|
||||
@@ -56,10 +55,8 @@ async fn extract_gpu_ids(args: &CliArgs, client: &DaemonClient) -> Vec<String> {
|
||||
match args.gpu_id {
|
||||
Some(ref id) => vec![id.clone()],
|
||||
None => {
|
||||
let buffer = client.list_devices().await.expect("Could not list GPUs");
|
||||
buffer
|
||||
.inner()
|
||||
.expect("Could not deserialize GPUs response")
|
||||
let entries = client.list_devices().await.expect("Could not list GPUs");
|
||||
entries
|
||||
.into_iter()
|
||||
.map(|entry| entry.id.to_owned())
|
||||
.collect()
|
||||
@@ -68,8 +65,7 @@ async fn extract_gpu_ids(args: &CliArgs, client: &DaemonClient) -> Vec<String> {
|
||||
}
|
||||
|
||||
async fn snapshot(client: &DaemonClient) -> Result<()> {
|
||||
let buffer = client.generate_debug_snapshot().await?;
|
||||
let path = buffer.inner()?;
|
||||
let path = client.generate_debug_snapshot().await?;
|
||||
println!("Generated debug snapshot in {path}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@ use schema::{
|
||||
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanOptions, PowerStates, ProfilesInfo,
|
||||
Request, Response, SystemInfo,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::{
|
||||
future::Future, marker::PhantomData, os::unix::net::UnixStream, path::PathBuf, pin::Pin,
|
||||
rc::Rc, time::Duration,
|
||||
future::Future, os::unix::net::UnixStream, path::PathBuf, pin::Pin, rc::Rc, time::Duration,
|
||||
};
|
||||
use tokio::{
|
||||
net::ToSocketAddrs,
|
||||
@@ -73,19 +72,24 @@ impl DaemonClient {
|
||||
self.status_tx.subscribe()
|
||||
}
|
||||
|
||||
fn make_request<'a, 'r, T: Deserialize<'r>>(
|
||||
fn make_request<'a, T: DeserializeOwned>(
|
||||
&'a self,
|
||||
request: Request<'a>,
|
||||
) -> Pin<Box<dyn Future<Output = anyhow::Result<ResponseBuffer<T>>> + 'a>> {
|
||||
) -> Pin<Box<dyn Future<Output = anyhow::Result<T>> + 'a>> {
|
||||
Box::pin(async {
|
||||
let mut stream = self.stream.lock().await;
|
||||
|
||||
let request_payload = serde_json::to_string(&request)?;
|
||||
match stream.request(&request_payload).await {
|
||||
Ok(response_payload) => Ok(ResponseBuffer {
|
||||
buf: response_payload,
|
||||
_phantom: PhantomData,
|
||||
}),
|
||||
Ok(response_payload) => {
|
||||
let response: Response<T> = serde_json::from_str(&response_payload)
|
||||
.context("Could not deserialize response from daemon")?;
|
||||
match response {
|
||||
Response::Ok(data) => Ok(data),
|
||||
Response::Error(err) => Err(anyhow::Error::new(err)
|
||||
.context("Got error from daemon, end of client boundary")),
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Could not make request: {err}, reconnecting to socket");
|
||||
let _ = self.status_tx.send(ConnectionStatusMsg::Disconnected);
|
||||
@@ -113,20 +117,16 @@ impl DaemonClient {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn list_devices(&self) -> anyhow::Result<ResponseBuffer<Vec<DeviceListEntry>>> {
|
||||
pub async fn list_devices(&self) -> anyhow::Result<Vec<DeviceListEntry>> {
|
||||
self.make_request(Request::ListDevices).await
|
||||
}
|
||||
|
||||
pub async fn set_fan_control(&self, cmd: FanOptions<'_>) -> anyhow::Result<u64> {
|
||||
self.make_request(Request::SetFanControl(cmd))
|
||||
.await?
|
||||
.inner()
|
||||
self.make_request(Request::SetFanControl(cmd)).await
|
||||
}
|
||||
|
||||
pub async fn set_power_cap(&self, id: &str, cap: Option<f64>) -> anyhow::Result<u64> {
|
||||
self.make_request(Request::SetPowerCap { id, cap })
|
||||
.await?
|
||||
.inner()
|
||||
self.make_request(Request::SetPowerCap { id, cap }).await
|
||||
}
|
||||
|
||||
request_plain!(get_system_info, SystemInfo, SystemInfo);
|
||||
@@ -148,38 +148,31 @@ impl DaemonClient {
|
||||
|
||||
pub async fn list_profiles(&self, include_state: bool) -> anyhow::Result<ProfilesInfo> {
|
||||
self.make_request(Request::ListProfiles { include_state })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_profile(&self, name: Option<String>, auto_switch: bool) -> anyhow::Result<()> {
|
||||
self.make_request(Request::SetProfile { name, auto_switch })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn create_profile(&self, name: String, base: ProfileBase) -> anyhow::Result<()> {
|
||||
self.make_request(Request::CreateProfile { name, base })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_profile(&self, name: String) -> anyhow::Result<()> {
|
||||
self.make_request(Request::DeleteProfile { name })
|
||||
.await?
|
||||
.inner()
|
||||
self.make_request(Request::DeleteProfile { name }).await
|
||||
}
|
||||
|
||||
pub async fn move_profile(&self, name: String, new_position: usize) -> anyhow::Result<()> {
|
||||
self.make_request(Request::MoveProfile { name, new_position })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn evaluate_profile_rule(&self, rule: ProfileRule) -> anyhow::Result<bool> {
|
||||
self.make_request(Request::EvaluateProfileRule { rule })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_profile_rule(
|
||||
@@ -188,8 +181,7 @@ impl DaemonClient {
|
||||
rule: Option<ProfileRule>,
|
||||
) -> anyhow::Result<()> {
|
||||
self.make_request(Request::SetProfileRule { name, rule })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_performance_level(
|
||||
@@ -201,8 +193,7 @@ impl DaemonClient {
|
||||
id,
|
||||
performance_level,
|
||||
})
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_clocks_value(
|
||||
@@ -211,8 +202,7 @@ impl DaemonClient {
|
||||
command: SetClocksCommand,
|
||||
) -> anyhow::Result<u64> {
|
||||
self.make_request(Request::SetClocksValue { id, command })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn batch_set_clocks_value(
|
||||
@@ -221,8 +211,7 @@ impl DaemonClient {
|
||||
commands: Vec<SetClocksCommand>,
|
||||
) -> anyhow::Result<u64> {
|
||||
self.make_request(Request::BatchSetClocksValue { id, commands })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_enabled_power_states(
|
||||
@@ -232,8 +221,7 @@ impl DaemonClient {
|
||||
states: Vec<u8>,
|
||||
) -> anyhow::Result<u64> {
|
||||
self.make_request(Request::SetEnabledPowerStates { id, kind, states })
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn set_power_profile_mode(
|
||||
@@ -247,14 +235,12 @@ impl DaemonClient {
|
||||
index,
|
||||
custom_heuristics,
|
||||
})
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn confirm_pending_config(&self, command: ConfirmCommand) -> anyhow::Result<()> {
|
||||
self.make_request(Request::ConfirmPendingConfig(command))
|
||||
.await?
|
||||
.inner()
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,25 +261,6 @@ fn get_socket_path() -> Option<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResponseBuffer<T> {
|
||||
buf: String,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Deserialize<'a>> ResponseBuffer<T> {
|
||||
pub fn inner(&'a self) -> anyhow::Result<T> {
|
||||
let response: Response<T> = serde_json::from_str(&self.buf)
|
||||
.context("Could not deserialize response from daemon")?;
|
||||
match response {
|
||||
Response::Ok(data) => Ok(data),
|
||||
Response::Error(err) => {
|
||||
Err(anyhow::Error::new(err)
|
||||
.context("Got error from daemon, end of client boundary"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ConnectionStatusMsg {
|
||||
Disconnected,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
macro_rules! request_with_id {
|
||||
($name:ident, $variant:ident, $response:ty) => {
|
||||
pub async fn $name(&self, id: &str) -> anyhow::Result<ResponseBuffer<$response>> {
|
||||
pub async fn $name(&self, id: &str) -> anyhow::Result<$response> {
|
||||
self.make_request(Request::$variant { id }).await
|
||||
}
|
||||
};
|
||||
@@ -8,7 +8,7 @@ macro_rules! request_with_id {
|
||||
|
||||
macro_rules! request_plain {
|
||||
($name:ident, $variant:ident, $response:ty) => {
|
||||
pub async fn $name(&self) -> anyhow::Result<ResponseBuffer<$response>> {
|
||||
pub async fn $name(&self) -> anyhow::Result<$response> {
|
||||
self.make_request(Request::$variant).await
|
||||
}
|
||||
};
|
||||
|
||||
@@ -161,17 +161,15 @@ impl AsyncComponent for AppModel {
|
||||
|
||||
register_actions(&sender);
|
||||
|
||||
let system_info_buf = daemon_client
|
||||
let system_info = daemon_client
|
||||
.get_system_info()
|
||||
.await
|
||||
.expect("Could not fetch system info");
|
||||
let system_info = system_info_buf.inner().expect("Invalid system info buffer");
|
||||
|
||||
let devices_buf = daemon_client
|
||||
let devices = daemon_client
|
||||
.list_devices()
|
||||
.await
|
||||
.expect("Could not list devices");
|
||||
let devices = devices_buf.inner().expect("Could not access devices");
|
||||
|
||||
if system_info.version != GUI_VERSION || system_info.commit.as_deref() != Some(GIT_COMMIT) {
|
||||
let err = anyhow!("Version mismatch between GUI and daemon ({GUI_VERSION}-{GIT_COMMIT} vs {}-{})! If you have updated LACT, you need to restart the service with `sudo systemctl restart lactd`.", system_info.version, system_info.commit.as_deref().unwrap_or_default());
|
||||
@@ -449,7 +447,7 @@ impl AppModel {
|
||||
.get_device_info(&gpu_id)
|
||||
.await
|
||||
.context("Could not fetch info")?;
|
||||
let info = Arc::new(info_buf.inner()?);
|
||||
let info = Arc::new(info_buf);
|
||||
|
||||
// Plain `nvidia` means that the nvidia driver is loaded, but it does not contain a version fetched from NVML
|
||||
if info.driver == "nvidia" {
|
||||
@@ -492,8 +490,7 @@ impl AppModel {
|
||||
.daemon_client
|
||||
.get_device_stats(&gpu_id)
|
||||
.await
|
||||
.context("Could not fetch stats")?
|
||||
.inner()?;
|
||||
.context("Could not fetch stats")?;
|
||||
let stats = Arc::new(stats);
|
||||
|
||||
self.oc_page.set_stats(&stats, true);
|
||||
@@ -502,13 +499,7 @@ impl AppModel {
|
||||
self.info_page.emit(PageUpdate::Stats(stats));
|
||||
|
||||
let maybe_clocks_table = match self.daemon_client.get_device_clocks_info(&gpu_id).await {
|
||||
Ok(clocks_buf) => match clocks_buf.inner() {
|
||||
Ok(info) => info.table,
|
||||
Err(err) => {
|
||||
debug!("could not extract clocks info: {err:?}");
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(info) => info.table,
|
||||
Err(err) => {
|
||||
debug!("could not fetch clocks info: {err:?}");
|
||||
None
|
||||
@@ -521,13 +512,7 @@ impl AppModel {
|
||||
.get_device_power_profile_modes(&gpu_id)
|
||||
.await
|
||||
{
|
||||
Ok(buf) => match buf.inner() {
|
||||
Ok(table) => Some(table),
|
||||
Err(err) => {
|
||||
debug!("Could not extract profile modes table: {err:?}");
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(buf) => Some(buf),
|
||||
Err(err) => {
|
||||
debug!("Could not get profile modes table: {err:?}");
|
||||
None
|
||||
@@ -537,12 +522,7 @@ impl AppModel {
|
||||
.performance_frame
|
||||
.set_power_profile_modes(maybe_modes_table);
|
||||
|
||||
match self
|
||||
.daemon_client
|
||||
.get_power_states(&gpu_id)
|
||||
.await
|
||||
.and_then(|states| states.inner())
|
||||
{
|
||||
match self.daemon_client.get_power_states(&gpu_id).await {
|
||||
Ok(power_states) => {
|
||||
self.oc_page
|
||||
.power_states_frame
|
||||
@@ -773,12 +753,7 @@ impl AppModel {
|
||||
}
|
||||
|
||||
async fn dump_vbios(&self, gpu_id: &str, root: >k::ApplicationWindow) {
|
||||
match self
|
||||
.daemon_client
|
||||
.dump_vbios(gpu_id)
|
||||
.await
|
||||
.and_then(|response| response.inner())
|
||||
{
|
||||
match self.daemon_client.dump_vbios(gpu_id).await {
|
||||
Ok(vbios_data) => {
|
||||
let file_chooser = FileChooserDialog::new(
|
||||
Some("Save VBIOS file"),
|
||||
@@ -826,12 +801,7 @@ impl AppModel {
|
||||
}
|
||||
|
||||
async fn generate_debug_snapshot(&self, root: >k::ApplicationWindow) {
|
||||
match self
|
||||
.daemon_client
|
||||
.generate_debug_snapshot()
|
||||
.await
|
||||
.and_then(|response| response.inner())
|
||||
{
|
||||
match self.daemon_client.generate_debug_snapshot().await {
|
||||
Ok(path) => {
|
||||
let path_label = gtk::Label::builder()
|
||||
.use_markup(true)
|
||||
@@ -968,11 +938,7 @@ fn start_stats_update_loop(
|
||||
loop {
|
||||
tokio::time::sleep(duration).await;
|
||||
|
||||
match daemon_client
|
||||
.get_device_stats(&gpu_id)
|
||||
.await
|
||||
.and_then(|buffer| buffer.inner())
|
||||
{
|
||||
match daemon_client.get_device_stats(&gpu_id).await {
|
||||
Ok(stats) => {
|
||||
sender.input(AppMsg::Stats(Arc::new(stats)));
|
||||
}
|
||||
@@ -1043,15 +1009,9 @@ async fn toggle_overdrive(daemon_client: &DaemonClient, enable: bool, root: Appl
|
||||
dialog.show();
|
||||
|
||||
let result = if enable {
|
||||
daemon_client
|
||||
.enable_overdrive()
|
||||
.await
|
||||
.and_then(|buffer| buffer.inner())
|
||||
daemon_client.enable_overdrive().await
|
||||
} else {
|
||||
daemon_client
|
||||
.disable_overdrive()
|
||||
.await
|
||||
.and_then(|buffer| buffer.inner())
|
||||
daemon_client.disable_overdrive().await
|
||||
};
|
||||
|
||||
dialog.hide();
|
||||
|
||||
Reference in New Issue
Block a user