Struct Client

Source
pub struct Client<T: Connector = TcpConnector> { /* private fields */ }
Expand description

A Redis client.

A Client can use various channels to connect to a Redis server. By default it uses TCP, but UDS and custom streams are available. Connection parameters used by a Client can be configured using a Builder.

A Client manages a pool of connections to a Redis server. Cloning a Client will result in a copy that shares the pool with the original one.

You do not need to re-wrap it with Arc or similar, since it already uses an Arc internally.

Implementations§

Source§

impl Client<TcpConnector>

Source

pub async fn new(max_connections: usize, addr: &str) -> Result<Self, BuildError>

Constructs a client with default configurations.

If you need more tweaks use Client::builder() instead.

Source

pub fn builder() -> Builder

Constructs a Builder to construct a Client with custom parameters.

Source§

impl<T: Connector> Client<T>

Source

pub fn server_hello(&self) -> Arc<Value>

Server hello response from the last connection created.

Source

pub async fn raw_command<Req: Serialize, Resp: DeserializeOwned>( &self, request: Req, ) -> Result<Resp, Error>

Sends any command and get a response.

Both command and response are serialized/deserialized using serde. See CommandSerializer and Deserializer for details.

Source

pub async fn connection(&self) -> Result<Connection<T::Stream>, Error>

Gets a connection from the pool, creating one if not available.

Normally, a dropped Connection will be returned to the Client’s pool.

Methods from Deref<Target = CommandHelper<ClientShared<T>>>§

Source

pub async fn copy<S, D>( &self, source: S, destination: D, db: Option<u32>, replace: bool, ) -> Result<bool, Error>
where S: Serialize + Send, D: Serialize + Send,

https://redis.io/commands/copy

source and the destination should be scalar types.

client.set(key1, "sheep").await?;
let res = client.copy(key1, key2, None, false).await?;
assert!(res);
let res: String = client.get(key2).await?;
assert_eq!("sheep", res);
Source

pub async fn del<K>(&self, keys: K) -> Result<usize, Error>
where K: Serialize + Send,

https://redis.io/commands/del

keys should be a sequence type.

client.set(key1, "Hello").await?;
client.set(key2, "World").await?;
let res = client.del([key1, key2]).await?;
assert_eq!(2, res);
Source

pub async fn exists<K>(&self, keys: K) -> Result<usize, Error>
where K: Serialize + Send,

https://redis.io/commands/exists

keys should be a sequence type.

client.set(key1, "Hello").await?;
let res = client.exists(key1).await?;
assert_eq!(1, res);
let res = client.exists("nosuchkey").await?;
assert_eq!(0, res);
client.set(key2, "World").await?;
let res = client.exists([key1, key2, "nosuchkey"]).await?;
assert_eq!(2, res);
Source

pub async fn exists_one<K>(&self, key: K) -> Result<bool, Error>
where K: Serialize + Send,

Same as .exists(), but takes single key and returns bool.

key should be a scalar type.

let res = client.exists_one(key).await?;
assert!(!res);
client.set(key, "Hello").await?;
let res = client.exists_one(key).await?;
assert!(res);
Source

pub async fn expire<K>(&self, key: K, timeout: Duration) -> Result<bool, Error>
where K: Serialize + Send,

https://redis.io/commands/pexpire

Despite the name, this method uses PEXPIRE, not EXPIRE, for millisecond-level accuracy.

keys should be a scalar type.

client.set(key, "Hello").await?;
let res = client.expire(key, Duration::from_secs(10)).await?;
assert!(res);
let res = client.ttl(key).await?;
assert!(helper::mostly_eq(res.unwrap(), Duration::from_secs(10)));
client.set(key, "Hello World").await?;
Source

pub async fn expireat<K>( &self, key: K, timestamp: SystemTime, ) -> Result<bool, Error>
where K: Serialize + Send,

https://redis.io/commands/pexpireat

Despite the name, this method uses PEXPIREAT, not EXPIREAT, for millisecond-level accuracy.

keys should be a scalar type.

client.set(key, "Hello").await?;
let res = client.exists_one(key).await?;
assert!(res);
let res = client.expireat(key, SystemTime::UNIX_EPOCH).await?;
assert!(res);
let res = client.exists_one(key).await?;
assert!(!res);
Source

pub async fn ttl<K>(&self, key: K) -> Result<Option<Duration>, Error>
where K: Serialize + Send,

