// Author: D.S. Ljungmark , Modio AB // SPDX-License-Identifier: AGPL-3.0-or-later use std::error::Error; use zbus::Connection; use zbus::Guid; use fsipc::legacy::fsipcProxy; use fsipc::unixtime; async fn printlast(ipc: &fsipcProxy<'_>, key: &str) { match ipc.retrieve(key).await { Ok(data) => println!("{}= {} @{}", data.key, data.value, data.timestamp), Err(e) => println!("Err retrieving: {key} : {e}"), } } async fn get_points(ipc: &fsipcProxy<'_>) -> zbus::Result<()> { println!("Retrieving all data points"); let res = ipc.retrieve_all().await?; for measure in &res { println!("Fetching {measure}"); match ipc.retrieve(&measure.key).await { Ok(data) => { println!("Got: {data}"); assert_eq!(data.key, measure.key); } Err(e) => { println!("Retrieve error: {e:?}"); return Err(e); } } } Ok(()) } async fn valid_invalid(ipc: &fsipcProxy<'_>) -> zbus::Result<()> { let valid_key = "modio.software.development"; match ipc.valid_key(valid_key).await { Ok(true) => println!("{valid_key} is valid"), Ok(false) => { println!("{valid_key} is invalid"); panic!("Valid key is invalid"); } Err(e) => { println!("{valid_key} gives error: {e}"); return Err(e); } } let invalid_key = "modio..invalid"; match ipc.valid_key(invalid_key).await { Ok(true) => { println!("{invalid_key} is valid"); panic!("Valid when it should not be"); } Ok(false) => println!("{invalid_key} is invalid"), Err(e) => { println!("{invalid_key} gives error: {e}"); return Err(e); } } Ok(()) } async fn transaction_test(ipc: &fsipcProxy<'_>) -> zbus::Result<()> { let key = "test.test.one"; let first = "first"; let mut our_value = "first"; let second = "second"; printlast(ipc, key).await; match ipc.store(key, our_value).await { Ok(_) => println!("stored {key} = {our_value}"), Err(e) => println!("Error: {e}"), } printlast(ipc, key).await; let when = unixtime(); match ipc.store_with_time(key, our_value, when).await { Ok(_) => println!("Store with time: {key}={our_value} @{when}"), Err(e) => println!("Store with time failed: {e}"), } printlast(ipc, key).await; let guid1 = Guid::generate(); // Transactions "id" are either a UUID or an timestamp-as-string match ipc .transaction_add(key, first, second, guid1.as_str()) .await { Ok(_) => println!("Adding Transaction: {key} {first}=>{second}"), Err(e) => println!("Error: {e}"), } let guid2 = Guid::generate(); match ipc .transaction_add(key, first, second, guid2.as_str()) .await { Ok(_) => println!("Adding Transaction: {key} {first}=>{second}"), Err(e) => println!("Error: {e}"), } let guid3 = Guid::generate(); match ipc .transaction_add(key, first, second, guid3.as_str()) .await { Ok(_) => println!("Adding Transaction: {key} {first}=>{second}"), Err(e) => println!("Error: {e}"), } println!("Fetching transaction for: {key}"); match ipc.transaction_get(key).await { Ok(transactions) => { // The "id" here is an internal ID in the current logger instance, not the same as // our GUID ID we entered above. for trn in &transactions { if our_value == trn.expected { println!( "{}({}): {} == {}, changing to {}, ok", trn.key, trn.t_id, trn.expected, our_value, trn.target ); our_value = &trn.target; match ipc.transaction_pass(trn.t_id).await { Ok(_) => println!("marked passed"), Err(e) => println!("error: {e}"), } } else { println!( "{}({}): {} != {}, failing", trn.key, trn.t_id, our_value, trn.expected ); match ipc.transaction_fail(trn.t_id).await { Ok(_) => println!("marked failed"), Err(e) => println!("error: {e}"), } } ipc.store(key, our_value).await?; } } Err(e) => println!("Error in transaction_get: {e}"), } printlast(ipc, key).await; Ok(()) } async fn double_transactions(ipc: &fsipcProxy<'_>) -> zbus::Result<()> { println!("Attempting double transactions"); { let key = "test.test.one"; let first = "first"; let second = "second"; let guid4 = Guid::generate(); match ipc .transaction_add(key, first, second, guid4.as_str()) .await { Ok(_) => println!("Added transaction: {key}, {first}=>{second}"), Err(e) => println!("Error: {e}"), } match ipc.transaction_get(key).await { Err(e) => println!("Error in transaction_get: {e}"), Ok(transactions) => { if let Some(val) = transactions.first() { println!("Received transaction: {}, t_id={}", val, val.t_id); println!("About to pass t_id={}", val.t_id); match ipc.transaction_pass(val.t_id).await { Ok(_) => println!("pass1 of t_id={} success", val.t_id), Err(e) => println!("pass1 of t_id={} fail: {}", val.t_id, e), } println!("About to pass t_id={}", val.t_id); match ipc.transaction_pass(val.t_id).await { Ok(_) => println!("pass2 of t_id={} success when it should not!", val.t_id), Err(e) => println!("pass2 of t_id={} fail: as expected! {}", val.t_id, e), } } } }; } Ok(()) } #[async_std::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt().init(); let connection = Connection::session().await?; let ipc = fsipcProxy::new(&connection).await?; printlast(&ipc, "hello.world").await; get_points(&ipc).await?; valid_invalid(&ipc).await?; transaction_test(&ipc).await?; double_transactions(&ipc).await?; Ok(()) }