rustis/lib.rs
1#![forbid(unsafe_code)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3/*!
4rustis is a Redis client for Rust.
5# Philosophy
6* Low allocations
7* Full async library
8* Lock free implementation
9* Rust idiomatic API
10
11# Features
12* Support all [Redis Commands](https://redis.io/commands/) until Redis 8.0
13* Async support ([tokio](https://tokio.rs/) or [async-std](https://async.rs/))
14* Different client types:
15 * Single client
16 * [Multiplexed](https://redis.com/blog/multiplexing-explained/) client
17 * Pooled client manager (based on [bb8](https://docs.rs/bb8/latest/bb8/))
18* Automatic command batching
19* Advanced reconnection & retry strategy
20* [Pipelining](https://redis.io/docs/manual/pipelining/) support
21* Configuration with Redis URL or dedicated builder
22* [TLS](https://redis.io/docs/latest/operate/oss_and_stack/management/security/encryption/) support
23* [Transaction](https://redis.io/docs/manual/transactions/) support
24* [Pub/sub](https://redis.io/docs/manual/pubsub/) support
25* [Sentinel](https://redis.io/docs/manual/sentinel/) support
26* [LUA Scripts/Functions](https://redis.io/docs/manual/programmability/) support
27* [Cluster](https://redis.io/docs/manual/scaling/) support
28* [Client-side caching](https://redis.io/docs/latest/develop/reference/client-side-caching/) support
29
30# Optional Features
31| Feature | Description |
32| ------- | ----------- |
33| `tokio-runtime` | [Tokio](https://tokio.rs/) runime (default) |
34| `async-std-runtime` | [async-std](https://async.rs/) runtime (optional) |
35| `tokio-rustls` | Tokio Rustls TLS support (optional) |
36| `tokio-native-tls` | Tokio native_tls TLS support (optional) |
37| `async-std-native-tls` | async-std native_tls TLS support (optional) |
38| `json` | Enables JSON (de)serialization support via `serde_json` |
39| `client-cache` | Enables client-side caching support |
40| `pool` | Pooled client manager (optional) |
41
42# Protocol Compatibility
43
44Rustis uses the RESP3 protocol **exclusively**.
45
46The `HELLO 3` command is automatically sent when establishing a connection.
47Therefore, your Redis server **must support RESP3** (Redis ≥6.0+ with RESP3 enabled).
48
49If you use Redis 5 or older, or your Redis 6+ server still defaults to RESP2,
50**Rustis will not work.**
51
52To verify your server supports RESP3:
53```bash
54redis-cli --raw HELLO 3
55```
56If you see server info (role, version, etc.), you're good to go.
57If you get an error, upgrade Redis.
58
59# Basic Usage
60
61```
62use rustis::{
63 client::Client,
64 commands::{FlushingMode, ServerCommands, StringCommands},
65 Result,
66};
67
68#[cfg_attr(feature = "tokio-runtime", tokio::main)]
69#[cfg_attr(feature = "async-std-runtime", async_std::main)]
70async fn main() -> Result<()> {
71 // Connect the client to a Redis server from its IP and port
72 let client = Client::connect("127.0.0.1:6379").await?;
73
74 // Flush all existing data in Redis
75 client.flushdb(FlushingMode::Sync).await?;
76
77 // sends the command SET to Redis. This command is defined in the StringCommands trait
78 client.set("key", "value").await?;
79
80 // sends the command GET to Redis. This command is defined in the StringCommands trait
81 let value: String = client.get("key").await?;
82 println!("value: {value:?}");
83
84 Ok(())
85}
86```
87
88# Client
89See the module [`client`] to discover which are the 3
90usages of the [`Client`](client::Client) struct and how to configure it.
91
92You will also learn how to use pipeline, pub/sub and transactions.
93
94# RESP
95RESP is the [Redis Serialization Protocol](https://redis.io/docs/reference/protocol-spec/).
96
97See the module [`resp`] to discover how **rustis**
98allows programmers to communicate with Redis in a Rust idiomatic way.
99
100You will learn how to:
101* Manipulate the **rustis** object model, the enum [`Value`](resp::Value), which is a generic Rust data structure over RESP.
102* Convert Rust type into Rust Commands with the [`Command`](resp::Command) struct and the [`Args`](resp::Args) trait.
103* Convert Rust command responses into Rust type with serde and helpful marker traits.
104
105# Commands
106In order to send [Commands](https://redis.io/commands/) to the Redis server,
107**rustis** offers two API levels:
108* High-level Built-in commands that implement all [Redis 7.0](https://redis.com/blog/redis-7-generally-available/) commands +
109 [Redis Stack](https://redis.io/docs/stack/) commands.
110* Low-level Generic command API to express any request that may not exist in **rustis**:
111 * new official commands not yet implemented by **rustis**.
112 * commands exposed by additional [Redis modules](https://redis.io/resources/modules/)
113 not included in [Redis Stack](https://redis.io/docs/stack/).
114
115## Built-in commands
116See the module [`commands`] to discover how Redis built-in commands are organized in different traits.
117
118## Generic command API
119To use the generic command API, you can use the [`cmd`](crate::resp::cmd) function to specify the name of the command,
120followed by one or multiple calls to the [`Commmand::arg`](crate::resp::Command::arg) associated function to add arguments to the command.
121
122This command can then be passed as a parameter to one of the following associated functions,
123depending on the client, transaction or pipeline struct used:
124* [`send`](crate::client::Client::send)
125* [`send_and_forget`](crate::client::Client::send_and_forget)
126* [`send_batch`](crate::client::Client::send_batch)
127
128```
129use rustis::{client::Client, resp::cmd, Result};
130
131#[cfg_attr(feature = "tokio-runtime", tokio::main)]
132#[cfg_attr(feature = "async-std-runtime", async_std::main)]
133async fn main() -> Result<()> {
134 let client = Client::connect("127.0.0.1:6379").await?;
135
136 client
137 .send::<()>(
138 cmd("MSET")
139 .arg("key1")
140 .arg("value1")
141 .arg("key2")
142 .arg("value2")
143 .arg("key3")
144 .arg("value3")
145 .arg("key4")
146 .arg("value4"),
147 None,
148 )
149 .await?;
150
151 let values: Vec<String> = client
152 .send(
153 cmd("MGET").arg("key1").arg("key2").arg("key3").arg("key4"),
154 None,
155 )
156 .await?;
157
158 assert_eq!(vec!["value1", "value2", "value3", "value4"], values);
159
160 Ok(())
161}
162```
163
164# Client-side caching
165See the module [`cache`] to discover how you can implement client-side caching.
166*/
167
168#[cfg(feature = "client-cache")]
169pub mod cache;
170pub mod client;
171pub mod commands;
172mod error;
173mod network;
174pub mod resp;
175
176#[cfg(feature = "pool")]
177pub use bb8;
178pub use error::*;
179use network::*;
180
181/// Library general result type.
182pub type Result<T> = std::result::Result<T, Error>;
183/// Library general future type.
184pub type Future<'a, T> = futures_util::future::BoxFuture<'a, Result<T>>;
185
186#[cfg(all(feature = "tokio-runtime", feature = "async-std-runtime"))]
187compile_error!(
188 "feature \"tokio-runtime\" and feature \"async-std-runtime\" cannot be enabled at the same time."
189);
190
191#[cfg(all(feature = "pool", feature = "async-std-runtime"))]
192compile_error!("feature \"pool\" is only compatible with \"tokio-runtime\" (bb8 constraint).");
193
194#[cfg(all(feature = "tokio-native-tls", feature = "tokio-rustls"))]
195compile_error!(
196 "Features `tokio-native-tls` and `tokio-rustls` cannot be enabled at the same time."
197);
198
199#[cfg(test)]
200mod tests;