mirror of https://github.com/tikv/client-rust.git
Add some docs and move try_one_pc out of options ctor
Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
parent
1c7e843b54
commit
f90a82fe35
|
@ -5,6 +5,9 @@
|
|||
use rand::{thread_rng, Rng};
|
||||
use std::time::Duration;
|
||||
|
||||
/// When a request is retried, we can backoff for some time to avoid saturating the network.
|
||||
///
|
||||
/// `Backoff` is an object which determines how long to wait for.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Backoff {
|
||||
kind: BackoffKind,
|
||||
|
@ -64,10 +67,12 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
/// True if we should not backoff at all (usually indicates that we should not retry a request).
|
||||
pub fn is_none(&self) -> bool {
|
||||
self.kind == BackoffKind::None
|
||||
}
|
||||
|
||||
/// Don't wait. Usually indicates that we should not retry a request.
|
||||
pub const fn no_backoff() -> Backoff {
|
||||
Backoff {
|
||||
kind: BackoffKind::None,
|
||||
|
@ -79,6 +84,11 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
// Exponential backoff means that the retry delay should multiply a constant
|
||||
// after each attempt, up to a maximum value. After each attempt, the new retry
|
||||
// delay should be:
|
||||
//
|
||||
// new_delay = min(max_delay, base_delay * 2 ** attempts)
|
||||
pub const fn no_jitter_backoff(
|
||||
base_delay_ms: u64,
|
||||
max_delay_ms: u64,
|
||||
|
@ -94,6 +104,11 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
// Adds Jitter to the basic exponential backoff. Returns a random value between
|
||||
// zero and the calculated exponential backoff:
|
||||
//
|
||||
// temp = min(max_delay, base_delay * 2 ** attempts)
|
||||
// new_delay = random_between(0, temp)
|
||||
pub fn full_jitter_backoff(
|
||||
base_delay_ms: u64,
|
||||
max_delay_ms: u64,
|
||||
|
@ -114,6 +129,11 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
// Equal Jitter limits the random value should be equal or greater than half of
|
||||
// the calculated exponential backoff:
|
||||
//
|
||||
// temp = min(max_delay, base_delay * 2 ** attempts)
|
||||
// new_delay = random_between(temp / 2, temp)
|
||||
pub fn equal_jitter_backoff(
|
||||
base_delay_ms: u64,
|
||||
max_delay_ms: u64,
|
||||
|
@ -134,6 +154,11 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
// Decorrelated Jitter is always calculated with the previous backoff
|
||||
// (the initial value is base_delay):
|
||||
//
|
||||
// temp = random_between(base_delay, previous_delay * 3)
|
||||
// new_delay = min(max_delay, temp)
|
||||
pub fn decorrelated_jitter_backoff(
|
||||
base_delay_ms: u64,
|
||||
max_delay_ms: u64,
|
||||
|
@ -152,33 +177,13 @@ impl Backoff {
|
|||
}
|
||||
}
|
||||
|
||||
/// The pattern for computing backoff times.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum BackoffKind {
|
||||
// NoBackoff means that we don't want any retry here.
|
||||
None,
|
||||
// Exponential backoff means that the retry delay should multiply a constant
|
||||
// after each attempt, up to a maximum value. After each attempt, the new retry
|
||||
// delay should be:
|
||||
//
|
||||
// new_delay = min(max_delay, base_delay * 2 ** attempts)
|
||||
NoJitter,
|
||||
// Adds Jitter to the basic exponential backoff. Returns a random value between
|
||||
// zero and the calculated exponential backoff:
|
||||
//
|
||||
// temp = min(max_delay, base_delay * 2 ** attempts)
|
||||
// new_delay = random_between(0, temp)
|
||||
FullJitter,
|
||||
// Equal Jitter limits the random value should be equal or greater than half of
|
||||
// the calculated exponential backoff:
|
||||
//
|
||||
// temp = min(max_delay, base_delay * 2 ** attempts)
|
||||
// new_delay = random_between(temp / 2, temp)
|
||||
EqualJitter,
|
||||
// Decorrelated Jitter is always calculated with the previous backoff
|
||||
// (the initial value is base_delay):
|
||||
//
|
||||
// temp = random_between(base_delay, previous_delay * 3)
|
||||
// new_delay = min(max_delay, temp)
|
||||
DecorrelatedJitter,
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,9 @@ pub use crate::raw::{Client as RawClient, ColumnFamily};
|
|||
#[doc(inline)]
|
||||
pub use crate::timestamp::{Timestamp, TimestampExt};
|
||||
#[doc(inline)]
|
||||
pub use crate::transaction::{Client as TransactionClient, Snapshot, Transaction};
|
||||
pub use crate::transaction::{
|
||||
Client as TransactionClient, Snapshot, Transaction, TransactionOptions,
|
||||
};
|
||||
#[doc(inline)]
|
||||
pub use config::Config;
|
||||
#[doc(inline)]
|
||||
|
|
|
@ -165,7 +165,9 @@ pub trait KvRequest: Request + Clone + Sync + Send + 'static + Sized {
|
|||
|
||||
#[derive(Clone, Debug, new, Eq, PartialEq)]
|
||||
pub struct RetryOptions {
|
||||
/// How to retry when there is a region error and we need to resolve regions with PD.
|
||||
pub region_backoff: Backoff,
|
||||
/// How to retry when a key is locked.
|
||||
pub lock_backoff: Backoff,
|
||||
}
|
||||
|
||||
|
|
|
@ -107,10 +107,11 @@ impl Client {
|
|||
/// ```
|
||||
pub async fn begin_optimistic(&self) -> Result<Transaction> {
|
||||
let timestamp = self.current_timestamp().await?;
|
||||
Ok(self.new_transaction(
|
||||
timestamp,
|
||||
TransactionOptions::new_optimistic(self.config.try_one_pc),
|
||||
))
|
||||
let mut options = TransactionOptions::new_optimistic();
|
||||
if self.config.try_one_pc {
|
||||
options = options.try_one_pc();
|
||||
}
|
||||
Ok(self.new_transaction(timestamp, options))
|
||||
}
|
||||
|
||||
/// Creates a new [`Transaction`](Transaction) in pessimistic mode.
|
||||
|
@ -132,12 +133,30 @@ impl Client {
|
|||
/// ```
|
||||
pub async fn begin_pessimistic(&self) -> Result<Transaction> {
|
||||
let timestamp = self.current_timestamp().await?;
|
||||
Ok(self.new_transaction(
|
||||
timestamp,
|
||||
TransactionOptions::new_pessimistic(self.config.try_one_pc),
|
||||
))
|
||||
let mut options = TransactionOptions::new_pessimistic();
|
||||
if self.config.try_one_pc {
|
||||
options = options.try_one_pc();
|
||||
}
|
||||
Ok(self.new_transaction(timestamp, options))
|
||||
}
|
||||
|
||||
/// Creates a new customized [`Transaction`](Transaction).
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust,no_run
|
||||
/// use tikv_client::{Config, TransactionClient, TransactionOptions};
|
||||
/// use futures::prelude::*;
|
||||
/// # futures::executor::block_on(async {
|
||||
/// let client = TransactionClient::new(vec!["192.168.0.100"]).await.unwrap();
|
||||
/// let mut transaction = client
|
||||
/// .begin_with_options(TransactionOptions::default().async_commit())
|
||||
/// .await
|
||||
/// .unwrap();
|
||||
/// // ... Issue some commands.
|
||||
/// let commit = transaction.commit();
|
||||
/// let result = commit.await.unwrap();
|
||||
/// # });
|
||||
/// ```
|
||||
pub async fn begin_with_options(&self, options: TransactionOptions) -> Result<Transaction> {
|
||||
let timestamp = self.current_timestamp().await?;
|
||||
Ok(self.new_transaction(timestamp, options))
|
||||
|
|
|
@ -11,8 +11,7 @@
|
|||
pub use client::Client;
|
||||
pub(crate) use lock::{resolve_locks, HasLocks};
|
||||
pub use snapshot::Snapshot;
|
||||
pub use transaction::Transaction;
|
||||
use transaction::TransactionOptions;
|
||||
pub use transaction::{Transaction, TransactionOptions};
|
||||
|
||||
mod buffer;
|
||||
mod client;
|
||||
|
|
|
@ -526,6 +526,7 @@ impl Drop for Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
/// Optimistic or pessimistic transaction.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum TransactionKind {
|
||||
Optimistic,
|
||||
|
@ -533,62 +534,81 @@ pub enum TransactionKind {
|
|||
Pessimistic(u64),
|
||||
}
|
||||
|
||||
/// Options for configuring a transaction.
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub struct TransactionOptions {
|
||||
/// Optimistic or pessimistic (default) transaction.
|
||||
kind: TransactionKind,
|
||||
/// Try using 1pc rather than 2pc (default is to always use 2pc).
|
||||
try_one_pc: bool,
|
||||
/// Try to use async commit (default is not to).
|
||||
async_commit: bool,
|
||||
/// Is the transaction read only? (Default is no).
|
||||
read_only: bool,
|
||||
/// How to retry in the event of certain errors.
|
||||
retry_options: RetryOptions,
|
||||
}
|
||||
|
||||
impl Default for TransactionOptions {
|
||||
fn default() -> TransactionOptions {
|
||||
Self::new_pessimistic(false)
|
||||
Self::new_pessimistic()
|
||||
}
|
||||
}
|
||||
|
||||
impl TransactionOptions {
|
||||
pub fn new_optimistic(try_one_pc: bool) -> TransactionOptions {
|
||||
/// Default options for an optimistic transaction.
|
||||
pub fn new_optimistic() -> TransactionOptions {
|
||||
TransactionOptions {
|
||||
kind: TransactionKind::Optimistic,
|
||||
try_one_pc,
|
||||
try_one_pc: false,
|
||||
async_commit: false,
|
||||
read_only: false,
|
||||
retry_options: RetryOptions::default_optimistic(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_pessimistic(try_one_pc: bool) -> TransactionOptions {
|
||||
/// Default options for a pessimistic transaction.
|
||||
pub fn new_pessimistic() -> TransactionOptions {
|
||||
TransactionOptions {
|
||||
kind: TransactionKind::Pessimistic(0),
|
||||
try_one_pc,
|
||||
try_one_pc: false,
|
||||
async_commit: false,
|
||||
read_only: false,
|
||||
retry_options: RetryOptions::default_pessimistic(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to use async commit.
|
||||
pub fn async_commit(mut self) -> TransactionOptions {
|
||||
self.async_commit = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Try to use 1pc.
|
||||
pub fn try_one_pc(mut self) -> TransactionOptions {
|
||||
self.try_one_pc = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Make the transaction read only.
|
||||
pub fn read_only(mut self) -> TransactionOptions {
|
||||
self.read_only = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Don't automatically resolve locks and retry if keys are locked.
|
||||
pub fn no_resolve_locks(mut self) -> TransactionOptions {
|
||||
self.retry_options.lock_backoff = Backoff::no_backoff();
|
||||
self
|
||||
}
|
||||
|
||||
/// Don't automatically resolve regions with PD if we have outdated region information.
|
||||
pub fn no_resolve_regions(mut self) -> TransactionOptions {
|
||||
self.retry_options.region_backoff = Backoff::no_backoff();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set RetryOptions.
|
||||
pub fn retry_options(mut self, options: RetryOptions) -> TransactionOptions {
|
||||
self.retry_options = options;
|
||||
self
|
||||
|
|
Loading…
Reference in New Issue