https://redis.io/commands/pttl

Despite the name, this method uses PTTL, not TTL, for millisecond-level accuracy.

keys should be a scalar type.

client.set(key, "Hello").await?;
let res = client.expire(key, Duration::from_secs(10)).await?;
assert!(res);
let res = client.ttl(key).await?;
assert!(helper::mostly_eq(res.unwrap(), Duration::from_secs(10)));
Source

pub async fn scan<R>( &self, cursor: u64, match_pattern: Option<&str>, count: Option<usize>, ) -> Result<(u64, R), Error>

https://redis.io/commands/scan

key should be a scalar type.

client.set(key1, "value1").await?;
client.set(key2, "value2").await?;
client.set(key3, "value3").await?;
let mut cursor = 0;
let mut output = vec![];
loop {
    let (next, res): (u64, Vec<String>) = client.scan(cursor, Some(pattern), None).await?;
    output.extend(res);
    cursor = next;
    if next == 0 {
        break;
    }
}
output.sort();
assert_eq!(vec![key1.to_owned(), key2.into(), key3.into()], output);
Source

pub async fn hdel<K, F>(&self, key: K, fields: F) -> Result<usize, Error>
where K: Serialize + Send, F: Serialize + Send,

https://redis.io/commands/hdel

key should be a scalar type, and fields should be a sequence type.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
    field2: i32,
}
let res = client.hset(key, &Fields { field1: "foo".into(), field2: 42 }).await?;
assert_eq!(2, res);
let res = client.hdel(key, ("field1", "field2")).await?;
assert_eq!(2, res);
let res = client.hdel(key, "field1").await?;
assert_eq!(0, res);
Source

pub async fn hexists<K, F>(&self, key: K, field: F) -> Result<bool, Error>
where K: Serialize + Send, F: Serialize + Send,

https://redis.io/commands/hexists

key and field should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
}
let res = client.hset(key, &Fields { field1: "foo".into() }).await?;
assert_eq!(1, res);
let res = client.hexists(key, "field1").await?;
assert!(res);
let res = client.hexists(key, "field2").await?;
assert!(!res);
Source

pub async fn hget<K, F, R>(&self, key: K, field: F) -> Result<R, Error>

https://redis.io/commands/hget

key and field should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
}
let res = client.hset(key, &Fields { field1: "foo".into() }).await?;
assert_eq!(1, res);
let res: String = client.hget(key, "field1").await?;
assert_eq!("foo", res);
let res: Option<String> = client.hget(key, "field2").await?;
assert!(res.is_none());
Source

pub async fn hgetall<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/hgetall

key should be a scalar type.

#[derive(serde::Serialize, PartialEq)]
struct Fields {
    field1: String,
    field2: String,
}
let res = client.hset(key, &Fields { field1: "Hello".into(), field2: "World".into() }).await?;
assert_eq!(2, res);
let res: HashMap<String, String> = client.hgetall(key).await?;
assert_eq!(2, res.len());
assert_eq!("Hello", &res["field1"]);
assert_eq!("World", &res["field2"]);
Source

pub async fn hincrby<K, F>( &self, key: K, field: F, increment: i64, ) -> Result<i64, Error>
where K: Serialize + Send, F: Serialize + Send,

https://redis.io/commands/hincrby

key and field should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    field1: i32,
}
let res = client.hset(key, &Fields { field1: 5 }).await?;
assert_eq!(1, res);
let res = client.hincrby(key, "field1", 1).await?;
assert_eq!(6, res);
let res = client.hincrby(key, "field1", -1).await?;
assert_eq!(5, res);
let res = client.hincrby(key, "field1", -10).await?;
assert_eq!(-5, res);
Source

pub async fn hincrbyfloat<K, F>( &self, key: K, field: F, increment: f64, ) -> Result<f64, Error>
where K: Serialize + Send, F: Serialize + Send,

https://redis.io/commands/hincrbyfloat

key and field should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    field: f64,
}
let res = client.hset(key, &Fields { field: 10.50 }).await?;
assert_eq!(1, res);
let res = client.hincrbyfloat(key, "field", 0.1).await?;
assert_eq!(10.6, res);
let res = client.hincrbyfloat(key, "field", -5.0).await?;
assert_eq!(5.6, res);
let res = client.hset(key, &Fields { field: 5.0e3 }).await?;
assert_eq!(0, res);
let res = client.hincrbyfloat(key, "field", 2.0e2).await?;
assert_eq!(5200.0, res);
Source

