Skip to content

Commit 3849ba4

Browse files
committed
Changes:
- Fix include header order. - Removes default completion token where it is not needed. - Replaces yield with BOOST_ macros.
1 parent 56bcdb7 commit 3849ba4

File tree

17 files changed

+145
-124
lines changed

17 files changed

+145
-124
lines changed

README.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Aedis is a [Redis](https://redis.io/) client library built on top of
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 most of
8+
It makes communication with a Redis server easy by hiding some of
99
the low-level Asio-related code away from the user, which in the majority of
1010
the cases will be concerned with only three library entities
1111

@@ -48,14 +48,14 @@ For other versions of this example that use different styles see
4848
* cpp17_intro.cpp: Uses callbacks and requires C++17.
4949
* cpp20_intro_tls.cpp: Communicates over TLS.
5050

51-
The execution of `connection::async_exec` above is composed with
51+
The execution of `connection::async_exec` in the example above is composed with
5252
`connection::async_run` with the aid of the Asio awaitable `operator ||`
5353
that ensures that one operation is cancelled as soon as the other
5454
completes. These functions play the following roles
5555

5656
* `connection::async_exec`: Execute commands by queuing the request
57-
for writing. It will wait for the response sent back by Redis and
58-
can be called from multiple places in your code concurrently.
57+
for writing and wait for the response sent back by
58+
Redis. Can be called from multiple places in your code concurrently.
5959
* `connection::async_run`: Coordinate low-level read and write
6060
operations. More specifically, it will hand IO control to
6161
`async_exec` when a response arrives and to `async_receive` when a
@@ -92,23 +92,30 @@ auto ping(std::shared_ptr<connection> conn) -> net::awaitable<void>
9292
{
9393
resp3::request req;
9494
req.push("PING", "Hello world");
95-
req.push("QUIT");
9695

97-
std::tuple<std::string, aedis::ignore> resp;
96+
std::tuple<std::string> resp;
9897
co_await conn->async_exec(req, adapt(resp));
9998
// Use the response ...
10099
}
101100

101+
auto quit(std::shared_ptr<connection> conn) -> net::awaitable<void>
102+
{
103+
resp3::request req;
104+
req.push("QUIT");
105+
106+
co_await conn->async_exec(req);
107+
}
108+
102109
auto async_main() -> net::awaitable<void>
103110
{
104111
auto ex = co_await net::this_coro::executor;
105112
auto conn = std::make_shared<connection>(ex);
106113
net::co_spawn(ex, run(conn), net::detached);
107114
co_await hello(conn);
108115
co_await ping(conn);
116+
co_await quit(conn);
109117

110-
// Here we can pass conn to other coroutines that need to
111-
// communicate with Redis.
118+
// Pass conn around to other coroutines that need to communicate with Redis.
112119
}
113120
```
114121
@@ -125,7 +132,7 @@ auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
125132
}
126133
```
127134

128-
Here we use Asio awaitable operator for simplicity, the same
135+
Here we use Asio awaitable operators for simplicity, the same
129136
functionality can be achieved by means of the
130137
`aedis::connection::cancel` function. The definition of the
131138
`healthy_checker` used above can be found in common.cpp.
@@ -170,7 +177,7 @@ auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
170177

171178
Adding a loop around `async_run` produces a simple way to support
172179
reconnection _while there are pending operations on the connection_,
173-
for example, to reconnect to the same address
180+
for example, to reconnect to the same address (see cpp20_subscriber.cpp)
174181

175182
```cpp
176183
auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
@@ -192,8 +199,15 @@ auto run(std::shared_ptr<connection> conn) -> net::awaitable<void>
192199
}
193200
```
194201
195-
For failover with sentinels see `cpp20_resolve_with_sentinel.cpp`. At
196-
this point the reasons for why `async_run` was introduced in Aedis
202+
This feature results in considerable simplification of backend code
203+
and makes it easier to write failover-safe applications. For example,
204+
a HTTP server might have a 100 sessions communicating with Redis at
205+
the time the connection is lost (or maybe killed by the server admin
206+
to force a failover). It would be annoying if each individual section
207+
were to throw exceptions and handle error. With the pattern shown
208+
above the only place that has to managed is the run function.
209+
210+
At this point the reasons for why `async_run` was introduced in Aedis
197211
might have become apparent to the reader
198212
199213
* Provide quick reaction to disconnections and hence faster failovers.
@@ -845,6 +859,7 @@ Acknowledgement to people that helped shape Aedis
845859
* Petr Dannhofer ([Eddie-cz](https://github.com/Eddie-cz)): For helping me understand how the `AUTH` and `HELLO` command can influence each other.
846860
* Mohammad Nejati ([ashtum](https://github.com/ashtum)): For pointing out scenarios where calls to `async_exec` should fail when the connection is lost.
847861
* Klemens Morgenstern ([klemens-morgenstern](https://github.com/klemens-morgenstern)): For useful discussion about timeouts, cancellation, synchronous interfaces and general help with Asio.
862+
* Vinnie Falco ([vinniefalco](https://github.com/vinniefalco)): For general suggestions about how to improve the code and the documentation.
848863

849864
## Changelog
850865

examples/cpp20_intro.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,21 @@ auto ping(std::shared_ptr<connection> conn) -> net::awaitable<void>
3232
{
3333
resp3::request req;
3434
req.push("PING", "Hello world");
35-
req.push("QUIT");
36-
37-
std::tuple<std::string, aedis::ignore> resp;
3835

36+
std::tuple<std::string> resp;
3937
co_await conn->async_exec(req, adapt(resp));
4038

4139
std::cout << "PING: " << std::get<0>(resp) << std::endl;
4240
}
4341

42+
auto quit(std::shared_ptr<connection> conn) -> net::awaitable<void>
43+
{
44+
resp3::request req;
45+
req.push("QUIT");
46+
47+
co_await conn->async_exec(req);
48+
}
49+
4450
// Called from the main function (see main.cpp)
4551
auto async_main() -> net::awaitable<void>
4652
{
@@ -49,6 +55,7 @@ auto async_main() -> net::awaitable<void>
4955
net::co_spawn(ex, run(conn), net::detached);
5056
co_await hello(conn);
5157
co_await ping(conn);
58+
co_await quit(conn);
5259
}
5360

5461
#endif // defined(BOOST_ASIO_HAS_CO_AWAIT)

include/aedis/adapt.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@
77
#ifndef AEDIS_ADAPT_HPP
88
#define AEDIS_ADAPT_HPP
99

10-
#include <tuple>
11-
#include <limits>
12-
#include <string_view>
13-
#include <variant>
10+
#include <aedis/resp3/node.hpp>
11+
#include <aedis/adapter/adapt.hpp>
12+
#include <aedis/adapter/detail/response_traits.hpp>
1413

1514
#include <boost/mp11.hpp>
1615
#include <boost/system.hpp>
1716

18-
#include <aedis/resp3/node.hpp>
19-
#include <aedis/adapter/adapt.hpp>
20-
#include <aedis/adapter/detail/response_traits.hpp>
17+
#include <tuple>
18+
#include <limits>
19+
#include <string_view>
20+
#include <variant>
2121

2222
namespace aedis {
2323

include/aedis/adapter/detail/adapters.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77
#ifndef AEDIS_ADAPTER_ADAPTERS_HPP
88
#define AEDIS_ADAPTER_ADAPTERS_HPP
99

10+
#include <aedis/error.hpp>
11+
#include <aedis/resp3/type.hpp>
12+
#include <aedis/resp3/request.hpp>
13+
#include <aedis/resp3/detail/parser.hpp>
14+
#include <aedis/resp3/node.hpp>
15+
16+
#include <boost/assert.hpp>
17+
1018
#include <set>
1119
#include <optional>
1220
#include <unordered_set>
@@ -21,14 +29,6 @@
2129
#include <string_view>
2230
#include <charconv>
2331

24-
#include <boost/assert.hpp>
25-
26-
#include <aedis/error.hpp>
27-
#include <aedis/resp3/type.hpp>
28-
#include <aedis/resp3/request.hpp>
29-
#include <aedis/resp3/detail/parser.hpp>
30-
#include <aedis/resp3/node.hpp>
31-
3232
namespace aedis::adapter::detail {
3333

3434
// Serialization.

include/aedis/adapter/detail/response_traits.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
#ifndef AEDIS_ADAPTER_RESPONSE_TRAITS_HPP
88
#define AEDIS_ADAPTER_RESPONSE_TRAITS_HPP
99

10-
#include <vector>
11-
#include <tuple>
12-
#include <string_view>
13-
#include <variant>
14-
15-
#include <boost/mp11.hpp>
16-
1710
#include <aedis/error.hpp>
1811
#include <aedis/resp3/type.hpp>
1912
#include <aedis/resp3/read.hpp>
2013
#include <aedis/adapter/detail/adapters.hpp>
2114

15+
#include <boost/mp11.hpp>
16+
17+
#include <vector>
18+
#include <tuple>
19+
#include <string_view>
20+
#include <variant>
21+
2222
namespace aedis::adapter::detail {
2323

2424
using ignore = std::decay_t<decltype(std::ignore)>;

include/aedis/connection.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
#ifndef AEDIS_CONNECTION_HPP
88
#define AEDIS_CONNECTION_HPP
99

10-
#include <chrono>
11-
#include <memory>
10+
#include <aedis/detail/connection_base.hpp>
1211

1312
#include <boost/asio/io_context.hpp>
14-
#include <aedis/detail/connection_base.hpp>
13+
14+
#include <chrono>
15+
#include <memory>
1516

1617
namespace aedis {
1718

include/aedis/detail/connection_base.hpp

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@
77
#ifndef AEDIS_CONNECTION_BASE_HPP
88
#define AEDIS_CONNECTION_BASE_HPP
99

10-
#include <vector>
11-
#include <queue>
12-
#include <limits>
13-
#include <chrono>
14-
#include <memory>
15-
#include <type_traits>
16-
#include <memory_resource>
10+
#include <aedis/adapt.hpp>
11+
#include <aedis/operation.hpp>
12+
#include <aedis/resp3/request.hpp>
13+
#include <aedis/detail/connection_ops.hpp>
1714

1815
#include <boost/assert.hpp>
1916
#include <boost/asio/ip/tcp.hpp>
@@ -22,10 +19,13 @@
2219
#include <boost/asio/deferred.hpp>
2320
#include <boost/asio/experimental/channel.hpp>
2421

25-
#include <aedis/adapt.hpp>
26-
#include <aedis/operation.hpp>
27-
#include <aedis/resp3/request.hpp>
28-
#include <aedis/detail/connection_ops.hpp>
22+
#include <vector>
23+
#include <queue>
24+
#include <limits>
25+
#include <chrono>
26+
#include <memory>
27+
#include <type_traits>
28+
#include <memory_resource>
2929

3030
namespace aedis::detail {
3131

@@ -44,7 +44,6 @@ class connection_base {
4444
using executor_type = Executor;
4545
using this_type = connection_base<Executor, Derived>;
4646

47-
explicit
4847
connection_base(executor_type ex, std::pmr::memory_resource* resource)
4948
: writer_timer_{ex}
5049
, read_timer_{ex}
@@ -134,13 +133,8 @@ class connection_base {
134133
return ret;
135134
}
136135

137-
template <
138-
class Adapter = detail::response_traits<void>::adapter_type,
139-
class CompletionToken = boost::asio::default_completion_token_t<executor_type>>
140-
auto async_exec(
141-
resp3::request const& req,
142-
Adapter adapter = adapt(),
143-
CompletionToken token = CompletionToken{})
136+
template <class Adapter, class CompletionToken>
137+
auto async_exec(resp3::request const& req, Adapter adapter, CompletionToken token)
144138
{
145139
BOOST_ASSERT_MSG(req.size() <= adapter.get_supported_response_size(), "Request and adapter have incompatible sizes.");
146140

@@ -150,12 +144,8 @@ class connection_base {
150144
>(detail::exec_op<Derived, Adapter>{&derived(), &req, adapter}, token, writer_timer_);
151145
}
152146

153-
template <
154-
class Adapter = detail::response_traits<void>::adapter_type,
155-
class CompletionToken = boost::asio::default_completion_token_t<executor_type>>
156-
auto async_receive(
157-
Adapter adapter = adapt(),
158-
CompletionToken token = CompletionToken{})
147+
template <class Adapter, class CompletionToken>
148+
auto async_receive(Adapter adapter, CompletionToken token)
159149
{
160150
auto f = detail::make_adapter_wrapper(adapter);
161151

0 commit comments

Comments
 (0)