Polish docs of clients and config

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron 2021-04-21 11:04:21 +12:00
parent 79d0d56193
commit 5b91ab9677
4 changed files with 121 additions and 90 deletions

View File

@ -3,22 +3,11 @@
use serde_derive::{Deserialize, Serialize};
use std::{path::PathBuf, time::Duration};
/// The configuration for either a `raw::Client` or a `transaction::Client`.
/// The configuration for either a [`RawClient`](crate::RawClient) or a
/// [`TransactionClient`](crate::TransactionClient).
///
/// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for PD
/// must be provided, **not** the TiKV nodes.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
///
/// By default, this client will use an insecure connection over instead of one protected by
/// Transport Layer Security (TLS). Your deployment may have chosen to rely on security measures
/// such as a private network, or a VPN layer to provide secure transmission.
///
/// To use a TLS secured connection, use the `with_security` function to set the required
/// parameters.
///
/// TiKV does not currently offer encrypted storage (or encryption-at-rest).
/// See also [`TransactionOptions`](crate::TransactionOptions) which provides more ways to configure
/// requests.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
@ -43,11 +32,16 @@ impl Default for Config {
}
impl Config {
/// Set the certificate authority, certificate, and key locations for the
/// [`Config`](Config).
/// Set the certificate authority, certificate, and key locations for clients.
///
/// By default, TiKV connections do not utilize transport layer security. Enable it by setting
/// these values.
/// By default, this client will use an insecure connection over instead of one protected by
/// Transport Layer Security (TLS). Your deployment may have chosen to rely on security measures
/// such as a private network, or a VPN layer to provide secure transmission.
///
/// To use a TLS secured connection, use the `with_security` function to set the required
/// parameters.
///
/// TiKV does not currently offer encrypted storage (or encryption-at-rest).
///
/// # Examples
/// ```rust
@ -66,16 +60,21 @@ impl Config {
self
}
/// Set the timeout for the [`Config`](Config).
/// Set the timeout for clients.
///
/// The timeout is used for all requests when using or connecting to a TiKV cluster (including
/// PD nodes). If the request does not complete within timeout, the request is cancelled and
/// an error returned to the user.
///
/// The default timeout is two seconds.
///
/// # Examples
/// ```rust
/// # use tikv_client::Config;
/// # use std::time::Duration;
/// let config = Config::default().timeout(Duration::from_secs(10));
/// let config = Config::default().with_timeout(Duration::from_secs(10));
/// ```
pub fn timeout(mut self, timeout: Duration) -> Self {
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}

View File

@ -62,24 +62,32 @@
//!
//! Raw mode:
//!
//! ```rust
//! use tikv_client::RawClient;
//!
//! ```rust,no_run
//! # use tikv_client::{RawClient, Result};
//! # use futures::prelude::*;
//! # fn main() -> Result<()> {
//! # futures::executor::block_on(async {
//! let client = RawClient::new(vec!["127.0.0.1:2379"]).await?;
//! client.put("key".to_owned(), "value".to_owned()).await?;
//! let value = client.get("key".to_owned()).await?;
//! # Ok(())
//! # })}
//! ```
//!
//! Transactional mode:
//!
//! ```rust
//! use tikv_client::TransactionClient;
//!
//! ```rust,no_run
//! # use tikv_client::{TransactionClient, Result};
//! # use futures::prelude::*;
//! # fn main() -> Result<()> {
//! # futures::executor::block_on(async {
//! let txn_client = TransactionClient::new(vec!["127.0.0.1:2379"]).await?;
//! let mut txn = txn_client.begin_optimistic().await?;
//! txn.put("key".to_owned(), "value".to_owned()).await?;
//! let value = txn.get("key".to_owned()).await?;
//! txn.commit().await?;
//! # Ok(())
//! # })}
//! ```
#[macro_use]

View File

@ -19,7 +19,8 @@ const MAX_RAW_KV_SCAN_LIMIT: u32 = 10240;
/// Raw requests don't need a wrapping transaction.
/// Each request is immediately processed once executed.
///
/// The returned results of raw requests are [`Future`](std::future::Future)s that must be awaited to execute.
/// The returned results of raw request methods are [`Future`](std::future::Future)s that must be
/// awaited to execute.
#[derive(Clone)]
pub struct Client {
rpc: Arc<PdRpcClient>,
@ -29,14 +30,16 @@ pub struct Client {
}
impl Client {
/// Create a raw [`Client`](Client).
/// Create a raw [`Client`] and connect to the TiKV cluster.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
/// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for
/// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint
/// (include all endpoints, if possible), this helps avoid having a single point of failure.
///
/// # Examples
///
/// ```rust,no_run
/// # use tikv_client::{Config, RawClient};
/// # use tikv_client::RawClient;
/// # use futures::prelude::*;
/// # futures::executor::block_on(async {
/// let client = RawClient::new(vec!["192.168.0.100"]).await.unwrap();
@ -46,17 +49,23 @@ impl Client {
Self::new_with_config(pd_endpoints, Config::default()).await
}
/// Create a raw [`Client`](Client).
/// Create a raw [`Client`] with a custom configuration, and connect to the TiKV cluster.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
/// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for
/// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint
/// (include all endpoints, if possible), this helps avoid having a single point of failure.
///
/// # Examples
///
/// ```rust,no_run
/// # use tikv_client::{Config, RawClient};
/// # use futures::prelude::*;
/// # use std::time::Duration;
/// # futures::executor::block_on(async {
/// let client = RawClient::new(vec!["192.168.0.100"]).await.unwrap();
/// let client = RawClient::new_with_config(
/// vec!["192.168.0.100"],
/// Config::default().with_timeout(Duration::from_secs(60)),
/// ).await.unwrap();
/// # });
/// ```
pub async fn new_with_config<S: Into<String>>(
@ -72,22 +81,27 @@ impl Client {
})
}
/// Set the column family of requests.
/// Create a new client which is a clone of `self`, but which uses an explicit column family for
/// all requests.
///
/// This function returns a new `Client`, requests created with it will have the
/// supplied column family constraint. The original `Client` can still be used.
/// This function returns a new `Client`; requests created with the new client will use the
/// supplied column family. The original `Client` can still be used (without the new
/// column family).
///
/// By default, raw client uses the `Default` column family.
///
/// For normal users of the raw API, you don't need to use other column families.
/// By default, raw clients use the `Default` column family.
///
/// # Examples
///
/// ```rust,no_run
/// # use tikv_client::{Config, RawClient, ColumnFamily};
/// # use futures::prelude::*;
/// # use std::convert::TryInto;
/// # futures::executor::block_on(async {
/// let client = RawClient::new(vec!["192.168.0.100"]).await.unwrap().with_cf(ColumnFamily::Write);
/// let client = RawClient::new(vec!["192.168.0.100"])
/// .await
/// .unwrap()
/// .with_cf(ColumnFamily::Write);
/// // Fetch a value at "foo" from the Write CF.
/// let get_request = client.get("foo".to_owned());
/// # });
/// ```
@ -411,11 +425,11 @@ impl Client {
///
/// Once resolved this request will result in a set of scanners over the given keys.
///
/// **Warning**: This method is experimental. The `each_limit` parameter does not work as expected.
/// It does not limit the number of results returned of each range,
/// **Warning**: This method is experimental.
/// The `each_limit` parameter does not limit the number of results returned of each range,
/// instead it limits the number of results in each region of each range.
/// As a result, you may get **more than** `each_limit` key-value pairs for each range.
/// But you should not miss any entries.
/// As a result, you may get **more than** `each_limit` key-value pairs for each range,
/// but you should not miss any entries.
///
/// # Examples
/// ```rust,no_run

View File

@ -13,36 +13,38 @@ use crate::{
use std::{mem, sync::Arc};
use tikv_client_proto::{kvrpcpb, pdpb::Timestamp};
const SCAN_LOCK_BATCH_SIZE: u32 = 1024; // FIXME: cargo-culted value
// FIXME: cargo-culted value
const SCAN_LOCK_BATCH_SIZE: u32 = 1024;
/// The TiKV transactional `Client` is used to interact with TiKV using transactional (MVCC) requests.
/// The TiKV transactional `Client` is used to interact with TiKV using transactional requests.
///
/// A [`Transaction`](crate::transaction::Transaction) provides a SQL-like interface.
/// It begins with a [`begin_optimistic`](Client::begin_optimistic) or [`begin_pessimistic`](Client::begin_pessimistic) request
/// and ends with a `rollback` or `commit` request.
/// If a `Transaction` is dropped before it's rolled back or committed, it is automatically rolled back.
/// Transactions support optimistic and pessimistic modes. For more details see the SIG-transaction
/// [docs](https://github.com/tikv/sig-transaction/tree/master/doc/tikv#optimistic-and-pessimistic-transactions).
///
/// Transaction supports optimistic and pessimistic modes, for mroe deatils, check our
/// [SIG-transaction](https://github.com/tikv/sig-transaction/tree/master/doc/tikv#optimistic-and-pessimistic-transactions).
/// Begin a [`Transaction`] by calling [`begin_optimistic`](Client::begin_optimistic) or
/// [`begin_pessimistic`](Client::begin_pessimistic). A transaction must be rolled back or committed.
///
/// Besides transaction, the client provides some utility methods:
/// - `gc`: execute a GC process which clear stale data. It is not stablized yet.
/// - `current_timestamp`: get the current `Timestamp`.
/// - `snapshot`: get the [`Snapshot`](crate::transaction::Snapshot) of the database at a certain timestamp.
/// Besides transactions, the client provides some further functionality:
/// - `gc`: trigger a GC process which clears stale data in the cluster.
/// - `current_timestamp`: get the current `Timestamp` from PD.
/// - `snapshot`: get a [`Snapshot`] of the database at a specified timestamp.
/// A `Snapshot` is a read-only transaction.
///
/// The returned results of transactional requests are [`Future`](std::future::Future)s that must be awaited to execute.
/// The returned results of transactional requests are [`Future`](std::future::Future)s that must be
/// awaited to execute.
pub struct Client {
pd: Arc<PdRpcClient>,
}
impl Client {
/// Creates a transactional [`Client`](Client).
/// Create a transactional [`Client`] and connect to the TiKV cluster.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
/// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for
/// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint
/// (include all endpoints, if possible), this helps avoid having a single point of failure.
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient};
/// use futures::prelude::*;
@ -54,17 +56,22 @@ impl Client {
Self::new_with_config(pd_endpoints, Config::default()).await
}
/// Creates a transactional [`Client`](Client).
/// Create a transactional [`Client`] with a custom configuration, and connect to the TiKV cluster.
///
/// It's important to **include more than one PD endpoint** (include all, if possible!)
/// This helps avoid having a *single point of failure*.
/// Because TiKV is managed by a [PD](https://github.com/pingcap/pd/) cluster, the endpoints for
/// PD must be provided, not the TiKV nodes. It's important to include more than one PD endpoint
/// (include all endpoints, if possible), this helps avoid having a single point of failure.
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient};
/// use futures::prelude::*;
/// # futures::executor::block_on(async {
/// let client = TransactionClient::new(vec!["192.168.0.100"]).await.unwrap();
/// let client = TransactionClient::new_with_config(
/// vec!["192.168.0.100"],
/// Config::default().with_timeout(Duration::from_secs(60)),
/// ).await.unwrap();
/// # });
/// ```
pub async fn new_with_config<S: Into<String>>(
@ -76,15 +83,16 @@ impl Client {
Ok(Client { pd })
}
/// Creates a new [`Transaction`](Transaction) in optimistic mode.
/// Creates a new optimistic [`Transaction`].
///
/// Using the transaction you can issue commands like [`get`](Transaction::get) or [`put`](Transaction::put).
/// Use the transaction to issue requests like [`get`](Transaction::get) or
/// [`put`](Transaction::put).
///
/// Write operations do not lock data in TiKV, thus commit request may fail due to write conflict.
///
/// For details, check our [SIG-transaction](https://github.com/tikv/sig-transaction/tree/master/doc/tikv#optimistic-and-pessimistic-transactions).
/// Write operations do not lock data in TiKV, thus the commit request may fail due to a write
/// conflict.
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient};
/// use futures::prelude::*;
@ -92,8 +100,7 @@ impl Client {
/// let client = TransactionClient::new(vec!["192.168.0.100"]).await.unwrap();
/// let mut transaction = client.begin_optimistic().await.unwrap();
/// // ... Issue some commands.
/// let commit = transaction.commit();
/// let result = commit.await.unwrap();
/// transaction.commit().await.unwrap();
/// # });
/// ```
pub async fn begin_optimistic(&self) -> Result<Transaction> {
@ -101,12 +108,13 @@ impl Client {
Ok(self.new_transaction(timestamp, TransactionOptions::new_optimistic()))
}
/// Creates a new [`Transaction`](Transaction) in pessimistic mode.
/// Creates a new pessimistic [`Transaction`].
///
/// Write operations will lock the data until commit, thus commit requests should not suffer from write conflict.
/// For details, check our [SIG-transaction](https://github.com/tikv/sig-transaction/tree/master/doc/tikv#optimistic-and-pessimistic-transactions).
/// Write operations will lock the data until committed, thus commit requests should not suffer
/// from write conflicts.
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient};
/// use futures::prelude::*;
@ -114,8 +122,7 @@ impl Client {
/// let client = TransactionClient::new(vec!["192.168.0.100"]).await.unwrap();
/// let mut transaction = client.begin_pessimistic().await.unwrap();
/// // ... Issue some commands.
/// let commit = transaction.commit();
/// let result = commit.await.unwrap();
/// transaction.commit().await.unwrap();
/// # });
/// ```
pub async fn begin_pessimistic(&self) -> Result<Transaction> {
@ -123,9 +130,10 @@ impl Client {
Ok(self.new_transaction(timestamp, TransactionOptions::new_pessimistic()))
}
/// Creates a new customized [`Transaction`](Transaction).
/// Create a new customized [`Transaction`].
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient, TransactionOptions};
/// use futures::prelude::*;
@ -136,8 +144,7 @@ impl Client {
/// .await
/// .unwrap();
/// // ... Issue some commands.
/// let commit = transaction.commit();
/// let result = commit.await.unwrap();
/// transaction.commit().await.unwrap();
/// # });
/// ```
pub async fn begin_with_options(&self, options: TransactionOptions) -> Result<Transaction> {
@ -145,14 +152,15 @@ impl Client {
Ok(self.new_transaction(timestamp, options))
}
/// Creates a new [`Snapshot`](Snapshot) at the given [`Timestamp`](Timestamp).
/// Create a new [`Snapshot`](Snapshot) at the given [`Timestamp`](Timestamp).
pub fn snapshot(&self, timestamp: Timestamp, options: TransactionOptions) -> Snapshot {
Snapshot::new(self.new_transaction(timestamp, options.read_only()))
}
/// Retrieves the current [`Timestamp`](Timestamp).
/// Retrieve the current [`Timestamp`].
///
/// # Examples
///
/// ```rust,no_run
/// use tikv_client::{Config, TransactionClient};
/// use futures::prelude::*;
@ -165,16 +173,18 @@ impl Client {
self.pd.clone().get_timestamp().await
}
/// Cleans MVCC records whose timestamp is lower than the given `timestamp` in TiKV.
/// Trigger garbage collection (GC) of the TiKV cluster.
///
/// GC deletes MVCC records whose timestamp is lower than the given `safepoint`.
///
/// For each key, the last mutation record (unless it's a deletion) before `safepoint` is retained.
///
/// It is done by:
/// 1. resolve all locks with ts <= `safepoint`
/// 2. update safepoint to PD
/// GC is performed by:
/// 1. resolving all locks with timestamp <= `safepoint`
/// 2. updating PD's known safepoint
///
/// This is a simplified version of [GC in TiDB](https://docs.pingcap.com/tidb/stable/garbage-collection-overview).
/// We omit the second step "delete ranges" which is an optimization for TiDB.
/// We skip the second step "delete ranges" which is an optimization for TiDB.
pub async fn gc(&self, safepoint: Timestamp) -> Result<bool> {
// scan all locks with ts <= safepoint
let mut locks: Vec<kvrpcpb::LockInfo> = vec![];