pub async fn hkeys<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/hkeys

key should be a scalar type.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
    field2: String,
}
let res = client.hset(key, &Fields { field1: "Hello".into(), field2: "World".into() }).await?;
assert_eq!(2, res);
let res: Vec<String> = client.hkeys(key).await?;
assert_eq!(&["field1".to_owned(), "field2".to_owned()][..], &res[..]);
Source

pub async fn hlen<K>(&self, key: K) -> Result<usize, Error>
where K: Serialize + Send,

https://redis.io/commands/hlen

key should be a scalar type.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
    field2: String,
}
let res = client.hset(key, &Fields { field1: "Hello".into(), field2: "World".into() }).await?;
assert_eq!(2, res);
let res = client.hlen(key).await?;
assert_eq!(2, res);
Source

pub async fn hmget<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/hmget

key should be a scalar type and returned R must be a struct type with named fields, not enum or tuple struct.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
    field2: String,
}
#[derive(serde::Deserialize, PartialEq, Debug)]
struct Query {
    field1: String,
    field2: String,
    nofield: Option<i32>,
}
let res = client.hset(key, &Fields { field1: "Hello".into(), field2: "World".into() }).await?;
assert_eq!(2, res);
for _ in 0..10 {
    let res: Query = client.hmget(key).await?;
    assert_eq!(Query { field1: "Hello".into(), field2: "World".into(), nofield: None }, res);
}
Source

pub async fn hrandfield<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/hrandfield

HRANDFIELD with just the key argument. key should be a scalar type.

#[derive(serde::Serialize)]
struct Fields {
    head: String,
    tails: String,
    edge: String,
}
let res = client.hset(key, &Fields { head: "obverse".into(), tails: "reverse".into(), edge: "null".into() }).await?;
assert_eq!(3, res);
let res: String = client.hrandfield(key).await?;
assert!(["head".to_owned(), "tails".to_owned(), "edge".to_owned()].contains(&res), "res: {}", res);
Source

pub async fn hrandfield_count<K, R>( &self, key: K, count: isize, ) -> Result<R, Error>

https://redis.io/commands/hrandfield

HRANDFIELD with count and optional WITHVALUES specifier. key should be a scalar type.

#[derive(serde::Serialize)]
struct Fields {
    head: String,
}
let res = client.hset(key, &Fields { head: "obverse".into() }).await?;
assert_eq!(1, res);
let res: Vec<String> = client.hrandfield_count(key, 3).await?;
assert_eq!(vec!["head".to_owned()], res);
let res: Vec<String> = client.hrandfield_count(key, -3).await?;
assert_eq!(vec!["head".to_owned(), "head".to_owned(), "head".to_owned()], res);
Source

pub async fn hscan<K, R>( &self, key: K, cursor: u64, match_pattern: Option<&str>, count: Option<usize>, ) -> Result<(u64, R), Error>

https://redis.io/commands/hscan

key should be a scalar type.

#[derive(serde::Serialize)]
struct Fields {
    name: String,
    age: i32,
}
let res = client.hset(key, &Fields { name: "Jack".into(), age: 33 }).await?;
assert_eq!(2, res);
let (cursor, res): (u64, Vec<String>) = client.hscan(key, 0, None, None).await?;
assert_eq!(0, cursor);
assert_eq!(vec!["name".to_owned(), "Jack".to_owned(), "age".to_owned(), "33".to_owned()], res);
Source

pub async fn hset<K, E>(&self, key: K, entries: E) -> Result<usize, Error>
where K: Serialize + Send, E: Serialize + Send,

https://redis.io/commands/hset

key should be a scalar type, and entries should be a map-like type.

#[derive(serde::Serialize)]
struct Fields {
    field1: String,
    field2: i32,
}
let res = client.hset(key, &Fields { field1: "foo".into(), field2: 42 }).await?;
assert_eq!(2, res);
let res: String = client.hget(key, "field1").await?;
assert_eq!("foo", res);
Source

pub async fn hsetnx<K, F, V>( &self, key: K, field: F, value: V, ) -> Result<bool, Error>
where K: Serialize + Send, F: Serialize + Send, V: Serialize + Send,

https://redis.io/commands/hsetnx

