2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00

Fixup Adds generic_flat_response typedef

This commit is contained in:
Marcelo Zimbres
2025-11-10 23:21:16 +01:00
parent 2c1f1c4c50
commit b365b96228
7 changed files with 131 additions and 15 deletions

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com) /* Copyright (c) 2018-2025 Marcelo Zimbres Silva (mzimbres@gmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. (See * Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
@@ -32,7 +32,7 @@ using boost::asio::dynamic_buffer;
using boost::asio::redirect_error; using boost::asio::redirect_error;
using boost::redis::config; using boost::redis::config;
using boost::redis::connection; using boost::redis::connection;
using boost::redis::resp3::flat_tree; using boost::redis::generic_flat_response;
using boost::redis::request; using boost::redis::request;
using boost::system::error_code; using boost::system::error_code;
using namespace std::chrono_literals; using namespace std::chrono_literals;
@@ -45,7 +45,7 @@ auto receiver(std::shared_ptr<connection> conn) -> awaitable<void>
request req; request req;
req.push("SUBSCRIBE", "channel"); req.push("SUBSCRIBE", "channel");
flat_tree resp; generic_flat_response resp;
conn->set_receive_response(resp); conn->set_receive_response(resp);
while (conn->will_reconnect()) { while (conn->will_reconnect()) {
@@ -58,12 +58,12 @@ auto receiver(std::shared_ptr<connection> conn) -> awaitable<void>
if (ec) if (ec)
break; // Connection lost, break so we can reconnect to channels. break; // Connection lost, break so we can reconnect to channels.
for (auto const& elem: resp.get_view()) for (auto const& elem: resp.value().get_view())
std::cout << elem.value << "\n"; std::cout << elem.value << "\n";
std::cout << std::endl; std::cout << std::endl;
resp.clear(); resp.value().clear();
} }
} }
} }

View File

@@ -21,7 +21,7 @@
namespace asio = boost::asio; namespace asio = boost::asio;
using namespace std::chrono_literals; using namespace std::chrono_literals;
using boost::redis::request; using boost::redis::request;
using boost::redis::resp3::flat_tree; using boost::redis::generic_flat_response;
using boost::redis::config; using boost::redis::config;
using boost::system::error_code; using boost::system::error_code;
using boost::redis::connection; using boost::redis::connection;
@@ -49,7 +49,7 @@ auto receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
request req; request req;
req.push("SUBSCRIBE", "channel"); req.push("SUBSCRIBE", "channel");
flat_tree resp; generic_flat_response resp;
conn->set_receive_response(resp); conn->set_receive_response(resp);
// Loop while reconnection is enabled // Loop while reconnection is enabled
@@ -66,12 +66,12 @@ auto receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
// The response must be consumed without suspending the // The response must be consumed without suspending the
// coroutine i.e. without the use of async operations. // coroutine i.e. without the use of async operations.
for (auto const& elem: resp.get_view()) for (auto const& elem: resp.value().get_view())
std::cout << elem.value << "\n"; std::cout << elem.value << "\n";
std::cout << std::endl; std::cout << std::endl;
resp.clear(); resp.value().clear();
} }
} }
} }

View File

@@ -13,6 +13,7 @@
#include <boost/redis/resp3/serialization.hpp> #include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/type.hpp> #include <boost/redis/resp3/type.hpp>
#include <boost/redis/resp3/flat_tree.hpp> #include <boost/redis/resp3/flat_tree.hpp>
#include <boost/redis/response.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
@@ -205,6 +206,45 @@ public:
} }
}; };
template <>
class general_aggregate<generic_flat_response> {
private:
generic_flat_response* tree_ = nullptr;
public:
explicit general_aggregate(generic_flat_response* c = nullptr)
: tree_(c)
{ }
void on_init() { }
void on_done()
{
BOOST_ASSERT_MSG(!!tree_, "Unexpected null pointer");
if (tree_->has_value()) {
tree_->value().notify_done();
}
}
template <class String>
void on_node(resp3::basic_node<String> const& nd, system::error_code&)
{
BOOST_ASSERT_MSG(!!tree_, "Unexpected null pointer");
switch (nd.data_type) {
case resp3::type::blob_error:
case resp3::type::simple_error:
*tree_ = error{
nd.data_type,
std::string{std::cbegin(nd.value), std::cend(nd.value)}
};
break;
default:
if (tree_->has_value()) {
(**tree_).push(nd);
}
}
}
};
template <> template <>
class general_aggregate<resp3::flat_tree> { class general_aggregate<resp3::flat_tree> {
private: private:

View File

@@ -115,6 +115,14 @@ struct response_traits<resp3::flat_tree> {
static auto adapt(response_type& v) noexcept { return adapter_type{&v}; } static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
}; };
template <>
struct response_traits<generic_flat_response> {
using response_type = generic_flat_response;
using adapter_type = general_aggregate<response_type>;
static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
};
template <class... Ts> template <class... Ts>
struct response_traits<response<Ts...>> { struct response_traits<response<Ts...>> {
using response_type = response<Ts...>; using response_type = response<Ts...>;

View File

@@ -71,6 +71,13 @@ struct result_traits<resp3::basic_tree<String>> {
static auto adapt(response_type& v) noexcept { return adapter_type{&v}; } static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
}; };
template <>
struct result_traits<generic_flat_response> {
using response_type = generic_flat_response;
using adapter_type = general_aggregate<response_type>;
static auto adapt(response_type& v) noexcept { return adapter_type{&v}; }
};
template <> template <>
struct result_traits<resp3::flat_tree> { struct result_traits<resp3::flat_tree> {
using response_type = resp3::flat_tree; using response_type = resp3::flat_tree;

View File

@@ -10,6 +10,7 @@
#include <boost/redis/adapter/result.hpp> #include <boost/redis/adapter/result.hpp>
#include <boost/redis/resp3/node.hpp> #include <boost/redis/resp3/node.hpp>
#include <boost/redis/resp3/tree.hpp> #include <boost/redis/resp3/tree.hpp>
#include <boost/redis/resp3/flat_tree.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
@@ -32,6 +33,9 @@ using response = std::tuple<adapter::result<Ts>...>;
*/ */
using generic_response = adapter::result<resp3::tree>; using generic_response = adapter::result<resp3::tree>;
/// Similar to @ref boost::redis::generic_response but stores data contiguously.
using generic_flat_response = adapter::result<resp3::flat_tree>;
/** @brief (Deprecated) Consume on response from a generic response /** @brief (Deprecated) Consume on response from a generic response
* *
* This function rotates the elements so that the start of the next * This function rotates the elements so that the start of the next

View File

@@ -24,6 +24,7 @@ using boost::redis::adapter::adapt2;
using boost::redis::adapter::result; using boost::redis::adapter::result;
using boost::redis::resp3::tree; using boost::redis::resp3::tree;
using boost::redis::resp3::flat_tree; using boost::redis::resp3::flat_tree;
using boost::redis::generic_flat_response;
using boost::redis::ignore_t; using boost::redis::ignore_t;
using boost::redis::resp3::detail::deserialize; using boost::redis::resp3::detail::deserialize;
using boost::redis::resp3::node; using boost::redis::resp3::node;
@@ -375,25 +376,45 @@ tree from_flat(flat_tree const& resp)
return ret; return ret;
} }
tree from_flat(generic_flat_response const& resp)
{
tree ret;
for (auto const& e: resp.value().get_view())
ret.push_back(from_node_view(e));
return ret;
}
// Parses the same data into a tree and a // Parses the same data into a tree and a
// flat_tree, they should be equal to each other. // flat_tree, they should be equal to each other.
BOOST_AUTO_TEST_CASE(flat_tree_views_are_set) BOOST_AUTO_TEST_CASE(flat_tree_views_are_set)
{ {
tree resp1; tree resp1;
flat_tree fresp; flat_tree resp2;
generic_flat_response resp3;
error_code ec; error_code ec;
deserialize(resp3_set, adapt2(resp1), ec); deserialize(resp3_set, adapt2(resp1), ec);
BOOST_CHECK_EQUAL(ec, error_code{}); BOOST_CHECK_EQUAL(ec, error_code{});
deserialize(resp3_set, adapt2(fresp), ec); deserialize(resp3_set, adapt2(resp2), ec);
BOOST_CHECK_EQUAL(ec, error_code{}); BOOST_CHECK_EQUAL(ec, error_code{});
BOOST_CHECK_EQUAL(fresp.get_reallocs(), 1u); deserialize(resp3_set, adapt2(resp3), ec);
BOOST_CHECK_EQUAL(fresp.get_total_msgs(), 1u); BOOST_CHECK_EQUAL(ec, error_code{});
auto const resp2 = from_flat(fresp); BOOST_CHECK_EQUAL(resp2.get_reallocs(), 1u);
BOOST_CHECK_EQUAL(resp1, resp2); BOOST_CHECK_EQUAL(resp2.get_total_msgs(), 1u);
BOOST_CHECK_EQUAL(resp3.value().get_reallocs(), 1u);
BOOST_CHECK_EQUAL(resp3.value().get_total_msgs(), 1u);
auto const tmp2 = from_flat(resp2);
BOOST_CHECK_EQUAL(resp1, tmp2);
auto const tmp3 = from_flat(resp3);
BOOST_CHECK_EQUAL(resp1, tmp3);
} }
// The response should be reusable. // The response should be reusable.
@@ -446,3 +467,39 @@ BOOST_AUTO_TEST_CASE(flat_tree_copy_assign)
BOOST_TEST((copy2 == resp)); BOOST_TEST((copy2 == resp));
BOOST_TEST((copy3 == resp)); BOOST_TEST((copy3 == resp));
} }
BOOST_AUTO_TEST_CASE(generic_flat_response_simple_error)
{
generic_flat_response resp;
char const* wire = "-Error\r\n";
error_code ec;
deserialize(wire, adapt2(resp), ec);
BOOST_CHECK_EQUAL(ec, error_code{});
BOOST_TEST(!resp.has_value());
BOOST_TEST(resp.has_error());
auto const error = resp.error();
BOOST_CHECK_EQUAL(error.data_type, boost::redis::resp3::type::simple_error);
BOOST_CHECK_EQUAL(error.diagnostic, std::string{"Error"});
}
BOOST_AUTO_TEST_CASE(generic_flat_response_blob_error)
{
generic_flat_response resp;
char const* wire = "!5\r\nError\r\n";
error_code ec;
deserialize(wire, adapt2(resp), ec);
BOOST_CHECK_EQUAL(ec, error_code{});
BOOST_TEST(!resp.has_value());
BOOST_TEST(resp.has_error());
auto const error = resp.error();
BOOST_CHECK_EQUAL(error.data_type, boost::redis::resp3::type::blob_error);
BOOST_CHECK_EQUAL(error.diagnostic, std::string{"Error"});
}