Skip to content

Commit 607ca17

Browse files
committed
Improvements in the documentation.
1 parent 3849ba4 commit 607ca17

File tree

1 file changed

+56
-68
lines changed

1 file changed

+56
-68
lines changed

README.md

Lines changed: 56 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
11
# Aedis
22

33
Aedis is a [Redis](https://redis.io/) client library built on top of
4-
[Asio](https://www.boost.org/doc/libs/release/doc/html/boost_asio.html)
4+
[Boost.Asio](https://www.boost.org/doc/libs/release/doc/html/boost_asio.html)
55
that implements the latest version of the Redis communication
66
protocol
77
[RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md).
8-
It makes communication with a Redis server easy by hiding some of
9-
the low-level Asio-related code away from the user, which in the majority of
10-
the cases will be concerned with only three library entities
8+
It makes communication with a Redis server easy by hiding low-level
9+
Asio-related code away from the user, which, in the majority of the
10+
cases will be concerned with only three library entities
1111

1212
* `aedis::connection`: A connection to the Redis server.
1313
* `aedis::resp3::request`: A container of Redis commands.
14-
* `aedis::adapt()`: Adapts data structures to receive responses.
14+
* `aedis::adapt()`: A function that adapts data structures to receive responses.
1515

16-
For example, the coroutine below uses a short-lived connection to read Redis
17-
[hashes](https://redis.io/docs/data-types/hashes/)
18-
in a `std::map`
16+
The requirements for using Aedis are
17+
18+
* Boost 1.80 or greater.
19+
* C++17 minimum.
20+
* Redis 6 or higher (must support RESP3).
21+
* Have basic-level knowledge about Redis and understand Asio and its asynchronous model.
22+
23+
Readers that are not familiar with Redis can learn more about
24+
it on https://redis.io/docs/, in essence
25+
26+
> Redis is an open source (BSD licensed), in-memory data structure
27+
> store used as a database, cache, message broker, and streaming
28+
> engine. Redis provides data structures such as strings, hashes,
29+
> lists, sets, sorted sets with range queries, bitmaps, hyperloglogs,
30+
> geospatial indexes, and streams. Redis has built-in replication, Lua
31+
> scripting, LRU eviction, transactions, and different levels of
32+
> on-disk persistence, and provides high availability via Redis
33+
> Sentinel and automatic partitioning with Redis Cluster.
34+
35+
<a name="connection"></a>
36+
## Connection
37+
38+
Let us start with a simple application that uses a short-lived
39+
connection to read Redis
40+
[hashes](https://redis.io/docs/data-types/hashes/) in a `std::map`
1941

2042
```cpp
2143
auto async_main() -> net::awaitable<void>
@@ -31,27 +53,21 @@ auto async_main() -> net::awaitable<void>
3153
req.push("HGETALL", "hset-key");
3254
req.push("QUIT");
3355

34-
// Responses as tuple elements.
56+
// The tuple elements below will store the response to each
57+
// individual command. The responses to HELLO and QUIT are being
58+
// ignored for simplicity.
3559
std::tuple<ignore, std::map<std::string, std::string>, ignore> resp;
3660

37-
// Executes the request and reads the response.
61+
// Executes the request. See below why we are using operator ||.
3862
co_await (conn->async_run() || conn->async_exec(req, adapt(resp)));
39-
4063
// Use the map from std::get<1>(resp) ...
4164
}
4265
```
4366

44-
For other versions of this example that use different styles see
45-
46-
* cpp20_intro.cpp: Does not use awaitable operators.
47-
* cpp20_intro_awaitable_ops.cpp: The version from above.
48-
* cpp17_intro.cpp: Uses callbacks and requires C++17.
49-
* cpp20_intro_tls.cpp: Communicates over TLS.
50-
51-
The execution of `connection::async_exec` in the example above is composed with
52-
`connection::async_run` with the aid of the Asio awaitable `operator ||`
53-
that ensures that one operation is cancelled as soon as the other
54-
completes. These functions play the following roles
67+
The example above uses the Asio awaitable `operator ||` to launch
68+
`connection::async_exec` and `connection::async_run` in parallel and
69+
to cancel one of the operations when the other completes. The role
70+
played by these functions are
5571

5672
* `connection::async_exec`: Execute commands by queuing the request
5773
for writing and wait for the response sent back by
@@ -62,11 +78,12 @@ completes. These functions play the following roles
6278
server-push is received. It will also trigger writes of pending
6379
requests when a reconnection occurs.
6480

65-
The role played by `async_run` can be better understood in the context
66-
of long-lived connections, which we will cover in the next section.
81+
The example above is also available in other programming styles for comparison
6782

68-
<a name="connection"></a>
69-
## Connection
83+
* cpp20_intro.cpp: Does not use awaitable operators.
84+
* cpp20_intro_awaitable_ops.cpp: The version from above.
85+
* cpp17_intro.cpp: Uses callbacks and requires C++17.
86+
* cpp20_intro_tls.cpp: Communicates over TLS.
7087

7188
For performance reasons we will usually want to perform multiple
7289
requests in the same connection. We can do this in the example above
@@ -132,10 +149,7 @@ auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
132149
}
133150
```
134151

135-
Here we use Asio awaitable operators for simplicity, the same
136-
functionality can be achieved by means of the
137-
`aedis::connection::cancel` function. The definition of the
138-
`healthy_checker` used above can be found in common.cpp.
152+
The definition of the `healthy_checker` used above can be found in common.cpp.
139153

140154
### Server pushes
141155

@@ -146,8 +160,8 @@ them are
146160
* [Keyspace notification](https://redis.io/docs/manual/keyspace-notifications/)
147161
* [Client-side caching](https://redis.io/docs/manual/client-side-caching/)
148162

149-
The connection class supports that by means of the
150-
`aedis::connection::async_receive` function
163+
The connection class supports server pushes by means of the
164+
`aedis::connection::async_receive` function, for example
151165

152166
```cpp
153167
auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
@@ -161,8 +175,8 @@ auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
161175
}
162176
```
163177
164-
This function can be also easily incorporated in the run function from
165-
above, for example
178+
The `receiver` defined above can be run detached or incorporated
179+
in the `run` function as we did for the `healthy_checker`
166180
167181
```cpp
168182
auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
@@ -207,26 +221,13 @@ to force a failover). It would be annoying if each individual section
207221
were to throw exceptions and handle error. With the pattern shown
208222
above the only place that has to managed is the run function.
209223
210-
At this point the reasons for why `async_run` was introduced in Aedis
211-
might have become apparent to the reader
212-
213-
* Provide quick reaction to disconnections and hence faster failovers.
214-
* Support server pushes and requests in the same connection object, concurrently.
215-
* Separate requests, handling of server pushes and reconnect operations.
216-
217224
### Cancellation
218225
219226
Aedis supports both implicit and explicit cancellation of connection
220227
operations. Explicit cancellation is supported by means of the
221-
`aedis::connection::cancel` member function. Implicit cancellation,
222-
like those that may happen when using Asio awaitable operators `&&` and
223-
`||` will be discussed with more detail below.
224-
225-
```cpp
226-
co_await (conn.async_run(...) && conn.async_exec(...))
227-
```
228-
229-
* Provides a simple way to send HELLO and perform channel subscription.
228+
`aedis::connection::cancel` member function. Implicit
229+
terminal-cancellation, like those that happen when using Asio
230+
awaitable `operator ||` will be discussed with more detail below.
230231
231232
```cpp
232233
co_await (conn.async_run(...) || conn.async_exec(...))
@@ -244,20 +245,14 @@ co_await (conn.async_exec(...) || time.async_wait(...))
244245
* NOTE: It is usually a better idea to have a healthy checker than adding
245246
per request timeout, see cpp20_subscriber.cpp for an example.
246247
247-
```cpp
248-
co_await (conn.async_run(...) || time.async_wait(...))
249-
```
250-
251-
* Sets a limit on how long the connection should live.
252-
253248
```cpp
254249
co_await (conn.async_exec(...) || conn.async_exec(...) || ... || conn.async_exec(...))
255250
```
256251

257252
* This works but is unnecessary. Unless the user has set
258253
`aedis::resp3::request::config::coalesce` to `false`, and he
259254
usually shouldn't, the connection will automatically merge the
260-
individual requests into a single payload anyway.
255+
individual requests into a single payload.
261256

262257
<a name="requests"></a>
263258
## Requests
@@ -334,7 +329,7 @@ reader is advised to read it carefully.
334329
Aedis uses the following strategy to support Redis responses
335330
336331
* **Static**: For `aedis::resp3::request` whose sizes are known at compile time
337-
std::tuple is supported.
332+
`std::tuple` is supported.
338333
* **Dynamic**: Otherwise use `std::vector<aedis::resp3::node<std::string>>`.
339334
340335
For example, below is a request with a compile time size
@@ -717,10 +712,10 @@ stars, namely
717712
718713
### Aedis vs Redis-plus-plus
719714
720-
Before we start it is important to mentioning some of the things
715+
Before we start it is important to mention some of the things
721716
redis-plus-plus does not support
722717
723-
* The latest version of the communication protocol RESP3. Without it it is impossible to support some important Redis features like client side caching, among other things.
718+
* The latest version of the communication protocol RESP3. Without that it is impossible to support some important Redis features like client side caching, among other things.
724719
* Coroutines.
725720
* Reading responses directly in user data structures to avoid creating temporaries.
726721
* Error handling with support for error-code.
@@ -817,7 +812,7 @@ It is also not clear how are pipelines realised with this design
817812
## Reference
818813
819814
* [High-Level](#high-level-api): Covers the topics discussed in this document.
820-
* [Low-Level](#low-level-api): Covers low-level building blocks. Provided mostly for developers, most users won't need any information provided here.
815+
* [Low-Level](#low-level-api): Covers low-level building blocks. Provided mostly for developers, users won't usually need any information provided here.
821816

822817
## Installation
823818

@@ -837,13 +832,6 @@ examples and test cmake is supported, for example
837832
BOOST_ROOT=/opt/boost_1_80_0 cmake --preset dev
838833
```
839834

840-
The requirements for using Aedis are
841-
842-
- Boost 1.80 or greater.
843-
- C++17 minimum.
844-
- Redis 6 or higher (must support RESP3).
845-
- Optionally also redis-cli and Redis Sentinel.
846-
847835
The following compilers are supported
848836

849837
- Gcc: 10, 11, 12.

0 commit comments

Comments
 (0)