key, field and value should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    field: f64,
}
let res = client.hsetnx(key, "field", "Hello").await?;
assert!(res);
let res = client.hsetnx(key, "field", "World").await?;
assert!(!res);
let res: String = client.hget(key, "field").await?;
assert_eq!("Hello", res);
Source

pub async fn hstrlen<K, F>(&self, key: K, field: F) -> Result<usize, Error>
where K: Serialize + Send, F: Serialize + Send,

https://redis.io/commands/hstrlen

key and field should be scalar types.

#[derive(serde::Serialize)]
struct Fields {
    f1: String,
    f2: usize,
    f3: i32,
}
let res = client.hset(key, &Fields { f1: "HelloWorld".into(), f2: 99, f3: -256 }).await?;
assert_eq!(3, res);
let res = client.hstrlen(key, "f1").await?;
assert_eq!(10, res);
let res = client.hstrlen(key, "f2").await?;
assert_eq!(2, res);
let res = client.hstrlen(key, "f3").await?;
assert_eq!(4, res);
Source

pub async fn hvals<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/hvals

key should be a scalar type.

#[derive(serde::Serialize, PartialEq)]
struct Fields {
    field1: String,
    field2: String,
}
let res = client.hset(key, &Fields { field1: "Hello".into(), field2: "World".into() }).await?;
assert_eq!(2, res);
let res: Vec<String> = client.hvals(key).await?;
assert_eq!(vec!["Hello".to_owned(), "World".to_owned()], res);
Source

pub async fn append<K, V>(&self, key: K, value: V) -> Result<usize, Error>
where K: Serialize + Send, V: Serialize + Send,

https://redis.io/commands/append

key and value should be scalar types.

let res = client.exists_one(key).await?;
assert!(!res);
let res = client.append(key, "Hello").await?;
assert_eq!(5, res);
let res = client.append(key, " World").await?;
assert_eq!(11, res);
let res: String = client.get(key).await?;
assert_eq!("Hello World", res);
Source

pub async fn decr<K>(&self, key: K) -> Result<i64, Error>
where K: Serialize + Send,

https://redis.io/commands/decr

key should be a scalar type.

client.set(key, "10").await?;
let res = client.decr(key).await?;
assert_eq!(9, res);
client.set(key, "234293482390480948029348230948").await?;
let res = client.decr(key).await;
assert!(res.is_err());
Source

pub async fn decrby<K>(&self, key: K, decrement: i64) -> Result<i64, Error>
where K: Serialize + Send,

https://redis.io/commands/decrby

key should be a scalar type.

client.set(key, "10").await?;
let res = client.decrby(key, 3).await?;
assert_eq!(7, res);
Source

pub async fn get<K, R>(&self, key: K) -> Result<R, Error>

https://redis.io/commands/get

key should be a scalar type.

let res: Option<i32> = client.get("nonexisting").await?;
assert!(res.is_none());
client.set(key, "Hello").await?;
let res: String = client.get(key).await?;
assert_eq!("Hello", res);
Source

pub async fn getrange<K, R>( &self, key: K, start: isize, end: isize, ) -> Result<R, Error>

https://redis.io/commands/getrange

key should be a scalar type.

client.set(key, "This is a string").await?;
let res: String = client.getrange(key, 0, 3).await?;
assert_eq!("This", res);
let res: String = client.getrange(key, -3, -1).await?;
assert_eq!("ing", res);
let res: String = client.getrange(key, 0, -1).await?;
assert_eq!("This is a string", res);
let res: String = client.getrange(key, 10, 100).await?;
assert_eq!("string", res);
Source

pub async fn incr<K>(&self, key: K) -> Result<i64, Error>
where K: Serialize + Send,

https://redis.io/commands/incr

key should be a scalar type.

client.set(key, "10").await?;
let res = client.incr(key).await?;
assert_eq!(11, res);
let res: i64 = client.get(key).await?;
assert_eq!(11, res);
Source

pub async fn incrby<K>(&self, key: K, increment: i64) -> Result<i64, Error>
where K: Serialize + Send,

https://redis.io/commands/incrby

key should be a scalar type.

client.set(key, "10").await?;
let res = client.incrby(key, 5).await?;
assert_eq!(15, res);
Source

pub async fn incrbyfloat<K>(&self, key: K, increment: f64) -> Result<f64, Error>
where K: Serialize + Send,

