From 32fa940d1a6ac26f631ed9d91b6f0870d53d60ae Mon Sep 17 00:00:00 2001 From: Phoeniix Zhao Date: Sun, 9 Jun 2024 11:22:12 +0800 Subject: [PATCH] refactor: add a syntactic sugar method Signed-off-by: Phoeniix Zhao --- crates/xline-client/examples/lock.rs | 28 ++++++++++++++++-------- crates/xline-client/src/clients/lock.rs | 29 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/crates/xline-client/examples/lock.rs b/crates/xline-client/examples/lock.rs index 56c1b9685..40a674069 100644 --- a/crates/xline-client/examples/lock.rs +++ b/crates/xline-client/examples/lock.rs @@ -1,23 +1,33 @@ use anyhow::Result; -use xline_client::{clients::Xutex, Client, ClientOptions}; +use xline_client::{ + clients::Xutex, + types::kv::{Compare, CompareResult, PutRequest, TxnOp}, + Client, ClientOptions, +}; #[tokio::main] async fn main() -> Result<()> { // the name and address of all curp members let curp_members = ["10.0.0.1:2379", "10.0.0.2:2379", "10.0.0.3:2379"]; - let client = Client::connect(curp_members, ClientOptions::default()) - .await? - .lock_client(); + let client = Client::connect(curp_members, ClientOptions::default()).await?; - let mut xutex = Xutex::new(client, "lock-test", None, None).await?; + let lock_client = client.lock_client(); + let kv_client = client.kv_client(); + + let mut xutex = Xutex::new(lock_client, "lock-test", None, None).await?; // when the `xutex_guard` drop, the lock will be unlocked. let xutex_guard = xutex.lock().await?; - println!( - "lock key: {:?}", - String::from_utf8_lossy(xutex_guard.key().as_bytes()) - ); + let txn_req = xutex_guard + .txn_check_locked_key() + .when([Compare::value("key2", CompareResult::Equal, "value2")]) + .and_then([TxnOp::put( + PutRequest::new("key2", "value3").with_prev_kv(true), + )]) + .or_else(&[]); + + let _resp = kv_client.txn(txn_req).await?; Ok(()) } diff --git a/crates/xline-client/src/clients/lock.rs b/crates/xline-client/src/clients/lock.rs index 7fc060149..efef2ef87 100644 --- a/crates/xline-client/src/clients/lock.rs +++ b/crates/xline-client/src/clients/lock.rs @@ -17,6 +17,7 @@ use crate::{ error::{Result, XlineClientError}, lease_gen::LeaseIdGenerator, types::{ + kv::TxnRequest as KvTxnRequest, lease::{LeaseGrantRequest, LeaseKeepAliveRequest}, watch::WatchRequest, }, @@ -82,6 +83,24 @@ impl XutexGuard { pub fn key(&self) -> &str { self.key.as_str() } + + /// Return a `TxnRequest` which will perform the success ops when the locked key is exist. + /// This method is syntactic sugar + #[inline] + #[must_use] + pub fn txn_check_locked_key(&self) -> KvTxnRequest { + let mut txn_request = KvTxnRequest::new(); + #[allow(clippy::as_conversions)] + let cmp = Compare { + result: CompareResult::Greater as i32, + target: CompareTarget::Create as i32, + key: self.key().into(), + range_end: Vec::new(), + target_union: Some(TargetUnion::CreateRevision(0)), + }; + txn_request.inner.compare.push(cmp); + txn_request + } } #[async_trait] @@ -263,6 +282,16 @@ impl Xutex { /// ``` #[inline] pub async fn lock(&mut self) -> Result> { + if self + .session + .keep_alive + .as_ref() + .is_some_and(JoinHandle::is_finished) + { + return Err(XlineClientError::LeaseError(String::from( + "Lock renew task exists unexpectedly", + ))); + } let resp = self.try_acquire().await?; #[allow(clippy::indexing_slicing)] if let Some(Response::ResponseRange(ref lock_owner)) = resp.responses[1].response {