mirror of
https://github.com/boostorg/redis.git
synced 2026-01-19 04:42:09 +00:00
Merge pull request #63 from boostorg/62-let-the-implementation-call-adaptresp-automatically
async_exec accepts response now instead of adapter.
This commit is contained in:
30
README.md
30
README.md
@@ -15,7 +15,7 @@ concerned with only three library entities
|
||||
[pipelines](https://redis.io/docs/manual/pipelining/).
|
||||
* `boost::redis::request`: A container of Redis commands that supports
|
||||
STL containers and user defined data types.
|
||||
* `boost::redis::adapt()`: A function that adapts data structures to receive responses.
|
||||
* `boost::redis::response`: Container of Redis responses.
|
||||
|
||||
In the next sections we will cover all those points in detail with
|
||||
examples. The requirements for using Boost.Redis are
|
||||
@@ -62,7 +62,7 @@ auto co_main() -> net::awaitable<void>
|
||||
// The tuple elements will store the responses to each individual
|
||||
// command. The responses to HELLO and QUIT are being ignored for
|
||||
// simplicity.
|
||||
response<ignore, std::map<std::string, std::string>, ignore> resp;
|
||||
response<ignore_t, std::map<std::string, std::string>, ignore_t> resp;
|
||||
|
||||
// Executes the request. See below why we are using operator ||.
|
||||
co_await (conn.async_run() || conn.async_exec(req, adapt(resp)));
|
||||
@@ -364,11 +364,11 @@ have as many elements as the request has commands (exceptions below).
|
||||
It is also necessary that each tuple element is capable of storing the
|
||||
response to the command it refers to, otherwise an error will occur.
|
||||
To ignore responses to individual commands in the request use the tag
|
||||
`boost::redis::ignore`
|
||||
`boost::redis::ignore_t`
|
||||
|
||||
```cpp
|
||||
// Ignore the second and last responses.
|
||||
response<std::string, boost::redis::ignore, std::string, boost::redis::ignore>
|
||||
response<std::string, boost::redis::ignore_t, std::string, boost::redis::ignore_t>
|
||||
```
|
||||
|
||||
The following table provides the resp3-types returned by some Redis
|
||||
@@ -416,12 +416,12 @@ can be read in the tuple below
|
||||
|
||||
```cpp
|
||||
response<
|
||||
redis::ignore, // hello
|
||||
int, // rpush
|
||||
int, // hset
|
||||
std::vector<T>, // lrange
|
||||
std::map<U, V>, // hgetall
|
||||
std::string // quit
|
||||
redis::ignore_t, // hello
|
||||
int, // rpush
|
||||
int, // hset
|
||||
std::vector<T>, // lrange
|
||||
std::map<U, V>, // hgetall
|
||||
std::string // quit
|
||||
> resp;
|
||||
```
|
||||
|
||||
@@ -515,10 +515,10 @@ using exec_resp_type =
|
||||
>;
|
||||
|
||||
response<
|
||||
boost::redis::ignore, // multi
|
||||
boost::redis::ignore, // get
|
||||
boost::redis::ignore, // lrange
|
||||
boost::redis::ignore, // hgetall
|
||||
boost::redis::ignore_t, // multi
|
||||
boost::redis::ignore_t, // get
|
||||
boost::redis::ignore_t, // lrange
|
||||
boost::redis::ignore_t, // hgetall
|
||||
exec_resp_type, // exec
|
||||
> resp;
|
||||
|
||||
@@ -868,6 +868,8 @@ Acknowledgement to people that helped shape Boost.Redis
|
||||
* Moves `boost::redis::resp3::request` to `boost::redis::request`.
|
||||
* Adds new typedef `boost::redis::response` that should be used instead of `std::tuple`.
|
||||
* Adds new typedef `boost::redis::generic_response` that should be used instead of `std::vector<resp3::node<std::string>>`.
|
||||
* Renames `redis::ignore` to `redis::ignore_t`.
|
||||
* Changes the signature from `async_exec` to receive a `redis::response` instead of an adapter.
|
||||
|
||||
### v1.4.0-1
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ using namespace net::experimental::awaitable_operators;
|
||||
using resolver = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::resolver>;
|
||||
using timer_type = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
|
||||
using boost::redis::request;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::operation;
|
||||
|
||||
namespace
|
||||
@@ -35,7 +34,7 @@ auto healthy_checker(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
|
||||
for (boost::system::error_code ec;;) {
|
||||
timer.expires_after(std::chrono::seconds{1});
|
||||
co_await (conn->async_exec(req, adapt()) || timer.async_wait(redir(ec)));
|
||||
co_await (conn->async_exec(req) || timer.async_wait(redir(ec)));
|
||||
|
||||
if (!ec) {
|
||||
co_return;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using redis::adapt;
|
||||
using redis::operation;
|
||||
using redis::request;
|
||||
using redis::response;
|
||||
@@ -39,7 +38,7 @@ auto main(int argc, char * argv[]) -> int
|
||||
req.push("QUIT");
|
||||
|
||||
// The response.
|
||||
response<redis::ignore, std::string, redis::ignore> resp;
|
||||
response<redis::ignore_t, std::string, redis::ignore_t> resp;
|
||||
|
||||
net::io_context ioc;
|
||||
|
||||
@@ -75,7 +74,7 @@ auto main(int argc, char * argv[]) -> int
|
||||
return log(ec, "on_connect: ");
|
||||
|
||||
conn.async_run(on_run);
|
||||
conn.async_exec(req, adapt(resp), on_exec);
|
||||
conn.async_exec(req, resp, on_exec);
|
||||
};
|
||||
|
||||
// Resolve callback.
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using redis::adapt;
|
||||
using connection = redis::connection;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
template <class Adapter>
|
||||
auto exec(std::shared_ptr<connection> conn, request const& req, Adapter adapter)
|
||||
template <class Response>
|
||||
auto exec(std::shared_ptr<connection> conn, request const& req, Response& resp)
|
||||
{
|
||||
net::dispatch(
|
||||
conn->get_executor(),
|
||||
net::deferred([&]() { return conn->async_exec(req, adapter, net::deferred); }))
|
||||
net::deferred([&]() { return conn->async_exec(req, resp, net::deferred); }))
|
||||
(net::use_future).get();
|
||||
}
|
||||
|
||||
@@ -67,10 +66,10 @@ auto main(int argc, char * argv[]) -> int
|
||||
req.push("PING");
|
||||
req.push("QUIT");
|
||||
|
||||
response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
|
||||
response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
|
||||
|
||||
// Executes commands synchronously.
|
||||
exec(conn, req, adapt(resp));
|
||||
exec(conn, req, resp);
|
||||
|
||||
std::cout << "Response: " << std::get<1>(resp) << std::endl;
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace net = boost::asio;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using stream_descriptor = net::use_awaitable_t<>::as_default_on_t<net::posix::stream_descriptor>;
|
||||
using signal_set = net::use_awaitable_t<>::as_default_on_t<net::signal_set>;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::generic_response;
|
||||
|
||||
@@ -29,7 +28,7 @@ using boost::redis::generic_response;
|
||||
auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
{
|
||||
for (generic_response resp;;) {
|
||||
co_await conn->async_receive(adapt(resp));
|
||||
co_await conn->async_receive(resp);
|
||||
std::cout << resp.at(1).value << " " << resp.at(2).value << " " << resp.at(3).value << std::endl;
|
||||
resp.clear();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
namespace net = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
@@ -63,10 +62,10 @@ auto hgetall(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
req.push("HGETALL", "hset-key");
|
||||
|
||||
// Responses as tuple elements.
|
||||
response<redis::ignore, std::map<std::string, std::string>> resp;
|
||||
response<redis::ignore_t, std::map<std::string, std::string>> resp;
|
||||
|
||||
// Executes the request and reads the response.
|
||||
co_await conn->async_exec(req, adapt(resp));
|
||||
co_await conn->async_exec(req, resp);
|
||||
|
||||
print(std::get<1>(resp));
|
||||
}
|
||||
@@ -82,14 +81,14 @@ auto transaction(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
req.push("EXEC");
|
||||
|
||||
response<
|
||||
redis::ignore, // hello
|
||||
redis::ignore, // multi
|
||||
redis::ignore, // lrange
|
||||
redis::ignore, // hgetall
|
||||
redis::ignore_t, // hello
|
||||
redis::ignore_t, // multi
|
||||
redis::ignore_t, // lrange
|
||||
redis::ignore_t, // hgetall
|
||||
response<std::optional<std::vector<int>>, std::optional<std::map<std::string, std::string>>> // exec
|
||||
> resp;
|
||||
|
||||
co_await conn->async_exec(req, adapt(resp));
|
||||
co_await conn->async_exec(req, resp);
|
||||
|
||||
print(std::get<0>(std::get<4>(resp)).value());
|
||||
print(std::get<1>(std::get<4>(resp)).value());
|
||||
|
||||
@@ -15,22 +15,20 @@ using namespace net::experimental::awaitable_operators;
|
||||
using tcp_socket = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::socket>;
|
||||
using tcp_acceptor = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::acceptor>;
|
||||
using signal_set = net::use_awaitable_t<>::as_default_on_t<net::signal_set>;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
auto echo_server_session(tcp_socket socket, std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
{
|
||||
request req;
|
||||
std::string resp;
|
||||
response<std::string> resp;
|
||||
|
||||
for (std::string buffer;;) {
|
||||
auto n = co_await net::async_read_until(socket, net::dynamic_buffer(buffer, 1024), "\n");
|
||||
req.push("PING", buffer);
|
||||
auto tmp = std::tie(resp);
|
||||
co_await conn->async_exec(req, adapt(tmp));
|
||||
co_await net::async_write(socket, net::buffer(resp));
|
||||
resp.clear();
|
||||
co_await conn->async_exec(req, resp);
|
||||
co_await net::async_write(socket, net::buffer(std::get<0>(resp)));
|
||||
std::get<0>(resp).clear();
|
||||
req.clear();
|
||||
buffer.erase(0, n);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "common/common.hpp"
|
||||
|
||||
namespace net = boost::asio;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::operation;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
@@ -35,7 +34,7 @@ auto ping(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
req.push("PING", "Hello world");
|
||||
|
||||
response<std::string> resp;
|
||||
co_await conn->async_exec(req, adapt(resp));
|
||||
co_await conn->async_exec(req, resp);
|
||||
|
||||
std::cout << "PING: " << std::get<0>(resp) << std::endl;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
@@ -24,11 +23,11 @@ auto co_main(std::string host, std::string port) -> net::awaitable<void>
|
||||
req.push("PING", "Hello world");
|
||||
req.push("QUIT");
|
||||
|
||||
response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
|
||||
response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
|
||||
|
||||
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
|
||||
co_await connect(conn, host, port);
|
||||
co_await (conn->async_run() || conn->async_exec(req, adapt(resp)));
|
||||
co_await (conn->async_run() || conn->async_exec(req, resp));
|
||||
|
||||
std::cout << "PING: " << std::get<1>(resp) << std::endl;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace net = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using resolver = net::use_awaitable_t<>::as_default_on_t<net::ip::tcp::resolver>;
|
||||
using redis::adapt;
|
||||
using connection = net::use_awaitable_t<>::as_default_on_t<redis::ssl::connection>;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
@@ -38,7 +37,7 @@ net::awaitable<void> co_main(std::string, std::string)
|
||||
req.push("PING");
|
||||
req.push("QUIT");
|
||||
|
||||
response<redis::ignore, std::string, redis::ignore> resp;
|
||||
response<redis::ignore_t, std::string, redis::ignore_t> resp;
|
||||
|
||||
// Resolve
|
||||
auto ex = co_await net::this_coro::executor;
|
||||
@@ -52,7 +51,7 @@ net::awaitable<void> co_main(std::string, std::string)
|
||||
|
||||
co_await net::async_connect(conn.lowest_layer(), endpoints);
|
||||
co_await conn.next_layer().async_handshake(net::ssl::stream_base::client);
|
||||
co_await (conn.async_run() || conn.async_exec(req, adapt(resp)));
|
||||
co_await (conn.async_run() || conn.async_exec(req, resp));
|
||||
|
||||
std::cout << "Response: " << std::get<1>(resp) << std::endl;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
namespace net = boost::asio;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using endpoints = net::ip::tcp::resolver::results_type;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
@@ -37,11 +36,11 @@ auto resolve_master_address(std::vector<address> const& endpoints) -> net::await
|
||||
|
||||
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
|
||||
|
||||
response<std::optional<std::array<std::string, 2>>, boost::redis::ignore> addr;
|
||||
response<std::optional<std::array<std::string, 2>>, boost::redis::ignore_t> addr;
|
||||
for (auto ep : endpoints) {
|
||||
boost::system::error_code ec;
|
||||
co_await connect(conn, ep.host, ep.port);
|
||||
co_await (conn->async_run() && conn->async_exec(req, adapt(addr), redir(ec)));
|
||||
co_await (conn->async_run() && conn->async_exec(req, addr, redir(ec)));
|
||||
conn->reset_stream();
|
||||
if (std::get<0>(addr))
|
||||
co_return address{std::get<0>(addr).value().at(0), std::get<0>(addr).value().at(1)};
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace net = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using namespace boost::json;
|
||||
using redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
@@ -99,12 +98,12 @@ net::awaitable<void> co_main(std::string host, std::string port)
|
||||
req.push("SMEMBERS", "sadd-key"); // Retrieves
|
||||
req.push("QUIT");
|
||||
|
||||
response<redis::ignore, int, std::set<user>, std::string> resp;
|
||||
response<redis::ignore_t, int, std::set<user>, std::string> resp;
|
||||
|
||||
auto conn = std::make_shared<connection>(co_await net::this_coro::executor);
|
||||
|
||||
co_await connect(conn, host, port);
|
||||
co_await (conn->async_run() || conn->async_exec(req, adapt(resp)));
|
||||
co_await (conn->async_run() || conn->async_exec(req, resp));
|
||||
|
||||
for (auto const& e: std::get<2>(resp))
|
||||
std::cout << e << "\n";
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
namespace net = boost::asio;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using steady_timer = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::generic_response;
|
||||
|
||||
@@ -38,7 +37,7 @@ using boost::redis::generic_response;
|
||||
auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
{
|
||||
for (generic_response resp;;) {
|
||||
co_await conn->async_receive(adapt(resp));
|
||||
co_await conn->async_receive(resp);
|
||||
std::cout << resp.at(1).value << " " << resp.at(2).value << " " << resp.at(3).value << std::endl;
|
||||
resp.clear();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define BOOST_REDIS_HPP
|
||||
|
||||
#include <boost/redis/error.hpp>
|
||||
#include <boost/redis/adapt.hpp>
|
||||
#include <boost/redis/connection.hpp>
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
|
||||
@@ -31,9 +31,9 @@ using adapter_t = typename detail::adapter_t<T>;
|
||||
|
||||
// Ignores all responses except for the response to ping.
|
||||
std::string buffer;
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt()); // hello
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt(resp)); // ping
|
||||
resp3::read(socket, dynamic_buffer(buffer, adapt())); // quit
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt2()); // hello
|
||||
resp3::read(socket, dynamic_buffer(buffer), adapt2(resp)); // ping
|
||||
resp3::read(socket, dynamic_buffer(buffer, adapt2())); // quit
|
||||
@endcode
|
||||
*/
|
||||
inline
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace boost::redis::adapter::detail {
|
||||
|
||||
using ignore = std::decay_t<decltype(std::ignore)>;
|
||||
using ignore_t = std::decay_t<decltype(std::ignore)>;
|
||||
|
||||
/* Traits class for response objects.
|
||||
*
|
||||
@@ -34,8 +34,8 @@ struct response_traits {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct response_traits<ignore> {
|
||||
using response_type = ignore;
|
||||
struct response_traits<ignore_t> {
|
||||
using response_type = ignore_t;
|
||||
using adapter_type = resp3::detail::ignore_response;
|
||||
static auto adapt(response_type) noexcept { return adapter_type{}; }
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define BOOST_REDIS_CONNECTION_HPP
|
||||
|
||||
#include <boost/redis/detail/connection_base.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <chrono>
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
* automatically queued by the implementation.
|
||||
*
|
||||
* @param req Request object.
|
||||
* @param adapter Response adapter.
|
||||
* @param response Response object.
|
||||
* @param token Asio completion token.
|
||||
*
|
||||
* For an example see cpp20_echo_server.cpp. The completion token must
|
||||
@@ -126,14 +127,14 @@ public:
|
||||
* bytes.
|
||||
*/
|
||||
template <
|
||||
class Adapter = detail::response_traits<void>::adapter_type,
|
||||
class Response = ignore_t,
|
||||
class CompletionToken = asio::default_completion_token_t<executor_type>>
|
||||
auto async_exec(
|
||||
request const& req,
|
||||
Adapter adapter = adapt(),
|
||||
Response& response = ignore,
|
||||
CompletionToken token = CompletionToken{})
|
||||
{
|
||||
return base_type::async_exec(req, adapter, std::move(token));
|
||||
return base_type::async_exec(req, response, std::move(token));
|
||||
}
|
||||
|
||||
/** @brief Receives server side pushes asynchronously.
|
||||
@@ -142,7 +143,7 @@ public:
|
||||
* loop. If a push arrives and there is no reader, the connection
|
||||
* will hang.
|
||||
*
|
||||
* @param adapter The response adapter.
|
||||
* @param response The response object.
|
||||
* @param token The Asio completion token.
|
||||
*
|
||||
* For an example see cpp20_subscriber.cpp. The completion token must
|
||||
@@ -156,13 +157,13 @@ public:
|
||||
* bytes.
|
||||
*/
|
||||
template <
|
||||
class Adapter = detail::response_traits<void>::adapter_type,
|
||||
class Response = ignore_t,
|
||||
class CompletionToken = asio::default_completion_token_t<executor_type>>
|
||||
auto async_receive(
|
||||
Adapter adapter = adapt(),
|
||||
Response& response = ignore,
|
||||
CompletionToken token = CompletionToken{})
|
||||
{
|
||||
return base_type::async_receive(adapter, std::move(token));
|
||||
return base_type::async_receive(response, std::move(token));
|
||||
}
|
||||
|
||||
/** @brief Cancel operations.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* accompanying file LICENSE.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_REDIS_ADAPT_HPP
|
||||
#define BOOST_REDIS_ADAPT_HPP
|
||||
#ifndef BOOST_REDIS_DETAIL_ADAPT_HPP
|
||||
#define BOOST_REDIS_DETAIL_ADAPT_HPP
|
||||
|
||||
#include <boost/redis/resp3/node.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
@@ -19,23 +19,7 @@
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
namespace boost::redis {
|
||||
|
||||
/** @brief Tag used to ignore responses.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* For example
|
||||
*
|
||||
* @code
|
||||
* response<boost::redis::ignore, std::string, boost::redis::ignore> resp;
|
||||
* @endcode
|
||||
*
|
||||
* will cause only the second tuple type to be parsed, the others
|
||||
* will be ignored.
|
||||
*/
|
||||
using ignore = adapter::detail::ignore;
|
||||
|
||||
namespace detail
|
||||
namespace boost::redis::detail
|
||||
{
|
||||
|
||||
class ignore_adapter {
|
||||
@@ -112,11 +96,11 @@ template <class>
|
||||
struct response_traits;
|
||||
|
||||
template <>
|
||||
struct response_traits<void> {
|
||||
struct response_traits<ignore_t> {
|
||||
using response_type = void;
|
||||
using adapter_type = detail::ignore_adapter;
|
||||
|
||||
static auto adapt() noexcept
|
||||
static auto adapt(ignore_t&) noexcept
|
||||
{ return detail::ignore_adapter{}; }
|
||||
};
|
||||
|
||||
@@ -160,21 +144,7 @@ auto make_adapter_wrapper(Adapter adapter)
|
||||
return wrapper{adapter};
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** @brief Creates an adapter that ignores responses.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* This function can be used to create adapters that ignores
|
||||
* responses.
|
||||
*/
|
||||
inline auto adapt() noexcept
|
||||
{
|
||||
return detail::response_traits<void>::adapt();
|
||||
}
|
||||
|
||||
/** @brief Adapts a type to be used as a response.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* The type T must be either
|
||||
*
|
||||
@@ -187,11 +157,11 @@ inline auto adapt() noexcept
|
||||
* @param t Tuple containing the responses.
|
||||
*/
|
||||
template<class T>
|
||||
auto adapt(T& t) noexcept
|
||||
auto boost_redis_adapt(T& t) noexcept
|
||||
{
|
||||
return detail::response_traits<T>::adapt(t);
|
||||
}
|
||||
|
||||
} // boost::redis
|
||||
} // boost::redis::detail
|
||||
|
||||
#endif // BOOST_REDIS_ADAPT_HPP
|
||||
#endif // BOOST_REDIS_DETAIL_ADAPT_HPP
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef BOOST_REDIS_CONNECTION_BASE_HPP
|
||||
#define BOOST_REDIS_CONNECTION_BASE_HPP
|
||||
|
||||
#include <boost/redis/adapt.hpp>
|
||||
#include <boost/redis/detail/adapt.hpp>
|
||||
#include <boost/redis/operation.hpp>
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/detail/connection_ops.hpp>
|
||||
@@ -128,20 +128,24 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class Adapter, class CompletionToken>
|
||||
auto async_exec(request const& req, Adapter adapter, CompletionToken token)
|
||||
template <class Response, class CompletionToken>
|
||||
auto async_exec(request const& req, Response& resp, CompletionToken token)
|
||||
{
|
||||
using namespace boost::redis;
|
||||
auto adapter = boost_redis_adapt(resp);
|
||||
BOOST_ASSERT_MSG(req.size() <= adapter.get_supported_response_size(), "Request and response have incompatible sizes.");
|
||||
|
||||
return asio::async_compose
|
||||
< CompletionToken
|
||||
, void(system::error_code, std::size_t)
|
||||
>(detail::exec_op<Derived, Adapter>{&derived(), &req, adapter}, token, writer_timer_);
|
||||
>(detail::exec_op<Derived, decltype(adapter)>{&derived(), &req, adapter}, token, writer_timer_);
|
||||
}
|
||||
|
||||
template <class Adapter, class CompletionToken>
|
||||
auto async_receive(Adapter adapter, CompletionToken token)
|
||||
template <class Response, class CompletionToken>
|
||||
auto async_receive(Response& response, CompletionToken token)
|
||||
{
|
||||
using namespace boost::redis;
|
||||
auto adapter = boost_redis_adapt(response);
|
||||
auto f = detail::make_adapter_wrapper(adapter);
|
||||
|
||||
return asio::async_compose
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef BOOST_REDIS_CONNECTION_OPS_HPP
|
||||
#define BOOST_REDIS_CONNECTION_OPS_HPP
|
||||
|
||||
#include <boost/redis/adapt.hpp>
|
||||
#include <boost/redis/detail/adapt.hpp>
|
||||
#include <boost/redis/error.hpp>
|
||||
#include <boost/redis/resp3/type.hpp>
|
||||
#include <boost/redis/resp3/detail/parser.hpp>
|
||||
|
||||
12
include/boost/redis/impl/response.ipp
Normal file
12
include/boost/redis/impl/response.ipp
Normal file
@@ -0,0 +1,12 @@
|
||||
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE.txt)
|
||||
*/
|
||||
|
||||
#include <boost/redis/response.hpp>
|
||||
|
||||
namespace boost::redis
|
||||
{
|
||||
ignore_t ignore;
|
||||
}
|
||||
@@ -16,31 +16,13 @@ namespace boost::redis::resp3 {
|
||||
*
|
||||
* RESP3 can contain recursive data structures: A map of sets of
|
||||
* vector of etc. As it is parsed each element is passed to user
|
||||
* callbacks (push parser), the `boost::redis::adapt` function. The signature of this
|
||||
* callbacks (push parser). The signature of this
|
||||
* callback is `f(resp3::node<std::string_view)`. This class is called a node
|
||||
* because it can be seen as the element of the response tree. It
|
||||
* is a template so that users can use it with owing strings e.g.
|
||||
* `std::string` or `boost::static_string` etc. if they decide to use a node as
|
||||
* response type, for example, to read a non-aggregate data-type use
|
||||
* `std::string` or `boost::static_string` etc.
|
||||
*
|
||||
* ```cpp
|
||||
* resp3::node<std::string> resp;
|
||||
* co_await conn->async_exec(req, adapt(resp));
|
||||
* ```
|
||||
*
|
||||
* for an aggregate use instead
|
||||
*
|
||||
* ```cpp
|
||||
* std::vector<resp3::node<std::string>> resp; co_await
|
||||
* conn->async_exec(req, adapt(resp));
|
||||
* ```
|
||||
*
|
||||
* The vector will contain the
|
||||
* [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
|
||||
* view of the response tree. Any Redis response can be received in
|
||||
* an array of nodes as shown above.
|
||||
*
|
||||
* \tparam String A `std::string`-like type.
|
||||
* @tparam String A `std::string`-like type.
|
||||
*/
|
||||
template <class String>
|
||||
struct node {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define BOOST_REDIS_RESPONSE_HPP
|
||||
|
||||
#include <boost/redis/resp3/node.hpp>
|
||||
#include <boost/redis/adapter/adapt.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -23,9 +24,39 @@ using response = std::tuple<Ts...>;
|
||||
|
||||
/** @brief A generic response to a request
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* It contains the
|
||||
* [pre-order](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order,_NLR)
|
||||
* view of the response tree. Any Redis response can be received in
|
||||
* an array of nodes.
|
||||
*/
|
||||
using generic_response = std::vector<resp3::node<std::string>>;
|
||||
|
||||
/** @brief Type used to ignore responses.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* For example
|
||||
*
|
||||
* @code
|
||||
* response<boost::redis::ignore_t, std::string, boost::redis::ignore_t> resp;
|
||||
* @endcode
|
||||
*
|
||||
* will cause only the second tuple type to be parsed, the others
|
||||
* will be ignored.
|
||||
*/
|
||||
using ignore_t = adapter::detail::ignore_t;
|
||||
|
||||
/** @brief Global ignore object.
|
||||
* @ingroup high-level-api
|
||||
*
|
||||
* Can be used to ignore responses to a request
|
||||
*
|
||||
* @code
|
||||
* conn->async_exec(req, ignore, ...);
|
||||
* @endcode
|
||||
*/
|
||||
extern ignore_t ignore;
|
||||
|
||||
} // boost::redis::resp3
|
||||
|
||||
#endif // BOOST_REDIS_RESPONSE_HPP
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
|
||||
#include <boost/redis/impl/error.ipp>
|
||||
#include <boost/redis/impl/request.ipp>
|
||||
#include <boost/redis/impl/response.ipp>
|
||||
#include <boost/redis/resp3/impl/type.ipp>
|
||||
#include <boost/redis/resp3/detail/impl/parser.ipp>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define BOOST_REDIS_SSL_CONNECTION_HPP
|
||||
|
||||
#include <boost/redis/detail/connection_base.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <chrono>
|
||||
@@ -93,14 +94,14 @@ public:
|
||||
* See redis::connection::async_exec for more information.
|
||||
*/
|
||||
template <
|
||||
class Adapter = redis::detail::response_traits<void>::adapter_type,
|
||||
class Response = ignore_t,
|
||||
class CompletionToken = asio::default_completion_token_t<executor_type>>
|
||||
auto async_exec(
|
||||
request const& req,
|
||||
Adapter adapter = adapt(),
|
||||
Response& response = ignore,
|
||||
CompletionToken token = CompletionToken{})
|
||||
{
|
||||
return base_type::async_exec(req, adapter, std::move(token));
|
||||
return base_type::async_exec(req, response, std::move(token));
|
||||
}
|
||||
|
||||
/** @brief Receives server side pushes asynchronously.
|
||||
@@ -108,13 +109,13 @@ public:
|
||||
* See redis::connection::async_receive for detailed information.
|
||||
*/
|
||||
template <
|
||||
class Adapter = redis::detail::response_traits<void>::adapter_type,
|
||||
class Response = ignore_t,
|
||||
class CompletionToken = asio::default_completion_token_t<executor_type>>
|
||||
auto async_receive(
|
||||
Adapter adapter = adapt(),
|
||||
Response& response = ignore,
|
||||
CompletionToken token = CompletionToken{})
|
||||
{
|
||||
return base_type::async_receive(adapter, std::move(token));
|
||||
return base_type::async_receive(response, std::move(token));
|
||||
}
|
||||
|
||||
/** @brief Cancel operations.
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
namespace net = boost::asio;
|
||||
using error_code = boost::system::error_code;
|
||||
using boost::redis::operation;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
auto push_consumer(std::shared_ptr<connection> conn, int expected) -> net::awaitable<void>
|
||||
{
|
||||
int c = 0;
|
||||
for (;;) {
|
||||
co_await conn->async_receive(adapt(), net::use_awaitable);
|
||||
co_await conn->async_receive(ignore, net::use_awaitable);
|
||||
if (++c == expected)
|
||||
break;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ auto push_consumer(std::shared_ptr<connection> conn, int expected) -> net::await
|
||||
request req;
|
||||
req.push("HELLO", 3);
|
||||
req.push("QUIT");
|
||||
co_await conn->async_exec(req, adapt());
|
||||
co_await conn->async_exec(req, ignore);
|
||||
}
|
||||
|
||||
auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> net::awaitable<void>
|
||||
@@ -42,7 +42,7 @@ auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> ne
|
||||
auto ex = co_await net::this_coro::executor;
|
||||
|
||||
request req;
|
||||
response<boost::redis::ignore, std::string> resp;
|
||||
response<boost::redis::ignore_t, std::string> resp;
|
||||
|
||||
for (auto i = 0; i < n; ++i) {
|
||||
auto const msg = id + "/" + std::to_string(i);
|
||||
@@ -51,7 +51,7 @@ auto echo_session(std::shared_ptr<connection> conn, std::string id, int n) -> ne
|
||||
req.push("PING", msg);
|
||||
req.push("SUBSCRIBE", "channel");
|
||||
boost::system::error_code ec;
|
||||
co_await conn->async_exec(req, adapt(resp), redir(ec));
|
||||
co_await conn->async_exec(req, resp, redir(ec));
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::error_code{});
|
||||
BOOST_CHECK_EQUAL(msg, std::get<1>(resp));
|
||||
req.clear();
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
namespace net = boost::asio;
|
||||
using error_code = boost::system::error_code;
|
||||
using connection = boost::redis::connection;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hello_priority)
|
||||
{
|
||||
@@ -55,21 +55,21 @@ BOOST_AUTO_TEST_CASE(hello_priority)
|
||||
bool seen2 = false;
|
||||
bool seen3 = false;
|
||||
|
||||
conn.async_exec(req1, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [&](auto ec, auto){
|
||||
std::cout << "bbb" << std::endl;
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST(!seen2);
|
||||
BOOST_TEST(seen3);
|
||||
seen1 = true;
|
||||
});
|
||||
conn.async_exec(req2, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req2, ignore, [&](auto ec, auto){
|
||||
std::cout << "ccc" << std::endl;
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST(seen1);
|
||||
BOOST_TEST(seen3);
|
||||
seen2 = true;
|
||||
});
|
||||
conn.async_exec(req3, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req3, ignore, [&](auto ec, auto){
|
||||
std::cout << "ddd" << std::endl;
|
||||
BOOST_TEST(!ec);
|
||||
BOOST_TEST(!seen1);
|
||||
@@ -91,14 +91,14 @@ BOOST_AUTO_TEST_CASE(wrong_response_data_type)
|
||||
req.push("QUIT");
|
||||
|
||||
// Wrong data type.
|
||||
response<boost::redis::ignore, int> resp;
|
||||
response<boost::redis::ignore_t, int> resp;
|
||||
net::io_context ioc;
|
||||
|
||||
auto const endpoints = resolve();
|
||||
connection conn{ioc};
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
conn.async_exec(req, adapt(resp), [](auto ec, auto){
|
||||
conn.async_exec(req, resp, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::redis::error::not_a_number);
|
||||
});
|
||||
conn.async_run([](auto ec){
|
||||
@@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(cancel_request_if_not_connected)
|
||||
|
||||
net::io_context ioc;
|
||||
auto conn = std::make_shared<connection>(ioc);
|
||||
conn->async_exec(req, adapt(), [](auto ec, auto){
|
||||
conn->async_exec(req, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::redis::error::not_connected);
|
||||
});
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace net = boost::asio;
|
||||
using error_code = boost::system::error_code;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using boost::redis::operation;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
{
|
||||
@@ -47,14 +47,14 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
request req0;
|
||||
req0.get_config().coalesce = false;
|
||||
req0.push("HELLO", 3);
|
||||
std::ignore = co_await conn->async_exec(req0, adapt(), net::use_awaitable);
|
||||
std::ignore = co_await conn->async_exec(req0, ignore, net::use_awaitable);
|
||||
|
||||
request req1;
|
||||
req1.get_config().coalesce = false;
|
||||
req1.push("BLPOP", "any", 3);
|
||||
|
||||
// Should not be canceled.
|
||||
conn->async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn->async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
@@ -63,7 +63,7 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
req2.push("PING", "second");
|
||||
|
||||
// Should be canceled.
|
||||
conn->async_exec(req2, adapt(), [](auto ec, auto){
|
||||
conn->async_exec(req2, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, net::error::basic_errors::operation_aborted);
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ auto async_ignore_explicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
|
||||
// Test whether the connection remains usable after a call to
|
||||
// cancel(exec).
|
||||
co_await conn->async_exec(req3, adapt(), net::redirect_error(net::use_awaitable, ec1));
|
||||
co_await conn->async_exec(req3, ignore, net::redirect_error(net::use_awaitable, ec1));
|
||||
|
||||
BOOST_TEST(!ec1);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ auto ignore_implicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
request req0;
|
||||
req0.get_config().coalesce = false;
|
||||
req0.push("HELLO", 3);
|
||||
std::ignore = co_await conn->async_exec(req0, adapt(), net::use_awaitable);
|
||||
std::ignore = co_await conn->async_exec(req0, ignore, net::use_awaitable);
|
||||
|
||||
// Will be cancelled after it has been written but before the
|
||||
// response arrives.
|
||||
@@ -119,8 +119,8 @@ auto ignore_implicit_cancel_of_req_written() -> net::awaitable<void>
|
||||
|
||||
boost::system::error_code ec1, ec2, ec3;
|
||||
co_await (
|
||||
conn->async_exec(req1, adapt(), redir(ec1)) ||
|
||||
conn->async_exec(req2, adapt(), redir(ec2)) ||
|
||||
conn->async_exec(req1, ignore, redir(ec1)) ||
|
||||
conn->async_exec(req2, ignore, redir(ec2)) ||
|
||||
st.async_wait(redir(ec3))
|
||||
);
|
||||
|
||||
@@ -149,8 +149,8 @@ auto cancel_of_req_written_on_run_canceled() -> net::awaitable<void>
|
||||
|
||||
boost::system::error_code ec0, ec1, ec2, ec3;
|
||||
co_await (
|
||||
conn->async_exec(req0, adapt(), redir(ec0)) &&
|
||||
(conn->async_exec(req1, adapt(), redir(ec1)) ||
|
||||
conn->async_exec(req0, ignore, redir(ec0)) &&
|
||||
(conn->async_exec(req1, ignore, redir(ec1)) ||
|
||||
conn->async_run(redir(ec2)) ||
|
||||
st.async_wait(redir(ec3)))
|
||||
);
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
namespace net = boost::asio;
|
||||
using error_code = boost::system::error_code;
|
||||
using connection = boost::redis::connection;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(request_retry_false)
|
||||
{
|
||||
@@ -58,15 +58,15 @@ BOOST_AUTO_TEST_CASE(request_retry_false)
|
||||
auto const endpoints = resolve();
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
conn.async_exec(req0, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req0, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
|
||||
conn.async_exec(req2, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req2, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
|
||||
@@ -117,17 +117,17 @@ BOOST_AUTO_TEST_CASE(request_retry_true)
|
||||
auto const endpoints = resolve();
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
conn.async_exec(req0, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req0, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
|
||||
conn.async_exec(req2, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req2, ignore, [&](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
conn.async_exec(req3, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req3, ignore, [&](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
namespace net = boost::asio;
|
||||
namespace resp3 = boost::redis::resp3;
|
||||
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::operation;
|
||||
using connection = boost::redis::connection;
|
||||
using error_code = boost::system::error_code;
|
||||
using net::experimental::as_tuple;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(push_filtered_out)
|
||||
{
|
||||
@@ -41,12 +41,12 @@ BOOST_AUTO_TEST_CASE(push_filtered_out)
|
||||
req.push("SUBSCRIBE", "channel");
|
||||
req.push("QUIT");
|
||||
|
||||
response<boost::redis::ignore, std::string, std::string> resp;
|
||||
conn.async_exec(req, adapt(resp), [](auto ec, auto){
|
||||
response<boost::redis::ignore_t, std::string, std::string> resp;
|
||||
conn.async_exec(req, resp, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
conn.async_receive(adapt(), [](auto ec, auto){
|
||||
conn.async_receive(ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ void receive_wrong_syntax(request const& req)
|
||||
connection conn{ioc};
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
conn.async_exec(req, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ void receive_wrong_syntax(request const& req)
|
||||
BOOST_CHECK_EQUAL(ec, boost::asio::error::basic_errors::operation_aborted);
|
||||
});
|
||||
|
||||
conn.async_receive(adapt(), [&](auto ec, auto){
|
||||
conn.async_receive(ignore, [&](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
conn.cancel(boost::redis::operation::run);
|
||||
});
|
||||
@@ -87,19 +87,22 @@ void receive_wrong_syntax(request const& req)
|
||||
net::awaitable<void> push_consumer1(connection& conn, bool& push_received)
|
||||
{
|
||||
{
|
||||
auto [ec, ev] = co_await conn.async_receive(adapt(), as_tuple(net::use_awaitable));
|
||||
auto [ec, ev] = co_await conn.async_receive(ignore, as_tuple(net::use_awaitable));
|
||||
BOOST_TEST(!ec);
|
||||
}
|
||||
|
||||
{
|
||||
auto [ec, ev] = co_await conn.async_receive(adapt(), as_tuple(net::use_awaitable));
|
||||
auto [ec, ev] = co_await conn.async_receive(ignore, as_tuple(net::use_awaitable));
|
||||
BOOST_CHECK_EQUAL(ec, net::experimental::channel_errc::channel_cancelled);
|
||||
}
|
||||
|
||||
push_received = true;
|
||||
}
|
||||
|
||||
struct adapter_error {
|
||||
struct response_error_tag{};
|
||||
response_error_tag error_tag_obj;
|
||||
|
||||
struct response_error_adapter {
|
||||
void
|
||||
operator()(
|
||||
std::size_t, boost::redis::resp3::node<std::string_view> const&, boost::system::error_code& ec)
|
||||
@@ -112,6 +115,11 @@ struct adapter_error {
|
||||
{ return static_cast<std::size_t>(-1);}
|
||||
};
|
||||
|
||||
auto boost_redis_adapt(response_error_tag&)
|
||||
{
|
||||
return response_error_adapter{};
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_push_adapter)
|
||||
{
|
||||
net::io_context ioc;
|
||||
@@ -125,11 +133,11 @@ BOOST_AUTO_TEST_CASE(test_push_adapter)
|
||||
req.push("SUBSCRIBE", "channel");
|
||||
req.push("PING");
|
||||
|
||||
conn.async_receive(adapter_error{}, [](auto ec, auto) {
|
||||
conn.async_receive(error_tag_obj, [](auto ec, auto) {
|
||||
BOOST_CHECK_EQUAL(ec, boost::redis::error::incompatible_size);
|
||||
});
|
||||
|
||||
conn.async_exec(req, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, net::experimental::error::channel_errors::channel_cancelled);
|
||||
});
|
||||
|
||||
@@ -156,7 +164,7 @@ void test_push_is_received1(bool coalesce)
|
||||
req.push("SUBSCRIBE", "channel");
|
||||
req.push("QUIT");
|
||||
|
||||
conn.async_exec(req, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
@@ -201,9 +209,9 @@ void test_push_is_received2(bool coalesce)
|
||||
BOOST_TEST(!ec);
|
||||
};
|
||||
|
||||
conn.async_exec(req1, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req3, adapt(), handler);
|
||||
conn.async_exec(req1, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req3, ignore, handler);
|
||||
|
||||
conn.async_run([&](auto ec) {
|
||||
BOOST_TEST(!ec);
|
||||
@@ -224,7 +232,7 @@ void test_push_is_received2(bool coalesce)
|
||||
net::awaitable<void> push_consumer3(connection& conn)
|
||||
{
|
||||
for (;;)
|
||||
co_await conn.async_receive(adapt(), net::use_awaitable);
|
||||
co_await conn.async_receive(ignore, net::use_awaitable);
|
||||
}
|
||||
|
||||
// Test many subscribe requests.
|
||||
@@ -252,18 +260,18 @@ void test_push_many_subscribes(bool coalesce)
|
||||
connection conn{ioc};
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
conn.async_exec(req0, adapt(), handler);
|
||||
conn.async_exec(req1, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req1, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req1, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req1, adapt(), handler);
|
||||
conn.async_exec(req2, adapt(), handler);
|
||||
conn.async_exec(req3, adapt(), handler);
|
||||
conn.async_exec(req0, ignore, handler);
|
||||
conn.async_exec(req1, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req1, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req1, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req1, ignore, handler);
|
||||
conn.async_exec(req2, ignore, handler);
|
||||
conn.async_exec(req3, ignore, handler);
|
||||
|
||||
conn.async_run([&](auto ec) {
|
||||
BOOST_TEST(!ec);
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
|
||||
using boost::redis::adapt;
|
||||
using connection = boost::redis::connection;
|
||||
using error_code = boost::system::error_code;
|
||||
using operation = boost::redis::operation;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
// Test if quit causes async_run to exit.
|
||||
BOOST_AUTO_TEST_CASE(test_quit_no_coalesce)
|
||||
@@ -43,19 +43,19 @@ BOOST_AUTO_TEST_CASE(test_quit_no_coalesce)
|
||||
req2.get_config().coalesce = false;
|
||||
req2.push("QUIT");
|
||||
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
conn.async_exec(req2, adapt(), [](auto ec, auto) {
|
||||
conn.async_exec(req2, ignore, [](auto ec, auto) {
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ void test_quit2(bool coalesce)
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
|
||||
|
||||
conn.async_exec(req, adapt(), [](auto ec, auto) {
|
||||
conn.async_exec(req, ignore, [](auto ec, auto) {
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
|
||||
using boost::redis::adapt;
|
||||
using connection = boost::redis::connection;
|
||||
using error_code = boost::system::error_code;
|
||||
using operation = boost::redis::operation;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_quit_coalesce)
|
||||
{
|
||||
@@ -37,16 +37,16 @@ BOOST_AUTO_TEST_CASE(test_quit_coalesce)
|
||||
request req2{{false, true}};
|
||||
req2.push("QUIT");
|
||||
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
conn.async_exec(req2, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req2, ignore, [](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
|
||||
});
|
||||
conn.async_exec(req1, adapt(), [](auto ec, auto){
|
||||
conn.async_exec(req1, ignore, [](auto ec, auto){
|
||||
BOOST_CHECK_EQUAL(ec, boost::system::errc::errc_t::operation_canceled);
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
#include "../examples/common/common.hpp"
|
||||
|
||||
namespace net = boost::asio;
|
||||
using boost::redis::adapt;
|
||||
using error_code = boost::system::error_code;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
#include <boost/asio/experimental/awaitable_operators.hpp>
|
||||
using namespace boost::asio::experimental::awaitable_operators;
|
||||
@@ -40,7 +40,7 @@ net::awaitable<void> test_reconnect_impl()
|
||||
boost::system::error_code ec1, ec2;
|
||||
net::connect(conn.next_layer(), endpoints);
|
||||
co_await (
|
||||
conn.async_exec(req, adapt(), net::redirect_error(net::use_awaitable, ec1)) &&
|
||||
conn.async_exec(req, ignore, net::redirect_error(net::use_awaitable, ec1)) &&
|
||||
conn.async_run(net::redirect_error(net::use_awaitable, ec2))
|
||||
);
|
||||
|
||||
@@ -80,7 +80,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
|
||||
co_await connect(conn, "127.0.0.1", "6379");
|
||||
st.expires_after(std::chrono::seconds{1});
|
||||
co_await (
|
||||
conn->async_exec(req1, adapt(), redir(ec1)) ||
|
||||
conn->async_exec(req1, ignore, redir(ec1)) ||
|
||||
conn->async_run(redir(ec2)) ||
|
||||
st.async_wait(redir(ec3))
|
||||
);
|
||||
@@ -99,7 +99,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
|
||||
co_await connect(conn, "127.0.0.1", "6379");
|
||||
st.expires_after(std::chrono::seconds{1});
|
||||
co_await (
|
||||
conn->async_exec(req1, adapt(), net::redirect_error(net::use_awaitable, ec1)) ||
|
||||
conn->async_exec(req1, ignore, net::redirect_error(net::use_awaitable, ec1)) ||
|
||||
conn->async_run(net::redirect_error(net::use_awaitable, ec2)) ||
|
||||
st.async_wait(net::redirect_error(net::use_awaitable, ec3))
|
||||
);
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
namespace net = boost::asio;
|
||||
|
||||
using boost::redis::operation;
|
||||
using boost::redis::adapt;
|
||||
using connection = boost::redis::connection;
|
||||
using error_code = boost::system::error_code;
|
||||
using net::experimental::as_tuple;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
using boost::redis::ignore;
|
||||
|
||||
#include <boost/asio/experimental/awaitable_operators.hpp>
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
@@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(reset_before_run_completes)
|
||||
req.push("HELLO", 3);
|
||||
req.push("PING");
|
||||
|
||||
conn.async_exec(req, adapt(), [&](auto ec, auto){
|
||||
conn.async_exec(req, ignore, [&](auto ec, auto){
|
||||
BOOST_TEST(!ec);
|
||||
conn.reset_stream();
|
||||
});
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
namespace net = boost::asio;
|
||||
|
||||
using boost::redis::adapt;
|
||||
using connection = boost::redis::ssl::connection;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
@@ -58,7 +57,7 @@ BOOST_AUTO_TEST_CASE(ping)
|
||||
net::connect(conn.lowest_layer(), endpoints);
|
||||
conn.next_layer().handshake(net::ssl::stream_base::client);
|
||||
|
||||
conn.async_exec(req, adapt(resp), [](auto ec, auto) {
|
||||
conn.async_exec(req, resp, [](auto ec, auto) {
|
||||
BOOST_TEST(!ec);
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
namespace net = boost::asio;
|
||||
using namespace net::experimental::awaitable_operators;
|
||||
using steady_timer = net::use_awaitable_t<>::as_default_on_t<net::steady_timer>;
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::request;
|
||||
using boost::redis::response;
|
||||
|
||||
@@ -38,8 +37,7 @@ auto periodic_task(std::shared_ptr<connection> conn) -> net::awaitable<void>
|
||||
request req;
|
||||
req.push("GET", "mykey");
|
||||
response<std::string> response;
|
||||
auto [ec, u] = co_await conn->async_exec(req, adapt(response),
|
||||
net::as_tuple(net::use_awaitable));
|
||||
auto [ec, u] = co_await conn->async_exec(req, response, net::as_tuple(net::use_awaitable));
|
||||
if (ec) {
|
||||
std::cout << "Error: " << ec << std::endl;
|
||||
} else {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
namespace std
|
||||
{
|
||||
auto operator==(boost::redis::ignore, boost::redis::ignore) noexcept {return true;}
|
||||
auto operator!=(boost::redis::ignore, boost::redis::ignore) noexcept {return false;}
|
||||
auto operator==(boost::redis::ignore_t, boost::redis::ignore_t) noexcept {return true;}
|
||||
auto operator!=(boost::redis::ignore_t, boost::redis::ignore_t) noexcept {return false;}
|
||||
}
|
||||
|
||||
namespace net = boost::asio;
|
||||
@@ -449,7 +449,7 @@ std::vector<node_type> const attr_e1b
|
||||
test(ex, make_expected(S09a, set_type{"apple", "one", "orange", "three", "two"})); \
|
||||
test(ex, make_expected(S04d, response<uset_type>{set_e1c})); \
|
||||
test(ex, make_expected(S09b, std::vector<node_type>{ {resp3::type::set, 0UL, 0UL, {}} })); \
|
||||
test(ex, make_expected(S10a, boost::redis::ignore{}, boost::redis::error::resp3_simple_error)); \
|
||||
test(ex, make_expected(S10a, boost::redis::ignore, boost::redis::error::resp3_simple_error)); \
|
||||
test(ex, make_expected(S10a, node_type{resp3::type::simple_error, 1UL, 0UL, {"Error"}}, boost::redis::error::resp3_simple_error)); \
|
||||
test(ex, make_expected(S10b, node_type{resp3::type::simple_error, 1UL, 0UL, {""}}, boost::redis::error::resp3_simple_error)); \
|
||||
test(ex, make_expected(S03c, map_type{}));\
|
||||
@@ -460,7 +460,7 @@ std::vector<node_type> const attr_e1b
|
||||
test(ex, make_expected(S11e, double{0}, boost::redis::error::not_a_double));\
|
||||
test(ex, make_expected(S12a, node_type{resp3::type::blob_error, 1UL, 0UL, {"SYNTAX invalid syntax"}}, boost::redis::error::resp3_blob_error));\
|
||||
test(ex, make_expected(S12b, node_type{resp3::type::blob_error, 1UL, 0UL, {}}, boost::redis::error::resp3_blob_error));\
|
||||
test(ex, make_expected(S12c, boost::redis::ignore{}, boost::redis::error::resp3_blob_error));\
|
||||
test(ex, make_expected(S12c, boost::redis::ignore, boost::redis::error::resp3_blob_error));\
|
||||
test(ex, make_expected(S13a, node_type{resp3::type::verbatim_string, 1UL, 0UL, {"txt:Some string"}}));\
|
||||
test(ex, make_expected(S13b, node_type{resp3::type::verbatim_string, 1UL, 0UL, {}}));\
|
||||
test(ex, make_expected(S14a, node_type{resp3::type::big_number, 1UL, 0UL, {"3492890328409238509324850943850943825024385"}}));\
|
||||
@@ -630,7 +630,7 @@ BOOST_AUTO_TEST_CASE(type_convert)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(adapter)
|
||||
{
|
||||
using boost::redis::adapt;
|
||||
using boost::redis::detail::boost_redis_adapt;
|
||||
using resp3::type;
|
||||
|
||||
boost::system::error_code ec;
|
||||
@@ -639,7 +639,7 @@ BOOST_AUTO_TEST_CASE(adapter)
|
||||
int b;
|
||||
auto resp = std::tie(a, b, std::ignore);
|
||||
|
||||
auto f = adapt(resp);
|
||||
auto f = boost_redis_adapt(resp);
|
||||
f(0, resp3::node<std::string_view>{type::simple_string, 1, 0, "Hello"}, ec);
|
||||
f(1, resp3::node<std::string_view>{type::number, 1, 0, "42"}, ec);
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/src.hpp>
|
||||
#include <boost/redis/impl/request.ipp>
|
||||
#include <boost/redis/resp3/impl/type.ipp>
|
||||
|
||||
using boost::redis::request;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user