https://redis.io/commands/incrbyfloat

key should be a scalar type.

client.set(key, 10.50f64).await?;
let res = client.incrbyfloat(key, 0.1).await?;
assert_eq!(10.6, res);
let res = client.incrbyfloat(key, -5.0).await?;
assert_eq!(5.6, res);
client.set(key, "5.0e3").await?;
let res = client.incrbyfloat(key, 200.0).await?;
assert_eq!(5200.0, res);
Source

pub async fn mget<K, R>(&self, keys: K) -> Result<R, Error>

https://redis.io/commands/mget

keys should be a sequence type.

client.set(key1, "Hello").await?;
client.set(key2, "World").await?;
let res: Vec<Option<String>> = client.mget([key1, key2, "nonexisting"]).await?;
assert_eq!(vec![
    Some("Hello".to_owned()),
    Some("World".to_owned()),
    None,
], res);
Source

pub async fn mset<E>(&self, entries: E) -> Result<(), Error>
where E: Serialize + Send,

https://redis.io/commands/mset

entries should be a map-like type.

let mut map = HashMap::new();
map.insert(key1, "Hello");
map.insert(key2, "World");
client.mset(&map).await?;
let res: String = client.get(key1).await?;
assert_eq!("Hello", res);
let res: String = client.get(key2).await?;
assert_eq!("World", res);
Source

pub async fn set<K, V>(&self, key: K, value: V) -> Result<(), Error>
where K: Serialize + Send, V: Serialize + Send,

https://redis.io/commands/set

key and value should be scalar types.

client.set(key, "Hello").await?;
let res: String = client.get(key).await?;
assert_eq!("Hello", res);
Source

pub async fn setrange<K, V>( &self, key: K, offset: usize, value: V, ) -> Result<usize, Error>
where K: Serialize + Send, V: Serialize + Send,

https://redis.io/commands/setrange

key and value should be scalar types.

client.set(key1, "Hello World").await?;
let res = client.setrange(key1, 6, "Redis").await?;
assert_eq!(11, res);
let res: String = client.get(key1).await?;
assert_eq!("Hello Redis", res);

let res = client.setrange(key2, 6, "Redis").await?;
assert_eq!(11, res);
let res: String = client.get(key2).await?;
assert_eq!("\0\0\0\0\0\0Redis", res);
Source

pub async fn strlen<K>(&self, key: K) -> Result<usize, Error>
where K: Serialize + Send,

https://redis.io/commands/strlen

key should be a scalar type.

client.set(key, "Hello world").await?;
let res = client.strlen(key).await?;
assert_eq!(11, res);
let res = client.strlen("nonexisting").await?;
assert_eq!(0, res);
Source

pub async fn raw_command<Req, Resp>(&self, request: Req) -> Result<Resp, Error>
where Req: Serialize + Send, Resp: DeserializeOwned,

Sends any command and get a response.

Both command and response are serialized/deserialized using serde. See CommandSerializer and Deserializer for details.

Trait Implementations§

Source§

impl<T: Connector> Clone for Client<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug + Connector> Debug for Client<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Connector> Deref for Client<T>

Source§

type Target = CommandHelper<ClientShared<T>>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T: Connector> From<Arc<CommandHelper<ClientShared<T>>>> for Client<T>

Source§

fn from(shared: Arc<CommandHelper<ClientShared<T>>>) -> Self

Converts to this type from the input type.
Source§

impl<T: Connector> From<Client<T>> for Arc<CommandHelper<ClientShared<T>>>

Source§

fn from(client: Client<T>) -> Self

Converts to this type from the input type.
Source§

impl<T: Connector> From<ClientShared<T>> for Client<T>

Source§

fn from(shared: ClientShared<T>) -> Self

Converts to this type from the input type.
Source§

impl<T: Connector> RawCommand for Client<T>

Source§

fn raw_command<'a, Req, Resp>( &'a self, request: Req, ) -> BoxFuture<'a, Result<Resp, Error>>
where Req: Serialize + Send + 'a, Resp: DeserializeOwned + 'a,

Sends any command and get a response. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Client<T>

§

impl<T> RefUnwindSafe for Client<T>
where T: RefUnwindSafe,

§

impl<T> Send for Client<T>

§

impl<T> Sync for Client<T>

§

impl<T> Unpin for Client<T>

§

impl<T> UnwindSafe for Client<T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.