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

Adds automatic formatting with clang-format

This commit is contained in:
Anarthal (Rubén Pérez)
2025-05-12 13:49:55 +02:00
committed by GitHub
parent 1060733b84
commit 328ad97a79
81 changed files with 1736 additions and 1589 deletions

176
.clang-format Normal file
View File

@@ -0,0 +1,176 @@
---
Language: Cpp
ColumnLimit: 100
IndentWidth: 3
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: false
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
AccessModifierOffset: -3
BinPackArguments: false
BinPackParameters: false
AlignAfterOpenBracket: AlwaysBreak
PointerAlignment: Left
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<boost/redis.*>|<boost/redis/.*>'
Priority: -10
SortPriority: 1
- Regex: '^<boost/.*>'
Priority: -8
SortPriority: 3
- Regex: "^<.*"
Priority: -6
SortPriority: 5
- Regex: ".*"
Priority: -5
SortPriority: 4
IndentCaseLabels: true
AllowShortCaseLabelsOnASingleLine: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlignArrayOfStructures: Left
DerivePointerAlignment: false
PenaltyBreakAssignment: 2000000
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyBreakOpenParenthesis: 0
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyBreakScopeResolution: 1000000
PenaltyReturnTypeOnItsOwnLine: 200000000
# Defaults (based on Google)
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllConstructorInitializersOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: Empty
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: ExceptShortType
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BreakTemplateDeclarations: Leave
BreakBeforeBinaryOperators: None
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
CommentPragmas: '(^ IWYU pragma:)|(^\\copydoc )|(^ ?\\n)'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 3
Cpp11BracedListStyle: true
DeriveLineEnding: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeIsMainRegex: null
IncludeIsMainSourceRegex: ""
IndentGotoLabels: false
IndentPPDirectives: None
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- "c++"
- "C++"
CanonicalDelimiter: ""
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ""
BasedOnStyle: google
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
AlignConsecutiveShortCaseStatements:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AlignCaseColons: false
---

View File

@@ -4,8 +4,9 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <iostream>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
namespace net = boost::asio; namespace net = boost::asio;
@@ -63,5 +64,9 @@ int main(int argc, char* argv[])
} }
} }
#else // defined(BOOST_ASIO_HAS_CO_AWAIT) #else // defined(BOOST_ASIO_HAS_CO_AWAIT)
auto main() -> int {std::cout << "Requires coroutine support." << std::endl; return 1;} auto main() -> int
{
std::cout << "Requires coroutine support." << std::endl;
return 1;
}
#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) #endif // defined(BOOST_ASIO_HAS_CO_AWAIT)

View File

@@ -8,9 +8,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#include <boost/asio.hpp>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <boost/asio.hpp>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
namespace net = boost::asio; namespace net = boost::asio;
@@ -59,5 +60,9 @@ int main()
} }
} }
#else // defined(BOOST_ASIO_HAS_CO_AWAIT) #else // defined(BOOST_ASIO_HAS_CO_AWAIT)
auto main() -> int {std::cout << "Requires coroutine support." << std::endl; return 1;} auto main() -> int
{
std::cout << "Requires coroutine support." << std::endl;
return 1;
}
#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) #endif // defined(BOOST_ASIO_HAS_CO_AWAIT)

View File

@@ -5,7 +5,9 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <iostream> #include <iostream>
namespace asio = boost::asio; namespace asio = boost::asio;
@@ -47,4 +49,3 @@ auto main(int argc, char * argv[]) -> int
return 1; return 1;
} }
} }

View File

@@ -6,8 +6,8 @@
#include "sync_connection.hpp" #include "sync_connection.hpp"
#include <string>
#include <iostream> #include <iostream>
#include <string>
using boost::redis::sync_connection; using boost::redis::sync_connection;
using boost::redis::request; using boost::redis::request;

View File

@@ -5,13 +5,15 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/posix/stream_descriptor.hpp> #include <boost/asio/posix/stream_descriptor.hpp>
#include <unistd.h> #include <boost/asio/redirect_error.hpp>
#include <boost/asio/signal_set.hpp>
#include <iostream> #include <iostream>
#include <unistd.h>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
@@ -38,8 +40,7 @@ using namespace std::chrono_literals;
// Chat over Redis pubsub. To test, run this program from multiple // Chat over Redis pubsub. To test, run this program from multiple
// terminals and type messages to stdin. // terminals and type messages to stdin.
auto auto receiver(std::shared_ptr<connection> conn) -> awaitable<void>
receiver(std::shared_ptr<connection> conn) -> awaitable<void>
{ {
request req; request req;
req.push("SUBSCRIBE", "channel"); req.push("SUBSCRIBE", "channel");
@@ -48,7 +49,6 @@ receiver(std::shared_ptr<connection> conn) -> awaitable<void>
conn->set_receive_response(resp); conn->set_receive_response(resp);
while (conn->will_reconnect()) { while (conn->will_reconnect()) {
// Subscribe to channels. // Subscribe to channels.
co_await conn->async_exec(req, ignore); co_await conn->async_exec(req, ignore);
@@ -57,18 +57,16 @@ receiver(std::shared_ptr<connection> conn) -> awaitable<void>
co_await conn->async_receive(redirect_error(use_awaitable, ec)); co_await conn->async_receive(redirect_error(use_awaitable, ec));
if (ec) if (ec)
break; // Connection lost, break so we can reconnect to channels. break; // Connection lost, break so we can reconnect to channels.
std::cout std::cout << resp.value().at(1).value << " " << resp.value().at(2).value << " "
<< resp.value().at(1).value << resp.value().at(3).value << std::endl;
<< " " << resp.value().at(2).value
<< " " << resp.value().at(3).value
<< std::endl;
resp.value().clear(); resp.value().clear();
} }
} }
} }
// Publishes stdin messages to a Redis channel. // Publishes stdin messages to a Redis channel.
auto publisher(std::shared_ptr<stream_descriptor> in, std::shared_ptr<connection> conn) -> awaitable<void> auto publisher(std::shared_ptr<stream_descriptor> in, std::shared_ptr<connection> conn)
-> awaitable<void>
{ {
for (std::string msg;;) { for (std::string msg;;) {
auto n = co_await async_read_until(*in, dynamic_buffer(msg, 1024), "\n"); auto n = co_await async_read_until(*in, dynamic_buffer(msg, 1024), "\n");

View File

@@ -5,11 +5,13 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <iostream>
#include <map> #include <map>
#include <vector> #include <vector>
#include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
@@ -44,18 +46,21 @@ void print(std::map<std::string, std::string> const& cont)
template <class T> template <class T>
void print(std::vector<T> const& cont) void print(std::vector<T> const& cont)
{ {
for (auto const& e: cont) std::cout << e << " "; for (auto const& e : cont)
std::cout << e << " ";
std::cout << "\n"; std::cout << "\n";
} }
// Stores the content of some STL containers in Redis. // Stores the content of some STL containers in Redis.
auto store(std::shared_ptr<connection> conn) -> awaitable<void> auto store(std::shared_ptr<connection> conn) -> awaitable<void>
{ {
std::vector<int> vec std::vector<int> vec{1, 2, 3, 4, 5, 6};
{1, 2, 3, 4, 5, 6};
std::map<std::string, std::string> map std::map<std::string, std::string> map{
{{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}}; {"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"}
};
request req; request req;
req.push_range("RPUSH", "rpush-key", vec); req.push_range("RPUSH", "rpush-key", vec);
@@ -113,9 +118,9 @@ auto transaction(std::shared_ptr<connection> conn) -> awaitable<void>
response< response<
std::optional<std::vector<int>>, std::optional<std::vector<int>>,
std::optional<std::map<std::string, std::string>>, std::optional<std::map<std::string, std::string>>,
std::optional<std::vector<std::optional<std::string>>> std::optional<std::vector<std::optional<std::string>>>> // exec
> // exec >
> resp; resp;
co_await conn->async_exec(req, resp); co_await conn->async_exec(req, resp);

View File

@@ -5,10 +5,12 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/redirect_error.hpp> #include <boost/asio/redirect_error.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/signal_set.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
@@ -22,10 +24,8 @@ using boost::system::error_code;
using boost::redis::connection; using boost::redis::connection;
using namespace std::chrono_literals; using namespace std::chrono_literals;
auto auto echo_server_session(asio::ip::tcp::socket socket, std::shared_ptr<connection> conn)
echo_server_session( -> asio::awaitable<void>
asio::ip::tcp::socket socket,
std::shared_ptr<connection> conn) -> asio::awaitable<void>
{ {
request req; request req;
response<std::string> resp; response<std::string> resp;

View File

@@ -5,9 +5,11 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)

View File

@@ -5,9 +5,11 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)

View File

@@ -5,20 +5,23 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/detached.hpp>
#include <boost/describe.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/use_awaitable.hpp> #include <boost/asio/use_awaitable.hpp>
#include <string> #include <boost/describe.hpp>
#include <iostream> #include <iostream>
#include <string>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
#include <boost/json/serialize.hpp> #include <boost/redis/resp3/serialization.hpp>
#include <boost/json/parse.hpp> #include <boost/json/parse.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/value_from.hpp> #include <boost/json/value_from.hpp>
#include <boost/json/value_to.hpp> #include <boost/json/value_to.hpp>
#include <boost/redis/resp3/serialization.hpp>
namespace asio = boost::asio; namespace asio = boost::asio;
namespace resp3 = boost::redis::resp3; namespace resp3 = boost::redis::resp3;
@@ -46,11 +49,7 @@ void boost_redis_to_bulk(std::string& to, user const& u)
resp3::boost_redis_to_bulk(to, boost::json::serialize(boost::json::value_from(u))); resp3::boost_redis_to_bulk(to, boost::json::serialize(boost::json::value_from(u)));
} }
void void boost_redis_from_bulk(user& u, node_view const& node, boost::system::error_code&)
boost_redis_from_bulk(
user& u,
node_view const& node,
boost::system::error_code&)
{ {
u = boost::json::value_to<user>(boost::json::parse(node.value)); u = boost::json::value_to<user>(boost::json::parse(node.value));
} }
@@ -75,8 +74,7 @@ auto co_main(config cfg) -> asio::awaitable<void>
conn->cancel(); conn->cancel();
// Prints the first ping // Prints the first ping
std::cout std::cout << "Name: " << std::get<1>(resp).value().name << "\n"
<< "Name: " << std::get<1>(resp).value().name << "\n"
<< "Age: " << std::get<1>(resp).value().age << "\n" << "Age: " << std::get<1>(resp).value().age << "\n"
<< "Country: " << std::get<1>(resp).value().country << "\n"; << "Country: " << std::get<1>(resp).value().country << "\n";
} }

View File

@@ -6,10 +6,12 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/resp3/serialization.hpp> #include <boost/redis/resp3/serialization.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#include <iostream> #include <iostream>
// See the definition in person.proto. This header is automatically // See the definition in person.proto. This header is automatically
@@ -32,8 +34,7 @@ using boost::redis::resp3::node_view;
using tutorial::person; using tutorial::person;
// Boost.Redis customization points (example/protobuf.hpp) // Boost.Redis customization points (example/protobuf.hpp)
namespace tutorial namespace tutorial {
{
// Below I am using a Boost.Redis to indicate a protobuf error, this // Below I am using a Boost.Redis to indicate a protobuf error, this
// is ok for an example, users however might want to define their own // is ok for an example, users however might want to define their own
@@ -47,18 +48,14 @@ void boost_redis_to_bulk(std::string& to, person const& u)
resp3::boost_redis_to_bulk(to, tmp); resp3::boost_redis_to_bulk(to, tmp);
} }
void void boost_redis_from_bulk(person& u, node_view const& node, boost::system::error_code& ec)
boost_redis_from_bulk(
person& u,
node_view const& node,
boost::system::error_code& ec)
{ {
std::string const tmp{node.value}; std::string const tmp{node.value};
if (!u.ParseFromString(tmp)) if (!u.ParseFromString(tmp))
ec = boost::redis::error::invalid_data_type; ec = boost::redis::error::invalid_data_type;
} }
} // tutorial } // namespace tutorial
using tutorial::boost_redis_to_bulk; using tutorial::boost_redis_to_bulk;
using tutorial::boost_redis_from_bulk; using tutorial::boost_redis_from_bulk;
@@ -84,8 +81,7 @@ asio::awaitable<void> co_main(config cfg)
co_await conn->async_exec(req, resp); co_await conn->async_exec(req, resp);
conn->cancel(); conn->cancel();
std::cout std::cout << "Name: " << std::get<1>(resp).value().name() << "\n"
<< "Name: " << std::get<1>(resp).value().name() << "\n"
<< "Age: " << std::get<1>(resp).value().id() << "\n" << "Age: " << std::get<1>(resp).value().id() << "\n"
<< "Email: " << std::get<1>(resp).value().email() << "\n"; << "Email: " << std::get<1>(resp).value().email() << "\n";
} }

View File

@@ -5,9 +5,11 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
@@ -21,8 +23,7 @@ using boost::redis::config;
using boost::redis::address; using boost::redis::address;
using boost::redis::connection; using boost::redis::connection;
auto redir(boost::system::error_code& ec) auto redir(boost::system::error_code& ec) { return asio::redirect_error(asio::use_awaitable, ec); }
{ return asio::redirect_error(asio::use_awaitable, ec); }
// For more info see // For more info see
// - https://redis.io/docs/manual/sentinel. // - https://redis.io/docs/manual/sentinel.
@@ -48,7 +49,9 @@ auto resolve_master_address(std::vector<address> const& addresses) -> asio::awai
conn->cancel(); conn->cancel();
conn->reset_stream(); conn->reset_stream();
if (!ec && std::get<0>(resp)) if (!ec && std::get<0>(resp))
co_return address{std::get<0>(resp).value().value().at(0), std::get<0>(resp).value().value().at(1)}; co_return address{
std::get<0>(resp).value().value().at(0),
std::get<0>(resp).value().value().at(1)};
} }
co_return address{}; co_return address{};
@@ -58,16 +61,15 @@ auto co_main(config cfg) -> asio::awaitable<void>
{ {
// A list of sentinel addresses from which only one is responsive. // A list of sentinel addresses from which only one is responsive.
// This simulates sentinels that are down. // This simulates sentinels that are down.
std::vector<address> const addresses std::vector<address> const addresses{
{ address{"foo", "26379"} address{"foo", "26379"},
, address{"bar", "26379"} address{"bar", "26379"},
, cfg.addr cfg.addr
}; };
auto const ep = co_await resolve_master_address(addresses); auto const ep = co_await resolve_master_address(addresses);
std::clog std::clog << "Host: " << ep.host << "\n"
<< "Host: " << ep.host << "\n"
<< "Port: " << ep.port << "\n" << "Port: " << ep.port << "\n"
<< std::flush; << std::flush;
} }

View File

@@ -5,11 +5,13 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/signal_set.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
@@ -63,10 +65,8 @@ auto stream_reader(std::shared_ptr<connection> conn) -> net::awaitable<void>
// The streamId is located at item_index - 2 // The streamId is located at item_index - 2
// The payload is located at item_index + 1 // The payload is located at item_index + 1
stream_id = resp.value().at(item_index - 2).value; stream_id = resp.value().at(item_index - 2).value;
std::cout std::cout << "StreamId: " << stream_id << ", "
<< "StreamId: " << stream_id << ", " << "MyField: " << resp.value().at(item_index + 1).value << std::endl;
<< "MyField: " << resp.value().at(item_index + 1).value
<< std::endl;
++item_index; // We can increase so we don't read this again ++item_index; // We can increase so we don't read this again
} }

View File

@@ -6,13 +6,15 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/redirect_error.hpp> #include <boost/asio/redirect_error.hpp>
#include <boost/asio/signal_set.hpp> #include <boost/asio/signal_set.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream> #include <iostream>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
@@ -47,8 +49,7 @@ using asio::signal_set;
*/ */
// Receives server pushes. // Receives server pushes.
auto auto receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
{ {
request req; request req;
req.push("SUBSCRIBE", "channel"); req.push("SUBSCRIBE", "channel");
@@ -58,7 +59,6 @@ receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
// Loop while reconnection is enabled // Loop while reconnection is enabled
while (conn->will_reconnect()) { while (conn->will_reconnect()) {
// Reconnect to the channels. // Reconnect to the channels.
co_await conn->async_exec(req, ignore); co_await conn->async_exec(req, ignore);
@@ -74,11 +74,8 @@ receiver(std::shared_ptr<connection> conn) -> asio::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.
std::cout std::cout << resp.value().at(1).value << " " << resp.value().at(2).value << " "
<< resp.value().at(1).value << resp.value().at(3).value << std::endl;
<< " " << resp.value().at(2).value
<< " " << resp.value().at(3).value
<< std::endl;
consume_one(resp); consume_one(resp);
} }

View File

@@ -4,11 +4,13 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/connection.hpp>
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/connection.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <iostream> #include <iostream>
namespace asio = boost::asio; namespace asio = boost::asio;

View File

@@ -7,16 +7,17 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/request.hpp> #include <boost/redis/request.hpp>
#include <boost/asio/deferred.hpp> #include <boost/asio/deferred.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/use_future.hpp> #include <boost/asio/use_future.hpp>
#include <thread>
#include <chrono> #include <chrono>
#include <thread>
using namespace std::chrono_literals; using namespace std::chrono_literals;
namespace boost::redis namespace boost::redis {
{
class sync_connection { class sync_connection {
public: public:
@@ -25,10 +26,7 @@ public:
, conn_{std::make_shared<connection>(ioc_)} , conn_{std::make_shared<connection>(ioc_)}
{ } { }
~sync_connection() ~sync_connection() { thread_.join(); }
{
thread_.join();
}
void run(config cfg) void run(config cfg)
{ {
@@ -42,16 +40,18 @@ public:
void stop() void stop()
{ {
asio::dispatch(ioc_, [this]() { conn_->cancel(); }); asio::dispatch(ioc_, [this]() {
conn_->cancel();
});
} }
template <class Response> template <class Response>
auto exec(request const& req, Response& resp) auto exec(request const& req, Response& resp)
{ {
asio::dispatch( asio::dispatch(conn_->get_executor(), asio::deferred([this, &req, &resp]() {
conn_->get_executor(), return conn_->async_exec(req, resp, asio::deferred);
asio::deferred([this, &req, &resp]() { return conn_->async_exec(req, resp, asio::deferred); })) }))(asio::use_future)
(asio::use_future).get(); .get();
} }
private: private:
@@ -60,4 +60,4 @@ private:
std::thread thread_; std::thread thread_;
}; };
} } // namespace boost::redis

View File

@@ -8,12 +8,12 @@
#define BOOST_REDIS_HPP #define BOOST_REDIS_HPP
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/error.hpp>
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/request.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/response.hpp>
#include <boost/redis/ignore.hpp> #include <boost/redis/ignore.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
/** @defgroup high-level-api Reference /** @defgroup high-level-api Reference
* *

View File

@@ -7,20 +7,20 @@
#ifndef BOOST_REDIS_ADAPTER_ADAPT_HPP #ifndef BOOST_REDIS_ADAPTER_ADAPT_HPP
#define BOOST_REDIS_ADAPTER_ADAPT_HPP #define BOOST_REDIS_ADAPTER_ADAPT_HPP
#include <boost/redis/adapter/detail/response_traits.hpp>
#include <boost/redis/adapter/detail/result_traits.hpp>
#include <boost/redis/resp3/node.hpp> #include <boost/redis/resp3/node.hpp>
#include <boost/redis/response.hpp> #include <boost/redis/response.hpp>
#include <boost/redis/adapter/detail/result_traits.hpp>
#include <boost/redis/adapter/detail/response_traits.hpp>
#include <boost/mp11.hpp> #include <boost/mp11.hpp>
#include <boost/system.hpp> #include <boost/system.hpp>
#include <tuple>
#include <limits> #include <limits>
#include <string_view> #include <string_view>
#include <tuple>
#include <variant> #include <variant>
namespace boost::redis::adapter namespace boost::redis::adapter {
{
/** @brief Adapts a type to be used as a response. /** @brief Adapts a type to be used as a response.
* *
@@ -73,8 +73,10 @@ auto boost_redis_adapt(T& t) noexcept
*/ */
template <class T> template <class T>
auto adapt2(T& t = redis::ignore) noexcept auto adapt2(T& t = redis::ignore) noexcept
{ return detail::result_traits<T>::adapt(t); } {
return detail::result_traits<T>::adapt(t);
}
} // boost::redis::adapter } // namespace boost::redis::adapter
#endif // BOOST_REDIS_ADAPTER_ADAPT_HPP #endif // BOOST_REDIS_ADAPTER_ADAPT_HPP

View File

@@ -7,10 +7,11 @@
#ifndef BOOST_REDIS_ANY_ADAPTER_HPP #ifndef BOOST_REDIS_ANY_ADAPTER_HPP
#define BOOST_REDIS_ANY_ADAPTER_HPP #define BOOST_REDIS_ANY_ADAPTER_HPP
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/adapter/adapt.hpp> #include <boost/redis/adapter/adapt.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <cstddef> #include <cstddef>
#include <functional> #include <functional>
#include <string_view> #include <string_view>
@@ -63,9 +64,11 @@ public:
* while `*this` is being used. * while `*this` is being used.
*/ */
template <class T, class = std::enable_if_t<!std::is_same_v<T, any_adapter>>> template <class T, class = std::enable_if_t<!std::is_same_v<T, any_adapter>>>
explicit any_adapter(T& resp) : impl_(create_impl(resp)) {} explicit any_adapter(T& resp)
: impl_(create_impl(resp))
{ }
}; };
} } // namespace boost::redis
#endif #endif

View File

@@ -7,27 +7,28 @@
#ifndef BOOST_REDIS_ADAPTER_ADAPTERS_HPP #ifndef BOOST_REDIS_ADAPTER_ADAPTERS_HPP
#define BOOST_REDIS_ADAPTER_ADAPTERS_HPP #define BOOST_REDIS_ADAPTER_ADAPTERS_HPP
#include <boost/redis/error.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/adapter/result.hpp> #include <boost/redis/adapter/result.hpp>
#include <boost/redis/error.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <set>
#include <optional>
#include <type_traits>
#include <unordered_set>
#include <forward_list>
#include <system_error>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <vector>
#include <array> #include <array>
#include <string_view>
#include <charconv> #include <charconv>
#include <deque>
#include <forward_list>
#include <list>
#include <map>
#include <optional>
#include <set>
#include <string_view>
#include <system_error>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// See https://stackoverflow.com/a/31658120/1077832 // See https://stackoverflow.com/a/31658120/1077832
#ifdef _LIBCPP_VERSION #ifdef _LIBCPP_VERSION
@@ -35,8 +36,7 @@
#include <cstdlib> #include <cstdlib>
#endif #endif
namespace boost::redis::adapter::detail namespace boost::redis::adapter::detail {
{
// Exclude bools, char and charXY_t types // Exclude bools, char and charXY_t types
template <class T> struct is_integral_number : std::is_integral<T> { }; template <class T> struct is_integral_number : std::is_integral<T> { };
@@ -55,14 +55,9 @@ struct converter;
template <class T> template <class T>
struct converter<T, true> { struct converter<T, true> {
template <class String> template <class String>
static void static void apply(T& i, resp3::basic_node<String> const& node, system::error_code& ec)
apply(
T& i,
resp3::basic_node<String> const& node,
system::error_code& ec)
{ {
auto const res = auto const res = std::from_chars(node.value.data(), node.value.data() + node.value.size(), i);
std::from_chars(node.value.data(), node.value.data() + node.value.size(), i);
if (res.ec != std::errc()) if (res.ec != std::errc())
ec = redis::error::not_a_number; ec = redis::error::not_a_number;
} }
@@ -71,11 +66,7 @@ struct converter<T, true> {
template <> template <>
struct converter<bool, false> { struct converter<bool, false> {
template <class String> template <class String>
static void static void apply(bool& t, resp3::basic_node<String> const& node, system::error_code& ec)
apply(
bool& t,
resp3::basic_node<String> const& node,
system::error_code& ec)
{ {
t = *node.value.data() == 't'; t = *node.value.data() == 't';
} }
@@ -84,11 +75,7 @@ struct converter<bool, false> {
template <> template <>
struct converter<double, false> { struct converter<double, false> {
template <class String> template <class String>
static void static void apply(double& d, resp3::basic_node<String> const& node, system::error_code& ec)
apply(
double& d,
resp3::basic_node<String> const& node,
system::error_code& ec)
{ {
#ifdef _LIBCPP_VERSION #ifdef _LIBCPP_VERSION
// The string in node.value is not null terminated and we also // The string in node.value is not null terminated and we also
@@ -110,8 +97,7 @@ struct converter<double, false> {
template <class CharT, class Traits, class Allocator> template <class CharT, class Traits, class Allocator>
struct converter<std::basic_string<CharT, Traits, Allocator>, false> { struct converter<std::basic_string<CharT, Traits, Allocator>, false> {
template <class String> template <class String>
static void static void apply(
apply(
std::basic_string<CharT, Traits, Allocator>& s, std::basic_string<CharT, Traits, Allocator>& s,
resp3::basic_node<String> const& node, resp3::basic_node<String> const& node,
system::error_code&) system::error_code&)
@@ -123,11 +109,7 @@ struct converter<std::basic_string<CharT, Traits, Allocator>, false> {
template <class T> template <class T>
struct from_bulk_impl { struct from_bulk_impl {
template <class String> template <class String>
static void static void apply(T& t, resp3::basic_node<String> const& node, system::error_code& ec)
apply(
T& t,
resp3::basic_node<String> const& node,
system::error_code& ec)
{ {
converter<T>::apply(t, node, ec); converter<T>::apply(t, node, ec);
} }
@@ -136,8 +118,7 @@ struct from_bulk_impl {
template <class T> template <class T>
struct from_bulk_impl<std::optional<T>> { struct from_bulk_impl<std::optional<T>> {
template <class String> template <class String>
static void static void apply(
apply(
std::optional<T>& op, std::optional<T>& op,
resp3::basic_node<String> const& node, resp3::basic_node<String> const& node,
system::error_code& ec) system::error_code& ec)
@@ -150,11 +131,7 @@ struct from_bulk_impl<std::optional<T>> {
}; };
template <class T, class String> template <class T, class String>
void void boost_redis_from_bulk(T& t, resp3::basic_node<String> const& node, system::error_code& ec)
boost_redis_from_bulk(
T& t,
resp3::basic_node<String> const& node,
system::error_code& ec)
{ {
from_bulk_impl<T>::apply(t, node, ec); from_bulk_impl<T>::apply(t, node, ec);
} }
@@ -167,7 +144,9 @@ private:
Result* result_; Result* result_;
public: public:
explicit general_aggregate(Result* c = nullptr): result_(c) {} explicit general_aggregate(Result* c = nullptr)
: result_(c)
{ }
template <class String> template <class String>
void operator()(resp3::basic_node<String> const& nd, system::error_code&) void operator()(resp3::basic_node<String> const& nd, system::error_code&)
{ {
@@ -175,10 +154,18 @@ public:
switch (nd.data_type) { switch (nd.data_type) {
case resp3::type::blob_error: case resp3::type::blob_error:
case resp3::type::simple_error: case resp3::type::simple_error:
*result_ = error{nd.data_type, std::string{std::cbegin(nd.value), std::cend(nd.value)}}; *result_ = error{
nd.data_type,
std::string{std::cbegin(nd.value), std::cend(nd.value)}
};
break; break;
default: default:
result_->value().push_back({nd.data_type, nd.aggregate_size, nd.depth, std::string{std::cbegin(nd.value), std::cend(nd.value)}}); result_->value().push_back({
nd.data_type,
nd.aggregate_size,
nd.depth,
std::string{std::cbegin(nd.value), std::cend(nd.value)}
});
} }
} }
}; };
@@ -189,7 +176,9 @@ private:
Node* result_; Node* result_;
public: public:
explicit general_simple(Node* t = nullptr) : result_(t) {} explicit general_simple(Node* t = nullptr)
: result_(t)
{ }
template <class String> template <class String>
void operator()(resp3::basic_node<String> const& nd, system::error_code&) void operator()(resp3::basic_node<String> const& nd, system::error_code&)
@@ -198,7 +187,10 @@ public:
switch (nd.data_type) { switch (nd.data_type) {
case resp3::type::blob_error: case resp3::type::blob_error:
case resp3::type::simple_error: case resp3::type::simple_error:
*result_ = error{nd.data_type, std::string{std::cbegin(nd.value), std::cend(nd.value)}}; *result_ = error{
nd.data_type,
std::string{std::cbegin(nd.value), std::cend(nd.value)}
};
break; break;
default: default:
result_->value().data_type = nd.data_type; result_->value().data_type = nd.data_type;
@@ -232,8 +224,7 @@ private:
typename Result::iterator hint_; typename Result::iterator hint_;
public: public:
void on_value_available(Result& result) void on_value_available(Result& result) { hint_ = std::end(result); }
{ hint_ = std::end(result); }
template <class String> template <class String>
void operator()(Result& result, resp3::basic_node<String> const& nd, system::error_code& ec) void operator()(Result& result, resp3::basic_node<String> const& nd, system::error_code& ec)
@@ -264,8 +255,7 @@ private:
bool on_key_ = true; bool on_key_ = true;
public: public:
void on_value_available(Result& result) void on_value_available(Result& result) { current_ = std::end(result); }
{ current_ = std::end(result); }
template <class String> template <class String>
void operator()(Result& result, resp3::basic_node<String> const& nd, system::error_code& ec) void operator()(Result& result, resp3::basic_node<String> const& nd, system::error_code& ec)
@@ -352,7 +342,6 @@ public:
template <class Result> template <class Result>
struct list_impl { struct list_impl {
void on_value_available(Result&) { } void on_value_available(Result&) { }
template <class String> template <class String>
@@ -374,43 +363,69 @@ struct list_impl {
//--------------------------------------------------- //---------------------------------------------------
template <class T> template <class T>
struct impl_map { using type = simple_impl<T>; }; struct impl_map {
using type = simple_impl<T>;
};
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class Allocator>
struct impl_map<std::set<Key, Compare, Allocator>> { using type = set_impl<std::set<Key, Compare, Allocator>>; }; struct impl_map<std::set<Key, Compare, Allocator>> {
using type = set_impl<std::set<Key, Compare, Allocator>>;
};
template <class Key, class Compare, class Allocator> template <class Key, class Compare, class Allocator>
struct impl_map<std::multiset<Key, Compare, Allocator>> { using type = set_impl<std::multiset<Key, Compare, Allocator>>; }; struct impl_map<std::multiset<Key, Compare, Allocator>> {
using type = set_impl<std::multiset<Key, Compare, Allocator>>;
};
template <class Key, class Hash, class KeyEqual, class Allocator> template <class Key, class Hash, class KeyEqual, class Allocator>
struct impl_map<std::unordered_set<Key, Hash, KeyEqual, Allocator>> { using type = set_impl<std::unordered_set<Key, Hash, KeyEqual, Allocator>>; }; struct impl_map<std::unordered_set<Key, Hash, KeyEqual, Allocator>> {
using type = set_impl<std::unordered_set<Key, Hash, KeyEqual, Allocator>>;
};
template <class Key, class Hash, class KeyEqual, class Allocator> template <class Key, class Hash, class KeyEqual, class Allocator>
struct impl_map<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>> { using type = set_impl<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>>; }; struct impl_map<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>> {
using type = set_impl<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>>;
};
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class Allocator>
struct impl_map<std::map<Key, T, Compare, Allocator>> { using type = map_impl<std::map<Key, T, Compare, Allocator>>; }; struct impl_map<std::map<Key, T, Compare, Allocator>> {
using type = map_impl<std::map<Key, T, Compare, Allocator>>;
};
template <class Key, class T, class Compare, class Allocator> template <class Key, class T, class Compare, class Allocator>
struct impl_map<std::multimap<Key, T, Compare, Allocator>> { using type = map_impl<std::multimap<Key, T, Compare, Allocator>>; }; struct impl_map<std::multimap<Key, T, Compare, Allocator>> {
using type = map_impl<std::multimap<Key, T, Compare, Allocator>>;
};
template <class Key, class Hash, class KeyEqual, class Allocator> template <class Key, class Hash, class KeyEqual, class Allocator>
struct impl_map<std::unordered_map<Key, Hash, KeyEqual, Allocator>> { using type = map_impl<std::unordered_map<Key, Hash, KeyEqual, Allocator>>; }; struct impl_map<std::unordered_map<Key, Hash, KeyEqual, Allocator>> {
using type = map_impl<std::unordered_map<Key, Hash, KeyEqual, Allocator>>;
};
template <class Key, class Hash, class KeyEqual, class Allocator> template <class Key, class Hash, class KeyEqual, class Allocator>
struct impl_map<std::unordered_multimap<Key, Hash, KeyEqual, Allocator>> { using type = map_impl<std::unordered_multimap<Key, Hash, KeyEqual, Allocator>>; }; struct impl_map<std::unordered_multimap<Key, Hash, KeyEqual, Allocator>> {
using type = map_impl<std::unordered_multimap<Key, Hash, KeyEqual, Allocator>>;
};
template <class T, class Allocator> template <class T, class Allocator>
struct impl_map<std::vector<T, Allocator>> { using type = vector_impl<std::vector<T, Allocator>>; }; struct impl_map<std::vector<T, Allocator>> {
using type = vector_impl<std::vector<T, Allocator>>;
};
template <class T, std::size_t N> template <class T, std::size_t N>
struct impl_map<std::array<T, N>> { using type = array_impl<std::array<T, N>>; }; struct impl_map<std::array<T, N>> {
using type = array_impl<std::array<T, N>>;
};
template <class T, class Allocator> template <class T, class Allocator>
struct impl_map<std::list<T, Allocator>> { using type = list_impl<std::list<T, Allocator>>; }; struct impl_map<std::list<T, Allocator>> {
using type = list_impl<std::list<T, Allocator>>;
};
template <class T, class Allocator> template <class T, class Allocator>
struct impl_map<std::deque<T, Allocator>> { using type = list_impl<std::deque<T, Allocator>>; }; struct impl_map<std::deque<T, Allocator>> {
using type = list_impl<std::deque<T, Allocator>>;
};
//--------------------------------------------------- //---------------------------------------------------
@@ -421,6 +436,7 @@ template <class T>
class wrapper<result<T>> { class wrapper<result<T>> {
public: public:
using response_type = result<T>; using response_type = result<T>;
private: private:
response_type* result_; response_type* result_;
typename impl_map<T>::type impl_; typename impl_map<T>::type impl_;
@@ -433,15 +449,18 @@ private:
case resp3::type::null: case resp3::type::null:
case resp3::type::simple_error: case resp3::type::simple_error:
case resp3::type::blob_error: case resp3::type::blob_error:
*result_ = error{nd.data_type, {std::cbegin(nd.value), std::cend(nd.value)}}; *result_ = error{
nd.data_type,
{std::cbegin(nd.value), std::cend(nd.value)}
};
return true; return true;
default: default: return false;
return false;
} }
} }
public: public:
explicit wrapper(response_type* t = nullptr) : result_(t) explicit wrapper(response_type* t = nullptr)
: result_(t)
{ {
if (result_) { if (result_) {
result_->value() = T{}; result_->value() = T{};
@@ -481,21 +500,22 @@ private:
switch (nd.data_type) { switch (nd.data_type) {
case resp3::type::blob_error: case resp3::type::blob_error:
case resp3::type::simple_error: case resp3::type::simple_error:
*result_ = error{nd.data_type, {std::cbegin(nd.value), std::cend(nd.value)}}; *result_ = error{
nd.data_type,
{std::cbegin(nd.value), std::cend(nd.value)}
};
return true; return true;
default: default: return false;
return false;
} }
} }
public: public:
explicit wrapper(response_type* o = nullptr) : result_(o) {} explicit wrapper(response_type* o = nullptr)
: result_(o)
{ }
template <class String> template <class String>
void void operator()(resp3::basic_node<String> const& nd, system::error_code& ec)
operator()(
resp3::basic_node<String> const& nd,
system::error_code& ec)
{ {
BOOST_ASSERT_MSG(!!result_, "Unexpected null pointer"); BOOST_ASSERT_MSG(!!result_, "Unexpected null pointer");
@@ -517,6 +537,6 @@ public:
} }
}; };
} // boost::redis::adapter::detail } // namespace boost::redis::adapter::detail
#endif // BOOST_REDIS_ADAPTER_ADAPTERS_HPP #endif // BOOST_REDIS_ADAPTER_ADAPTERS_HPP

View File

@@ -7,19 +7,19 @@
#ifndef BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP #ifndef BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
#define BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP #define BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP
#include <boost/redis/adapter/detail/result_traits.hpp>
#include <boost/redis/resp3/node.hpp> #include <boost/redis/resp3/node.hpp>
#include <boost/redis/response.hpp> #include <boost/redis/response.hpp>
#include <boost/redis/adapter/detail/result_traits.hpp>
#include <boost/mp11.hpp> #include <boost/mp11.hpp>
#include <boost/system.hpp> #include <boost/system.hpp>
#include <tuple>
#include <limits> #include <limits>
#include <string_view> #include <string_view>
#include <tuple>
#include <variant> #include <variant>
namespace boost::redis::adapter::detail namespace boost::redis::adapter::detail {
{
class ignore_adapter { class ignore_adapter {
public: public:
@@ -36,7 +36,9 @@ public:
[[nodiscard]] [[nodiscard]]
auto get_supported_response_size() const noexcept auto get_supported_response_size() const noexcept
{ return static_cast<std::size_t>(-1);} {
return static_cast<std::size_t>(-1);
}
}; };
template <class Response> template <class Response>
@@ -50,14 +52,13 @@ private:
adapters_array_type adapters_; adapters_array_type adapters_;
public: public:
explicit static_adapter(Response& r) explicit static_adapter(Response& r) { assigner<size - 1>::assign(adapters_, r); }
{
assigner<size - 1>::assign(adapters_, r);
}
[[nodiscard]] [[nodiscard]]
auto get_supported_response_size() const noexcept auto get_supported_response_size() const noexcept
{ return size;} {
return size;
}
template <class String> template <class String>
void operator()(std::size_t i, resp3::basic_node<String> const& nd, system::error_code& ec) void operator()(std::size_t i, resp3::basic_node<String> const& nd, system::error_code& ec)
@@ -65,7 +66,11 @@ public:
using std::visit; using std::visit;
// I am usure whether this should be an error or an assertion. // I am usure whether this should be an error or an assertion.
BOOST_ASSERT(i < adapters_.size()); BOOST_ASSERT(i < adapters_.size());
visit([&](auto& arg){arg(nd, ec);}, adapters_.at(i)); visit(
[&](auto& arg) {
arg(nd, ec);
},
adapters_.at(i));
} }
}; };
@@ -81,9 +86,10 @@ public:
{ } { }
[[nodiscard]] [[nodiscard]]
auto auto get_supported_response_size() const noexcept
get_supported_response_size() const noexcept {
{ return static_cast<std::size_t>(-1);} return static_cast<std::size_t>(-1);
}
template <class String> template <class String>
void operator()(std::size_t, resp3::basic_node<String> const& nd, system::error_code& ec) void operator()(std::size_t, resp3::basic_node<String> const& nd, system::error_code& ec)
@@ -100,8 +106,7 @@ struct response_traits<ignore_t> {
using response_type = ignore_t; using response_type = ignore_t;
using adapter_type = detail::ignore_adapter; using adapter_type = detail::ignore_adapter;
static auto adapt(response_type&) noexcept static auto adapt(response_type&) noexcept { return detail::ignore_adapter{}; }
{ return detail::ignore_adapter{}; }
}; };
template <> template <>
@@ -109,8 +114,7 @@ struct response_traits<result<ignore_t>> {
using response_type = result<ignore_t>; using response_type = result<ignore_t>;
using adapter_type = detail::ignore_adapter; using adapter_type = detail::ignore_adapter;
static auto adapt(response_type&) noexcept static auto adapt(response_type&) noexcept { return detail::ignore_adapter{}; }
{ return detail::ignore_adapter{}; }
}; };
template <class String, class Allocator> template <class String, class Allocator>
@@ -118,8 +122,7 @@ struct response_traits<result<std::vector<resp3::basic_node<String>, Allocator>>
using response_type = result<std::vector<resp3::basic_node<String>, Allocator>>; using response_type = result<std::vector<resp3::basic_node<String>, Allocator>>;
using adapter_type = vector_adapter<response_type>; using adapter_type = vector_adapter<response_type>;
static auto adapt(response_type& v) noexcept static auto adapt(response_type& v) noexcept { return adapter_type{v}; }
{ return adapter_type{v}; }
}; };
template <class... Ts> template <class... Ts>
@@ -127,22 +130,27 @@ struct response_traits<response<Ts...>> {
using response_type = response<Ts...>; using response_type = response<Ts...>;
using adapter_type = static_adapter<response_type>; using adapter_type = static_adapter<response_type>;
static auto adapt(response_type& r) noexcept static auto adapt(response_type& r) noexcept { return adapter_type{r}; }
{ return adapter_type{r}; }
}; };
template <class Adapter> template <class Adapter>
class wrapper { class wrapper {
public: public:
explicit wrapper(Adapter adapter) : adapter_{adapter} {} explicit wrapper(Adapter adapter)
: adapter_{adapter}
{ }
template <class String> template <class String>
void operator()(resp3::basic_node<String> const& nd, system::error_code& ec) void operator()(resp3::basic_node<String> const& nd, system::error_code& ec)
{ return adapter_(0, nd, ec); } {
return adapter_(0, nd, ec);
}
[[nodiscard]] [[nodiscard]]
auto get_supported_response_size() const noexcept auto get_supported_response_size() const noexcept
{ return adapter_.get_supported_response_size();} {
return adapter_.get_supported_response_size();
}
private: private:
Adapter adapter_; Adapter adapter_;
@@ -154,6 +162,6 @@ auto make_adapter_wrapper(Adapter adapter)
return wrapper{adapter}; return wrapper{adapter};
} }
} // boost::redis::adapter::detail } // namespace boost::redis::adapter::detail
#endif // BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP #endif // BOOST_REDIS_ADAPTER_DETAIL_RESPONSE_TRAITS_HPP

View File

@@ -7,21 +7,21 @@
#ifndef BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP #ifndef BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP
#define BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP #define BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP
#include <boost/redis/error.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/ignore.hpp>
#include <boost/redis/adapter/detail/adapters.hpp> #include <boost/redis/adapter/detail/adapters.hpp>
#include <boost/redis/adapter/result.hpp>
#include <boost/redis/adapter/ignore.hpp> #include <boost/redis/adapter/ignore.hpp>
#include <boost/redis/adapter/result.hpp>
#include <boost/redis/error.hpp>
#include <boost/redis/ignore.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/mp11.hpp> #include <boost/mp11.hpp>
#include <vector>
#include <tuple>
#include <string_view> #include <string_view>
#include <tuple>
#include <variant> #include <variant>
#include <vector>
namespace boost::redis::adapter::detail namespace boost::redis::adapter::detail {
{
/* Traits class for response objects. /* Traits class for response objects.
* *
@@ -67,7 +67,9 @@ using adapter_t = typename result_traits<std::decay_t<T>>::adapter_type;
template <class T> template <class T>
auto internal_adapt(T& t) noexcept auto internal_adapt(T& t) noexcept
{ return result_traits<std::decay_t<T>>::adapt(t); } {
return result_traits<std::decay_t<T>>::adapt(t);
}
template <std::size_t N> template <std::size_t N>
struct assigner { struct assigner {
@@ -94,12 +96,8 @@ class static_aggregate_adapter;
template <class Tuple> template <class Tuple>
class static_aggregate_adapter<result<Tuple>> { class static_aggregate_adapter<result<Tuple>> {
private: private:
using adapters_array_type = using adapters_array_type = std::array<
std::array< mp11::mp_rename<mp11::mp_transform<adapter_t, Tuple>, std::variant>,
mp11::mp_rename<
mp11::mp_transform<
adapter_t, Tuple>,
std::variant>,
std::tuple_size<Tuple>::value>; std::tuple_size<Tuple>::value>;
// Tuple element we are currently on. // Tuple element we are currently on.
@@ -148,19 +146,22 @@ public:
return; return;
} }
visit([&](auto& arg){arg(elem, ec);}, adapters_[i_]); visit(
[&](auto& arg) {
arg(elem, ec);
},
adapters_[i_]);
count(elem); count(elem);
} }
}; };
template <class... Ts> template <class... Ts>
struct result_traits<result<std::tuple<Ts...>>> struct result_traits<result<std::tuple<Ts...>>> {
{
using response_type = result<std::tuple<Ts...>>; using response_type = result<std::tuple<Ts...>>;
using adapter_type = static_aggregate_adapter<response_type>; using adapter_type = static_aggregate_adapter<response_type>;
static auto adapt(response_type& r) noexcept { return adapter_type{&r}; } static auto adapt(response_type& r) noexcept { return adapter_type{&r}; }
}; };
} // boost::redis::adapter::detail } // namespace boost::redis::adapter::detail
#endif // BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP #endif // BOOST_REDIS_ADAPTER_RESPONSE_TRAITS_HPP

View File

@@ -7,13 +7,14 @@
#ifndef BOOST_REDIS_ADAPTER_IGNORE_HPP #ifndef BOOST_REDIS_ADAPTER_IGNORE_HPP
#define BOOST_REDIS_ADAPTER_IGNORE_HPP #define BOOST_REDIS_ADAPTER_IGNORE_HPP
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <string> #include <string>
namespace boost::redis::adapter namespace boost::redis::adapter {
{
/** @brief An adapter that ignores responses /** @brief An adapter that ignores responses
* @ingroup high-level-api * @ingroup high-level-api
@@ -32,6 +33,6 @@ struct ignore {
} }
}; };
} // boost::redis::adapter } // namespace boost::redis::adapter
#endif // BOOST_REDIS_ADAPTER_IGNORE_HPP #endif // BOOST_REDIS_ADAPTER_IGNORE_HPP

View File

@@ -8,13 +8,14 @@
#ifndef BOOST_REDIS_ADAPTER_RESULT_HPP #ifndef BOOST_REDIS_ADAPTER_RESULT_HPP
#define BOOST_REDIS_ADAPTER_RESULT_HPP #define BOOST_REDIS_ADAPTER_RESULT_HPP
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/system/result.hpp> #include <boost/system/result.hpp>
#include <string> #include <string>
namespace boost::redis::adapter namespace boost::redis::adapter {
{
/** @brief Stores any resp3 error /** @brief Stores any resp3 error
* @ingroup high-level-api * @ingroup high-level-api
@@ -44,10 +45,7 @@ inline bool operator==(error const& a, error const& b)
* @param a Left hand side error object. * @param a Left hand side error object.
* @param b Right hand side error object. * @param b Right hand side error object.
*/ */
inline bool operator!=(error const& a, error const& b) inline bool operator!=(error const& a, error const& b) { return !(a == b); }
{
return !(a == b);
}
/** @brief Stores response to individual Redis commands /** @brief Stores response to individual Redis commands
* @ingroup high-level-api * @ingroup high-level-api
@@ -55,27 +53,19 @@ inline bool operator!=(error const& a, error const& b)
template <class Value> template <class Value>
using result = system::result<Value, error>; using result = system::result<Value, error>;
BOOST_NORETURN inline void BOOST_NORETURN inline void throw_exception_from_error(error const& e, boost::source_location const&)
throw_exception_from_error(error const & e, boost::source_location const &)
{ {
system::error_code ec; system::error_code ec;
switch (e.data_type) { switch (e.data_type) {
case resp3::type::simple_error: case resp3::type::simple_error: ec = redis::error::resp3_simple_error; break;
ec = redis::error::resp3_simple_error; case resp3::type::blob_error: ec = redis::error::resp3_blob_error; break;
break; case resp3::type::null: ec = redis::error::resp3_null; break;
case resp3::type::blob_error: default: BOOST_ASSERT_MSG(false, "Unexpected data type.");
ec = redis::error::resp3_blob_error;
break;
case resp3::type::null:
ec = redis::error::resp3_null;
break;
default:
BOOST_ASSERT_MSG(false, "Unexpected data type.");
} }
throw system::system_error(ec, e.diagnostic); throw system::system_error(ec, e.diagnostic);
} }
} // boost::redis::adapter } // namespace boost::redis::adapter
#endif // BOOST_REDIS_ADAPTER_RESULT_HPP #endif // BOOST_REDIS_ADAPTER_RESULT_HPP

View File

@@ -7,13 +7,12 @@
#ifndef BOOST_REDIS_CONFIG_HPP #ifndef BOOST_REDIS_CONFIG_HPP
#define BOOST_REDIS_CONFIG_HPP #define BOOST_REDIS_CONFIG_HPP
#include <string>
#include <chrono> #include <chrono>
#include <optional>
#include <limits> #include <limits>
#include <optional>
#include <string>
namespace boost::redis namespace boost::redis {
{
/** @brief Address of a Redis server /** @brief Address of a Redis server
* @ingroup high-level-api * @ingroup high-level-api
@@ -88,6 +87,6 @@ struct config {
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)(); std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)();
}; };
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_CONFIG_HPP #endif // BOOST_REDIS_CONFIG_HPP

View File

@@ -42,7 +42,6 @@
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp> #include <boost/core/ignore_unused.hpp>
#include <array> #include <array>
@@ -53,8 +52,7 @@
#include <memory> #include <memory>
namespace boost::redis { namespace boost::redis {
namespace detail namespace detail {
{
template <class AsyncReadStream, class DynamicBuffer> template <class AsyncReadStream, class DynamicBuffer>
class append_some_op { class append_some_op {
@@ -73,9 +71,7 @@ public:
{ } { }
template <class Self> template <class Self>
void operator()( Self& self void operator()(Self& self, system::error_code ec = {}, std::size_t n = 0)
, system::error_code ec = {}
, std::size_t n = 0)
{ {
BOOST_ASIO_CORO_REENTER(coro_) BOOST_ASIO_CORO_REENTER(coro_)
{ {
@@ -96,22 +92,22 @@ public:
}; };
template <class AsyncReadStream, class DynamicBuffer, class CompletionToken> template <class AsyncReadStream, class DynamicBuffer, class CompletionToken>
auto auto async_append_some(
async_append_some(
AsyncReadStream& stream, AsyncReadStream& stream,
DynamicBuffer buffer, DynamicBuffer buffer,
std::size_t size, std::size_t size,
CompletionToken&& token) CompletionToken&& token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code, std::size_t)>(
< CompletionToken append_some_op<AsyncReadStream, DynamicBuffer>{stream, buffer, size},
, void(system::error_code, std::size_t) token,
>(append_some_op<AsyncReadStream, DynamicBuffer> {stream, buffer, size}, token, stream); stream);
} }
template <class Executor> template <class Executor>
using exec_notifier_type = using exec_notifier_type = asio::experimental::channel<
asio::experimental::channel<Executor, void(system::error_code, std::size_t)>; Executor,
void(system::error_code, std::size_t)>;
template <class Conn> template <class Conn>
struct exec_op { struct exec_op {
@@ -188,9 +184,7 @@ struct writer_op {
asio::coroutine coro{}; asio::coroutine coro{};
template <class Self> template <class Self>
void operator()( Self& self void operator()(Self& self, system::error_code ec = {}, std::size_t n = 0)
, system::error_code ec = {}
, std::size_t n = 0)
{ {
ignore_unused(n); ignore_unused(n);
@@ -248,7 +242,10 @@ struct writer_op {
template <class Conn, class Logger> template <class Conn, class Logger>
struct reader_op { struct reader_op {
using dyn_buffer_type = asio::dynamic_string_buffer<char, std::char_traits<char>, std::allocator<char>>; using dyn_buffer_type = asio::dynamic_string_buffer<
char,
std::char_traits<char>,
std::allocator<char>>;
// TODO: Move this to config so the user can fine tune? // TODO: Move this to config so the user can fine tune?
static constexpr std::size_t buffer_growth_hint = 4096; static constexpr std::size_t buffer_growth_hint = 4096;
@@ -259,9 +256,7 @@ struct reader_op {
asio::coroutine coro{}; asio::coroutine coro{};
template <class Self> template <class Self>
void operator()( Self& self void operator()(Self& self, system::error_code ec = {}, std::size_t n = 0)
, system::error_code ec = {}
, std::size_t n = 0)
{ {
ignore_unused(n); ignore_unused(n);
@@ -331,7 +326,6 @@ struct reader_op {
self.complete(asio::error::operation_aborted); self.complete(asio::error::operation_aborted);
return; return;
} }
} }
} }
} }
@@ -353,13 +347,14 @@ public:
{ } { }
template <class Self> template <class Self>
void operator()( Self& self void operator()(
, order_t order = {} Self& self,
, system::error_code ec0 = {} order_t order = {},
, system::error_code ec1 = {} system::error_code ec0 = {},
, system::error_code ec2 = {} system::error_code ec1 = {},
, system::error_code ec3 = {} system::error_code ec2 = {},
, system::error_code ec4 = {}) system::error_code ec3 = {},
system::error_code ec4 = {})
{ {
BOOST_ASIO_CORO_REENTER(coro_) for (;;) BOOST_ASIO_CORO_REENTER(coro_) for (;;)
{ {
@@ -391,13 +386,8 @@ public:
conn_->next_layer().async_handshake( conn_->next_layer().async_handshake(
asio::ssl::stream_base::client, asio::ssl::stream_base::client,
asio::prepend( asio::prepend(
asio::cancel_after( asio::cancel_after(conn_->cfg_.ssl_handshake_timeout, std::move(self)),
conn_->cfg_.ssl_handshake_timeout, order_t{}));
std::move(self)
),
order_t {}
)
);
logger_.on_ssl_handshake(ec0); logger_.on_ssl_handshake(ec0);
@@ -414,14 +404,22 @@ public:
// causing an authentication problem. // causing an authentication problem.
BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD
asio::experimental::make_parallel_group( asio::experimental::make_parallel_group(
[this](auto token) { return conn_->handshaker_.async_hello(*conn_, logger_, token); }, [this](auto token) {
[this](auto token) { return conn_->health_checker_.async_ping(*conn_, logger_, token); }, return conn_->handshaker_.async_hello(*conn_, logger_, token);
[this](auto token) { return conn_->health_checker_.async_check_timeout(*conn_, logger_, token);}, },
[this](auto token) { return conn_->reader(logger_, token);}, [this](auto token) {
[this](auto token) { return conn_->writer(logger_, token);} return conn_->health_checker_.async_ping(*conn_, logger_, token);
).async_wait( },
asio::experimental::wait_for_one_error(), [this](auto token) {
std::move(self)); return conn_->health_checker_.async_check_timeout(*conn_, logger_, token);
},
[this](auto token) {
return conn_->reader(logger_, token);
},
[this](auto token) {
return conn_->writer(logger_, token);
})
.async_wait(asio::experimental::wait_for_one_error(), std::move(self));
if (order[0] == 0 && !!ec0) { if (order[0] == 0 && !!ec0) {
self.complete(ec0); self.complete(ec0);
@@ -465,7 +463,7 @@ public:
} }
}; };
} // boost::redis::detail } // namespace detail
/** @brief A SSL connection to the Redis server. /** @brief A SSL connection to the Redis server.
* @ingroup high-level-api * @ingroup high-level-api
@@ -489,13 +487,11 @@ public:
using executor_type = Executor; using executor_type = Executor;
/// Returns the associated executor. /// Returns the associated executor.
executor_type get_executor() noexcept executor_type get_executor() noexcept { return writer_timer_.get_executor(); }
{return writer_timer_.get_executor();}
/// Rebinds the socket type to another executor. /// Rebinds the socket type to another executor.
template <class Executor1> template <class Executor1>
struct rebind_executor struct rebind_executor {
{
/// The connection type when rebound to the specified executor. /// The connection type when rebound to the specified executor.
using other = basic_connection<Executor1>; using other = basic_connection<Executor1>;
}; };
@@ -505,8 +501,7 @@ public:
* @param ex Executor on which connection operation will run. * @param ex Executor on which connection operation will run.
* @param ctx SSL context. * @param ctx SSL context.
*/ */
explicit explicit basic_connection(
basic_connection(
executor_type ex, executor_type ex,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client}) asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client})
: ctx_{std::move(ctx)} : ctx_{std::move(ctx)}
@@ -521,8 +516,7 @@ public:
} }
/// Constructs from a context. /// Constructs from a context.
explicit explicit basic_connection(
basic_connection(
asio::io_context& ioc, asio::io_context& ioc,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client}) asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client})
: basic_connection(ioc.get_executor(), std::move(ctx)) : basic_connection(ioc.get_executor(), std::move(ctx))
@@ -568,11 +562,7 @@ public:
template < template <
class Logger = logger, class Logger = logger,
class CompletionToken = asio::default_completion_token_t<executor_type>> class CompletionToken = asio::default_completion_token_t<executor_type>>
auto auto async_run(config const& cfg = {}, Logger l = Logger{}, CompletionToken&& token = {})
async_run(
config const& cfg = {},
Logger l = Logger{},
CompletionToken&& token = {})
{ {
cfg_ = cfg; cfg_ = cfg;
resv_.set_config(cfg); resv_.set_config(cfg);
@@ -581,10 +571,10 @@ public:
handshaker_.set_config(cfg); handshaker_.set_config(cfg);
l.set_prefix(cfg.log_prefix); l.set_prefix(cfg.log_prefix);
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken detail::run_op<this_type, Logger>{this, l},
, void(system::error_code) token,
>(detail::run_op<this_type, Logger>{this, l}, token, writer_timer_); writer_timer_);
} }
/** @brief Receives server side pushes asynchronously. /** @brief Receives server side pushes asynchronously.
@@ -611,7 +601,9 @@ public:
*/ */
template <class CompletionToken = asio::default_completion_token_t<executor_type>> template <class CompletionToken = asio::default_completion_token_t<executor_type>>
auto async_receive(CompletionToken&& token = {}) auto async_receive(CompletionToken&& token = {})
{ return receive_channel_.async_receive(std::forward<CompletionToken>(token)); } {
return receive_channel_.async_receive(std::forward<CompletionToken>(token));
}
/** @brief Receives server pushes synchronously without blocking. /** @brief Receives server pushes synchronously without blocking.
* *
@@ -628,8 +620,7 @@ public:
{ {
std::size_t size = 0; std::size_t size = 0;
auto f = [&](system::error_code const& ec2, std::size_t n) auto f = [&](system::error_code const& ec2, std::size_t n) {
{
ec = ec2; ec = ec2;
size = n; size = n;
}; };
@@ -669,13 +660,8 @@ public:
*/ */
template < template <
class Response = ignore_t, class Response = ignore_t,
class CompletionToken = asio::default_completion_token_t<executor_type> class CompletionToken = asio::default_completion_token_t<executor_type>>
> auto async_exec(request const& req, Response& resp = ignore, CompletionToken&& token = {})
auto
async_exec(
request const& req,
Response& resp = ignore,
CompletionToken&& token = {})
{ {
return this->async_exec(req, any_adapter(resp), std::forward<CompletionToken>(token)); return this->async_exec(req, any_adapter(resp), std::forward<CompletionToken>(token));
} }
@@ -686,26 +672,26 @@ public:
* encapsulates a reference to a response object. * encapsulates a reference to a response object.
*/ */
template <class CompletionToken = asio::default_completion_token_t<executor_type>> template <class CompletionToken = asio::default_completion_token_t<executor_type>>
auto auto async_exec(request const& req, any_adapter adapter, CompletionToken&& token = {})
async_exec(
request const& req,
any_adapter adapter,
CompletionToken&& token = {})
{ {
auto& adapter_impl = adapter.impl_; auto& adapter_impl = adapter.impl_;
BOOST_ASSERT_MSG(req.get_expected_responses() <= adapter_impl.supported_response_size, "Request and response have incompatible sizes."); BOOST_ASSERT_MSG(
req.get_expected_responses() <= adapter_impl.supported_response_size,
"Request and response have incompatible sizes.");
auto notifier = std::make_shared<detail::exec_notifier_type<executor_type>>(get_executor(), 1); auto notifier = std::make_shared<detail::exec_notifier_type<executor_type>>(
get_executor(),
1);
auto info = detail::make_elem(req, std::move(adapter_impl.adapt_fn)); auto info = detail::make_elem(req, std::move(adapter_impl.adapt_fn));
info->set_done_callback([notifier]() { info->set_done_callback([notifier]() {
notifier->try_send(std::error_code{}, 0); notifier->try_send(std::error_code{}, 0);
}); });
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code, std::size_t)>(
< CompletionToken detail::exec_op<this_type>{this, notifier, info},
, void(system::error_code, std::size_t) token,
>(detail::exec_op<this_type>{this, notifier, info}, token, writer_timer_); writer_timer_);
} }
/** @brief Cancel operations. /** @brief Cancel operations.
@@ -722,24 +708,14 @@ public:
void cancel(operation op = operation::all) void cancel(operation op = operation::all)
{ {
switch (op) { switch (op) {
case operation::resolve: case operation::resolve: resv_.cancel(); break;
resv_.cancel(); case operation::exec: mpx_.cancel_waiting(); break;
break;
case operation::exec:
mpx_.cancel_waiting();
break;
case operation::reconnection: case operation::reconnection:
cfg_.reconnect_wait_interval = std::chrono::seconds::zero(); cfg_.reconnect_wait_interval = std::chrono::seconds::zero();
break; break;
case operation::run: case operation::run: cancel_run(); break;
cancel_run(); case operation::receive: receive_channel_.cancel(); break;
break; case operation::health_check: health_checker_.cancel(); break;
case operation::receive:
receive_channel_.cancel();
break;
case operation::health_check:
health_checker_.cancel();
break;
case operation::all: case operation::all:
resv_.cancel(); resv_.cancel();
cfg_.reconnect_wait_interval = std::chrono::seconds::zero(); cfg_.reconnect_wait_interval = std::chrono::seconds::zero();
@@ -752,50 +728,52 @@ public:
} }
} }
auto run_is_canceled() const noexcept auto run_is_canceled() const noexcept { return mpx_.get_cancel_run_state(); }
{ return mpx_.get_cancel_run_state(); }
/// Returns true if the connection was canceled. /// Returns true if the connection was canceled.
bool will_reconnect() const noexcept bool will_reconnect() const noexcept
{ return cfg_.reconnect_wait_interval != std::chrono::seconds::zero();} {
return cfg_.reconnect_wait_interval != std::chrono::seconds::zero();
}
/// Returns the ssl context. /// Returns the ssl context.
auto const& get_ssl_context() const noexcept auto const& get_ssl_context() const noexcept { return ctx_; }
{ return ctx_;}
/// Resets the underlying stream. /// Resets the underlying stream.
void reset_stream() void reset_stream()
{ stream_ = std::make_unique<next_layer_type>(writer_timer_.get_executor(), ctx_); } {
stream_ = std::make_unique<next_layer_type>(writer_timer_.get_executor(), ctx_);
}
/// Returns a reference to the next layer. /// Returns a reference to the next layer.
auto& next_layer() noexcept auto& next_layer() noexcept { return *stream_; }
{ return *stream_; }
/// Returns a const reference to the next layer. /// Returns a const reference to the next layer.
auto const& next_layer() const noexcept auto const& next_layer() const noexcept { return *stream_; }
{ return *stream_; }
/// Sets the response object of `async_receive` operations. /// Sets the response object of `async_receive` operations.
template <class Response> template <class Response>
void set_receive_response(Response& response) void set_receive_response(Response& response)
{ mpx_.set_receive_response(response); } {
mpx_.set_receive_response(response);
}
/// Returns connection usage information. /// Returns connection usage information.
usage get_usage() const noexcept usage get_usage() const noexcept { return mpx_.get_usage(); }
{ return mpx_.get_usage(); }
private: private:
using clock_type = std::chrono::steady_clock; using clock_type = std::chrono::steady_clock;
using clock_traits_type = asio::wait_traits<clock_type>; using clock_traits_type = asio::wait_traits<clock_type>;
using timer_type = asio::basic_waitable_timer<clock_type, clock_traits_type, executor_type>; using timer_type = asio::basic_waitable_timer<clock_type, clock_traits_type, executor_type>;
using receive_channel_type = asio::experimental::channel<executor_type, void(system::error_code, std::size_t)>; using receive_channel_type = asio::experimental::channel<
executor_type,
void(system::error_code, std::size_t)>;
using resolver_type = detail::resolver<Executor>; using resolver_type = detail::resolver<Executor>;
using health_checker_type = detail::health_checker<Executor>; using health_checker_type = detail::health_checker<Executor>;
using resp3_handshaker_type = detail::resp3_handshaker<executor_type>; using resp3_handshaker_type = detail::resp3_handshaker<executor_type>;
auto use_ssl() const noexcept auto use_ssl() const noexcept { return cfg_.use_ssl; }
{ return cfg_.use_ssl;}
void cancel_run() void cancel_run()
{ {
@@ -813,20 +791,19 @@ private:
template <class CompletionToken, class Logger> template <class CompletionToken, class Logger>
auto reader(Logger l, CompletionToken&& token) auto reader(Logger l, CompletionToken&& token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken detail::reader_op<this_type, Logger>{this, l},
, void(system::error_code) std::forward<CompletionToken>(token),
>(detail::reader_op<this_type, Logger>{this, l}, writer_timer_);
std::forward<CompletionToken>(token), writer_timer_);
} }
template <class CompletionToken, class Logger> template <class CompletionToken, class Logger>
auto writer(Logger l, CompletionToken&& token) auto writer(Logger l, CompletionToken&& token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken detail::writer_op<this_type, Logger>{this, l},
, void(system::error_code) std::forward<CompletionToken>(token),
>(detail::writer_op<this_type, Logger>{this, l}, std::forward<CompletionToken>(token), writer_timer_); writer_timer_);
} }
void close() void close()
@@ -840,10 +817,7 @@ private:
auto is_open() const noexcept { return stream_->next_layer().is_open(); } auto is_open() const noexcept { return stream_->next_layer().is_open(); }
auto& lowest_layer() noexcept { return stream_->lowest_layer(); } auto& lowest_layer() noexcept { return stream_->lowest_layer(); }
[[nodiscard]] bool trigger_write() const noexcept [[nodiscard]] bool trigger_write() const noexcept { return is_open() && !mpx_.is_writing(); }
{
return is_open() && !mpx_.is_writing();
}
asio::ssl::context ctx_; asio::ssl::context ctx_;
std::unique_ptr<next_layer_type> stream_; std::unique_ptr<next_layer_type> stream_;
@@ -877,43 +851,41 @@ public:
using executor_type = asio::any_io_executor; using executor_type = asio::any_io_executor;
/// Contructs from an executor. /// Contructs from an executor.
explicit explicit connection(
connection(
executor_type ex, executor_type ex,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client}); asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client});
/// Contructs from a context. /// Contructs from a context.
explicit explicit connection(
connection(
asio::io_context& ioc, asio::io_context& ioc,
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client}); asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client});
/// Returns the underlying executor. /// Returns the underlying executor.
executor_type get_executor() noexcept executor_type get_executor() noexcept { return impl_.get_executor(); }
{ return impl_.get_executor(); }
/// Calls `boost::redis::basic_connection::async_run`. /// Calls `boost::redis::basic_connection::async_run`.
template <class CompletionToken = asio::deferred_t> template <class CompletionToken = asio::deferred_t>
auto async_run(config const& cfg, logger l, CompletionToken&& token = {}) auto async_run(config const& cfg, logger l, CompletionToken&& token = {})
{ {
return asio::async_initiate< return asio::async_initiate<CompletionToken, void(boost::system::error_code)>(
CompletionToken, void(boost::system::error_code)>( [](auto handler, connection* self, config const* cfg, logger l) {
[](auto handler, connection* self, config const* cfg, logger l)
{
self->async_run_impl(*cfg, l, std::move(handler)); self->async_run_impl(*cfg, l, std::move(handler));
}, token, this, &cfg, l); },
token,
this,
&cfg,
l);
} }
/// Calls `boost::redis::basic_connection::async_receive`. /// Calls `boost::redis::basic_connection::async_receive`.
template <class CompletionToken = asio::deferred_t> template <class CompletionToken = asio::deferred_t>
auto async_receive(CompletionToken&& token = {}) auto async_receive(CompletionToken&& token = {})
{ return impl_.async_receive(std::forward<CompletionToken>(token)); } {
return impl_.async_receive(std::forward<CompletionToken>(token));
}
/// Calls `boost::redis::basic_connection::receive`. /// Calls `boost::redis::basic_connection::receive`.
std::size_t receive(system::error_code& ec) std::size_t receive(system::error_code& ec) { return impl_.receive(ec); }
{
return impl_.receive(ec);
}
/// Calls `boost::redis::basic_connection::async_exec`. /// Calls `boost::redis::basic_connection::async_exec`.
template <class Response, class CompletionToken = asio::deferred_t> template <class Response, class CompletionToken = asio::deferred_t>
@@ -924,61 +896,53 @@ public:
/// Calls `boost::redis::basic_connection::async_exec`. /// Calls `boost::redis::basic_connection::async_exec`.
template <class CompletionToken = asio::deferred_t> template <class CompletionToken = asio::deferred_t>
auto auto async_exec(request const& req, any_adapter adapter, CompletionToken&& token = {})
async_exec(
request const& req,
any_adapter adapter,
CompletionToken&& token = {})
{
return asio::async_initiate<
CompletionToken, void(boost::system::error_code, std::size_t)>(
[](auto handler, connection* self, request const* req, any_adapter&& adapter)
{ {
return asio::async_initiate<CompletionToken, void(boost::system::error_code, std::size_t)>(
[](auto handler, connection* self, request const* req, any_adapter&& adapter) {
self->async_exec_impl(*req, std::move(adapter), std::move(handler)); self->async_exec_impl(*req, std::move(adapter), std::move(handler));
}, token, this, &req, std::move(adapter)); },
token,
this,
&req,
std::move(adapter));
} }
/// Calls `boost::redis::basic_connection::cancel`. /// Calls `boost::redis::basic_connection::cancel`.
void cancel(operation op = operation::all); void cancel(operation op = operation::all);
/// Calls `boost::redis::basic_connection::will_reconnect`. /// Calls `boost::redis::basic_connection::will_reconnect`.
bool will_reconnect() const noexcept bool will_reconnect() const noexcept { return impl_.will_reconnect(); }
{ return impl_.will_reconnect();}
/// Calls `boost::redis::basic_connection::next_layer`. /// Calls `boost::redis::basic_connection::next_layer`.
auto& next_layer() noexcept auto& next_layer() noexcept { return impl_.next_layer(); }
{ return impl_.next_layer(); }
/// Calls `boost::redis::basic_connection::next_layer`. /// Calls `boost::redis::basic_connection::next_layer`.
auto const& next_layer() const noexcept auto const& next_layer() const noexcept { return impl_.next_layer(); }
{ return impl_.next_layer(); }
/// Calls `boost::redis::basic_connection::reset_stream`. /// Calls `boost::redis::basic_connection::reset_stream`.
void reset_stream() void reset_stream() { impl_.reset_stream(); }
{ impl_.reset_stream();}
/// Sets the response object of `async_receive` operations. /// Sets the response object of `async_receive` operations.
template <class Response> template <class Response>
void set_receive_response(Response& response) void set_receive_response(Response& response)
{ impl_.set_receive_response(response); } {
impl_.set_receive_response(response);
}
/// Returns connection usage information. /// Returns connection usage information.
usage get_usage() const noexcept usage get_usage() const noexcept { return impl_.get_usage(); }
{ return impl_.get_usage(); }
/// Returns the ssl context. /// Returns the ssl context.
auto const& get_ssl_context() const noexcept auto const& get_ssl_context() const noexcept { return impl_.get_ssl_context(); }
{ return impl_.get_ssl_context();}
private: private:
void void async_run_impl(
async_run_impl(
config const& cfg, config const& cfg,
logger l, logger l,
asio::any_completion_handler<void(boost::system::error_code)> token); asio::any_completion_handler<void(boost::system::error_code)> token);
void void async_exec_impl(
async_exec_impl(
request const& req, request const& req,
any_adapter&& adapter, any_adapter&& adapter,
asio::any_completion_handler<void(boost::system::error_code, std::size_t)> token); asio::any_completion_handler<void(boost::system::error_code, std::size_t)> token);
@@ -986,6 +950,6 @@ private:
basic_connection<executor_type> impl_; basic_connection<executor_type> impl_;
}; };
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_CONNECTION_HPP #endif // BOOST_REDIS_CONNECTION_HPP

View File

@@ -9,16 +9,17 @@
#include <boost/redis/detail/helper.hpp> #include <boost/redis/detail/helper.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/asio/cancel_after.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/connect.hpp> #include <boost/asio/connect.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/cancel_after.hpp>
#include <string>
#include <chrono>
namespace boost::redis::detail #include <chrono>
{ #include <string>
namespace boost::redis::detail {
template <class Connector, class Stream> template <class Connector, class Stream>
struct connect_op { struct connect_op {
@@ -28,15 +29,20 @@ struct connect_op {
asio::coroutine coro{}; asio::coroutine coro{};
template <class Self> template <class Self>
void operator()( Self& self void operator()(
, system::error_code const& ec = {} Self& self,
, asio::ip::tcp::endpoint const& ep= {}) system::error_code const& ec = {},
asio::ip::tcp::endpoint const& ep = {})
{ {
BOOST_ASIO_CORO_REENTER(coro) BOOST_ASIO_CORO_REENTER(coro)
{ {
BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD
asio::async_connect(*stream, *res_, asio::async_connect(
[](system::error_code const&, auto const&) { return true; }, *stream,
*res_,
[](system::error_code const&, auto const&) {
return true;
},
asio::cancel_after(ctor_->timeout_, std::move(self))); asio::cancel_after(ctor_->timeout_, std::move(self)));
ctor_->endpoint_ = ep; ctor_->endpoint_ = ep;
@@ -52,20 +58,17 @@ struct connect_op {
class connector { class connector {
public: public:
void set_config(config const& cfg) void set_config(config const& cfg) { timeout_ = cfg.connect_timeout; }
{ timeout_ = cfg.connect_timeout; }
template <class Stream, class CompletionToken> template <class Stream, class CompletionToken>
auto auto async_connect(
async_connect(
Stream& stream, Stream& stream,
asio::ip::tcp::resolver::results_type const& res, asio::ip::tcp::resolver::results_type const& res,
CompletionToken&& token) CompletionToken&& token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken connect_op<connector, Stream>{this, &stream, &res},
, void(system::error_code) token);
>(connect_op<connector, Stream>{this, &stream, &res}, token);
} }
auto const& endpoint() const noexcept { return endpoint_; } auto const& endpoint() const noexcept { return endpoint_; }
@@ -77,6 +80,6 @@ private:
asio::ip::tcp::endpoint endpoint_; asio::ip::tcp::endpoint endpoint_;
}; };
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_CONNECTOR_HPP #endif // BOOST_REDIS_CONNECTOR_HPP

View File

@@ -7,19 +7,20 @@
#ifndef BOOST_REDIS_HEALTH_CHECKER_HPP #ifndef BOOST_REDIS_HEALTH_CHECKER_HPP
#define BOOST_REDIS_HEALTH_CHECKER_HPP #define BOOST_REDIS_HEALTH_CHECKER_HPP
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/redis/operation.hpp>
#include <boost/redis/adapter/any_adapter.hpp> #include <boost/redis/adapter/any_adapter.hpp>
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/operation.hpp> #include <boost/redis/operation.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/consign.hpp> #include <boost/asio/consign.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
#include <boost/asio/post.hpp> #include <boost/asio/post.hpp>
#include <memory> #include <boost/asio/steady_timer.hpp>
#include <chrono> #include <chrono>
#include <memory>
namespace boost::redis::detail { namespace boost::redis::detail {
@@ -130,8 +131,7 @@ public:
template <class Executor> template <class Executor>
class health_checker { class health_checker {
private: private:
using timer_type = using timer_type = asio::basic_waitable_timer<
asio::basic_waitable_timer<
std::chrono::steady_clock, std::chrono::steady_clock,
asio::wait_traits<std::chrono::steady_clock>, asio::wait_traits<std::chrono::steady_clock>,
Executor>; Executor>;
@@ -160,20 +160,22 @@ public:
template <class Connection, class Logger, class CompletionToken> template <class Connection, class Logger, class CompletionToken>
auto async_ping(Connection& conn, Logger l, CompletionToken token) auto async_ping(Connection& conn, Logger l, CompletionToken token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken ping_op<health_checker, Connection, Logger>{this, &conn, l},
, void(system::error_code) token,
>(ping_op<health_checker, Connection, Logger>{this, &conn, l}, token, conn, ping_timer_); conn,
ping_timer_);
} }
template <class Connection, class Logger, class CompletionToken> template <class Connection, class Logger, class CompletionToken>
auto async_check_timeout(Connection& conn, Logger l, CompletionToken token) auto async_check_timeout(Connection& conn, Logger l, CompletionToken token)
{ {
checker_has_exited_ = false; checker_has_exited_ = false;
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken check_timeout_op<health_checker, Connection, Logger>{this, &conn, l},
, void(system::error_code) token,
>(check_timeout_op<health_checker, Connection, Logger>{this, &conn, l}, token, conn, wait_timer_); conn,
wait_timer_);
} }
private: private:
@@ -188,6 +190,6 @@ private:
bool checker_has_exited_ = false; bool checker_has_exited_ = false;
}; };
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_HEALTH_CHECKER_HPP #endif // BOOST_REDIS_HEALTH_CHECKER_HPP

View File

@@ -9,8 +9,7 @@
#include <boost/asio/cancellation_type.hpp> #include <boost/asio/cancellation_type.hpp>
namespace boost::redis::detail namespace boost::redis::detail {
{
template <class T> template <class T>
auto is_cancelled(T const& self) auto is_cancelled(T const& self)
@@ -20,18 +19,16 @@ auto is_cancelled(T const& self)
#define BOOST_REDIS_CHECK_OP0(X) \ #define BOOST_REDIS_CHECK_OP0(X) \
if (ec || redis::detail::is_cancelled(self)) { \ if (ec || redis::detail::is_cancelled(self)) { \
X\ X self.complete(!!ec ? ec : asio::error::operation_aborted); \
self.complete(!!ec ? ec : asio::error::operation_aborted);\
return; \ return; \
} }
#define BOOST_REDIS_CHECK_OP1(X) \ #define BOOST_REDIS_CHECK_OP1(X) \
if (ec || redis::detail::is_cancelled(self)) { \ if (ec || redis::detail::is_cancelled(self)) { \
X\ X self.complete(!!ec ? ec : asio::error::operation_aborted, {}); \
self.complete(!!ec ? ec : asio::error::operation_aborted, {});\
return; \ return; \
} }
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_HELPER_HPP #endif // BOOST_REDIS_HELPER_HPP

View File

@@ -20,12 +20,11 @@
#include <deque> #include <deque>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <optional>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <optional>
namespace boost::redis namespace boost::redis {
{
class request; class request;
@@ -35,63 +34,61 @@ using tribool = std::optional<bool>;
struct multiplexer { struct multiplexer {
using adapter_type = std::function<void(resp3::node_view const&, system::error_code&)>; using adapter_type = std::function<void(resp3::node_view const&, system::error_code&)>;
using pipeline_adapter_type = std::function<void(std::size_t, resp3::node_view const&, system::error_code&)>; using pipeline_adapter_type = std::function<
void(std::size_t, resp3::node_view const&, system::error_code&)>;
struct elem { struct elem {
public: public:
explicit elem(request const& req, pipeline_adapter_type adapter); explicit elem(request const& req, pipeline_adapter_type adapter);
void set_done_callback(std::function<void()> f) noexcept void set_done_callback(std::function<void()> f) noexcept { done_ = std::move(f); };
{ done_ = std::move(f); };
auto notify_done() noexcept auto notify_done() noexcept { done_(); }
{ done_(); }
auto notify_error(system::error_code ec) noexcept -> void; auto notify_error(system::error_code ec) noexcept -> void;
[[nodiscard]] [[nodiscard]]
auto is_waiting() const noexcept auto is_waiting() const noexcept
{ return status_ == status::waiting; } {
return status_ == status::waiting;
}
[[nodiscard]] [[nodiscard]]
auto is_written() const noexcept auto is_written() const noexcept
{ return status_ == status::written; } {
return status_ == status::written;
}
[[nodiscard]] [[nodiscard]]
auto is_staged() const noexcept auto is_staged() const noexcept
{ return status_ == status::staged; } {
return status_ == status::staged;
}
void mark_written() noexcept void mark_written() noexcept { status_ = status::written; }
{ status_ = status::written; }
void mark_staged() noexcept void mark_staged() noexcept { status_ = status::staged; }
{ status_ = status::staged; }
void mark_waiting() noexcept void mark_waiting() noexcept { status_ = status::waiting; }
{ status_ = status::waiting; }
auto get_error() const -> system::error_code const& auto get_error() const -> system::error_code const& { return ec_; }
{ return ec_; }
auto get_request() const -> request const& auto get_request() const -> request const& { return *req_; }
{ return *req_; }
auto get_read_size() const -> std::size_t auto get_read_size() const -> std::size_t { return read_size_; }
{ return read_size_; }
auto get_remaining_responses() const -> std::size_t auto get_remaining_responses() const -> std::size_t { return remaining_responses_; }
{ return remaining_responses_; }
auto commit_response(std::size_t read_size) -> void; auto commit_response(std::size_t read_size) -> void;
auto get_adapter() -> adapter_type& auto get_adapter() -> adapter_type& { return adapter_; }
{ return adapter_; }
private: private:
enum class status enum class status
{ waiting {
, staged waiting,
, written staged,
written
}; };
request const* req_; request const* req_;
@@ -124,7 +121,9 @@ struct multiplexer {
[[nodiscard]] [[nodiscard]]
auto const& get_parser() const noexcept auto const& get_parser() const noexcept
{ return parser_; } {
return parser_;
}
//[[nodiscard]] //[[nodiscard]]
auto cancel_waiting() -> std::size_t; auto cancel_waiting() -> std::size_t;
@@ -134,19 +133,27 @@ struct multiplexer {
[[nodiscard]] [[nodiscard]]
auto get_cancel_run_state() const noexcept -> bool auto get_cancel_run_state() const noexcept -> bool
{ return cancel_run_called_; } {
return cancel_run_called_;
}
[[nodiscard]] [[nodiscard]]
auto get_write_buffer() noexcept -> std::string_view auto get_write_buffer() noexcept -> std::string_view
{ return std::string_view{write_buffer_}; } {
return std::string_view{write_buffer_};
}
[[nodiscard]] [[nodiscard]]
auto get_read_buffer() noexcept -> std::string& auto get_read_buffer() noexcept -> std::string&
{ return read_buffer_; } {
return read_buffer_;
}
[[nodiscard]] [[nodiscard]]
auto is_data_needed() const noexcept -> bool auto is_data_needed() const noexcept -> bool
{ return std::empty(read_buffer_); } {
return std::empty(read_buffer_);
}
// TODO: Change signature to receive an adapter instead of a // TODO: Change signature to receive an adapter instead of a
// response. // response.
@@ -160,7 +167,9 @@ struct multiplexer {
[[nodiscard]] [[nodiscard]]
auto get_usage() const noexcept -> usage auto get_usage() const noexcept -> usage
{ return usage_;} {
return usage_;
}
[[nodiscard]] [[nodiscard]]
auto is_writing() const noexcept -> bool; auto is_writing() const noexcept -> bool;
@@ -189,12 +198,10 @@ private:
adapter_type receive_adapter_; adapter_type receive_adapter_;
}; };
auto auto make_elem(request const& req, multiplexer::pipeline_adapter_type adapter)
make_elem( -> std::shared_ptr<multiplexer::elem>;
request const& req,
multiplexer::pipeline_adapter_type adapter) -> std::shared_ptr<multiplexer::elem>;
} // detail } // namespace detail
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_MULTIPLEXER_HPP #endif // BOOST_REDIS_MULTIPLEXER_HPP

View File

@@ -9,15 +9,16 @@
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/asio/cancel_after.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/cancel_after.hpp>
#include <string>
#include <chrono>
namespace boost::redis::detail #include <chrono>
{ #include <string>
namespace boost::redis::detail {
template <class Resolver> template <class Resolver>
struct resolve_op { struct resolve_op {
@@ -25,9 +26,10 @@ struct resolve_op {
asio::coroutine coro{}; asio::coroutine coro{};
template <class Self> template <class Self>
void operator()( Self& self void operator()(
, system::error_code ec = {} Self& self,
, asio::ip::tcp::resolver::results_type res = {}) system::error_code ec = {},
asio::ip::tcp::resolver::results_type res = {})
{ {
BOOST_ASIO_CORO_REENTER(coro) BOOST_ASIO_CORO_REENTER(coro)
{ {
@@ -51,22 +53,22 @@ struct resolve_op {
template <class Executor> template <class Executor>
class resolver { class resolver {
public: public:
resolver(Executor ex) : resv_{ex} {} resolver(Executor ex)
: resv_{ex}
{ }
template <class CompletionToken> template <class CompletionToken>
auto async_resolve(CompletionToken&& token) auto async_resolve(CompletionToken&& token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken resolve_op<resolver>{this},
, void(system::error_code) token,
>(resolve_op<resolver>{this}, token, resv_); resv_);
} }
void cancel() void cancel() { resv_.cancel(); }
{ resv_.cancel(); }
auto const& results() const noexcept auto const& results() const noexcept { return results_; }
{ return results_;}
void set_config(config const& cfg) void set_config(config const& cfg)
{ {
@@ -84,6 +86,6 @@ private:
asio::ip::tcp::resolver::results_type results_; asio::ip::tcp::resolver::results_type results_;
}; };
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_RESOLVER_HPP #endif // BOOST_REDIS_RESOLVER_HPP

View File

@@ -8,20 +8,20 @@
#define BOOST_REDIS_RUNNER_HPP #define BOOST_REDIS_RUNNER_HPP
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/redis/operation.hpp> #include <boost/redis/operation.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
//#include <boost/asio/ip/tcp.hpp> //#include <boost/asio/ip/tcp.hpp>
#include <string>
#include <memory>
#include <chrono> #include <chrono>
#include <memory>
#include <string>
namespace boost::redis::detail namespace boost::redis::detail {
{
void push_hello(config const& cfg, request& req); void push_hello(config const& cfg, request& req);
@@ -43,7 +43,10 @@ struct hello_op {
handshaker_->add_hello(); handshaker_->add_hello();
BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD
conn_->async_exec(handshaker_->hello_req_, any_adapter(handshaker_->hello_resp_), std::move(self)); conn_->async_exec(
handshaker_->hello_req_,
any_adapter(handshaker_->hello_resp_),
std::move(self));
logger_.on_hello(ec, handshaker_->hello_resp_); logger_.on_hello(ec, handshaker_->hello_resp_);
if (ec) { if (ec) {
@@ -66,16 +69,15 @@ struct hello_op {
template <class Executor> template <class Executor>
class resp3_handshaker { class resp3_handshaker {
public: public:
void set_config(config const& cfg) void set_config(config const& cfg) { cfg_ = cfg; }
{ cfg_ = cfg; }
template <class Connection, class Logger, class CompletionToken> template <class Connection, class Logger, class CompletionToken>
auto async_hello(Connection& conn, Logger l, CompletionToken token) auto async_hello(Connection& conn, Logger l, CompletionToken token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken hello_op<resp3_handshaker, Connection, Logger>{this, &conn, l},
, void(system::error_code) token,
>(hello_op<resp3_handshaker, Connection, Logger>{this, &conn, l}, token, conn); conn);
} }
private: private:
@@ -94,8 +96,7 @@ private:
if (!hello_resp_.has_value()) if (!hello_resp_.has_value())
return true; return true;
auto f = [](auto const& e) auto f = [](auto const& e) {
{
switch (e.data_type) { switch (e.data_type) {
case resp3::type::simple_error: case resp3::type::simple_error:
case resp3::type::blob_error: return true; case resp3::type::blob_error: return true;
@@ -111,6 +112,6 @@ private:
config cfg_; config cfg_;
}; };
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_RUNNER_HPP #endif // BOOST_REDIS_RUNNER_HPP

View File

@@ -9,26 +9,27 @@
#include <boost/redis/adapter/any_adapter.hpp> #include <boost/redis/adapter/any_adapter.hpp>
#include <boost/redis/config.hpp> #include <boost/redis/config.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/redis/detail/helper.hpp> #include <boost/redis/detail/helper.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/redis/operation.hpp> #include <boost/redis/operation.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/cancel_after.hpp>
#include <boost/asio/compose.hpp> #include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp> #include <boost/asio/coroutine.hpp>
#include <boost/asio/experimental/parallel_group.hpp> #include <boost/asio/experimental/parallel_group.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/prepend.hpp> #include <boost/asio/prepend.hpp>
#include <boost/asio/ssl.hpp> #include <boost/asio/ssl.hpp>
#include <boost/asio/cancel_after.hpp> #include <boost/asio/steady_timer.hpp>
#include <string>
#include <memory>
#include <chrono>
namespace boost::redis::detail #include <chrono>
{ #include <memory>
#include <string>
namespace boost::redis::detail {
void push_hello(config const& cfg, request& req); void push_hello(config const& cfg, request& req);
@@ -88,13 +89,14 @@ public:
{ } { }
template <class Self> template <class Self>
void operator()( Self& self void operator()(
, order_t order = {} Self& self,
, system::error_code ec0 = {} order_t order = {},
, system::error_code ec1 = {} system::error_code ec0 = {},
, system::error_code ec2 = {} system::error_code ec1 = {},
, system::error_code ec3 = {} system::error_code ec2 = {},
, system::error_code ec4 = {}) system::error_code ec3 = {},
system::error_code ec4 = {})
{ {
BOOST_ASIO_CORO_REENTER(coro_) for (;;) BOOST_ASIO_CORO_REENTER(coro_) for (;;)
{ {
@@ -126,13 +128,8 @@ public:
conn_->next_layer().async_handshake( conn_->next_layer().async_handshake(
asio::ssl::stream_base::client, asio::ssl::stream_base::client,
asio::prepend( asio::prepend(
asio::cancel_after( asio::cancel_after(runner_->cfg_.ssl_handshake_timeout, std::move(self)),
runner_->cfg_.ssl_handshake_timeout, order_t{}));
std::move(self)
),
order_t {}
)
);
logger_.on_ssl_handshake(ec0); logger_.on_ssl_handshake(ec0);
@@ -149,14 +146,22 @@ public:
// causing an authentication problem. // causing an authentication problem.
BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD
asio::experimental::make_parallel_group( asio::experimental::make_parallel_group(
[this](auto token) { return runner_->async_hello(*conn_, logger_, token); }, [this](auto token) {
[this](auto token) { return conn_->health_checker_.async_ping(*conn_, logger_, token); }, return runner_->async_hello(*conn_, logger_, token);
[this](auto token) { return conn_->health_checker_.async_check_timeout(*conn_, logger_, token);}, },
[this](auto token) { return conn_->reader(logger_, token);}, [this](auto token) {
[this](auto token) { return conn_->writer(logger_, token);} return conn_->health_checker_.async_ping(*conn_, logger_, token);
).async_wait( },
asio::experimental::wait_for_one_error(), [this](auto token) {
std::move(self)); return conn_->health_checker_.async_check_timeout(*conn_, logger_, token);
},
[this](auto token) {
return conn_->reader(logger_, token);
},
[this](auto token) {
return conn_->writer(logger_, token);
})
.async_wait(asio::experimental::wait_for_one_error(), std::move(self));
if (order[0] == 0 && !!ec0) { if (order[0] == 0 && !!ec0) {
self.complete(ec0); self.complete(ec0);
@@ -207,32 +212,28 @@ public:
: cfg_{cfg} : cfg_{cfg}
{ } { }
void set_config(config const& cfg) void set_config(config const& cfg) { cfg_ = cfg; }
{
cfg_ = cfg;
}
template <class Connection, class Logger, class CompletionToken> template <class Connection, class Logger, class CompletionToken>
auto async_run(Connection& conn, Logger l, CompletionToken token) auto async_run(Connection& conn, Logger l, CompletionToken token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken runner_op<runner, Connection, Logger>{this, &conn, l},
, void(system::error_code) token,
>(runner_op<runner, Connection, Logger>{this, &conn, l}, token, conn); conn);
} }
private: private:
template <class, class, class> friend class runner_op; template <class, class, class> friend class runner_op;
template <class, class, class> friend struct hello_op; template <class, class, class> friend struct hello_op;
template <class Connection, class Logger, class CompletionToken> template <class Connection, class Logger, class CompletionToken>
auto async_hello(Connection& conn, Logger l, CompletionToken token) auto async_hello(Connection& conn, Logger l, CompletionToken token)
{ {
return asio::async_compose return asio::async_compose<CompletionToken, void(system::error_code)>(
< CompletionToken hello_op<runner, Connection, Logger>{this, &conn, l},
, void(system::error_code) token,
>(hello_op<runner, Connection, Logger>{this, &conn, l}, token, conn); conn);
} }
void add_hello() void add_hello()
@@ -248,8 +249,7 @@ private:
if (!hello_resp_.has_value()) if (!hello_resp_.has_value())
return true; return true;
auto f = [](auto const& e) auto f = [](auto const& e) {
{
switch (e.data_type) { switch (e.data_type) {
case resp3::type::simple_error: case resp3::type::simple_error:
case resp3::type::blob_error: return true; case resp3::type::blob_error: return true;
@@ -265,6 +265,6 @@ private:
config cfg_; config cfg_;
}; };
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_RUNNER_HPP #endif // BOOST_REDIS_RUNNER_HPP

View File

@@ -7,9 +7,10 @@
#ifndef BOOST_REDIS_WRITE_HPP #ifndef BOOST_REDIS_WRITE_HPP
#define BOOST_REDIS_WRITE_HPP #define BOOST_REDIS_WRITE_HPP
#include <boost/asio/write.hpp>
#include <boost/redis/request.hpp> #include <boost/redis/request.hpp>
#include <boost/asio/write.hpp>
namespace boost::redis::detail { namespace boost::redis::detail {
/** \brief Writes a request synchronously. /** \brief Writes a request synchronously.
@@ -39,8 +40,8 @@ auto write(SyncWriteStream& stream, request const& req, system::error_code& ec)
*/ */
template < template <
class AsyncWriteStream, class AsyncWriteStream,
class CompletionToken = asio::default_completion_token_t<typename AsyncWriteStream::executor_type> class CompletionToken =
> asio::default_completion_token_t<typename AsyncWriteStream::executor_type> >
auto async_write( auto async_write(
AsyncWriteStream& stream, AsyncWriteStream& stream,
request const& req, request const& req,
@@ -50,6 +51,6 @@ auto async_write(
return asio::async_write(stream, asio::buffer(req.payload()), token); return asio::async_write(stream, asio::buffer(req.payload()), token);
} }
} // boost::redis::detail } // namespace boost::redis::detail
#endif // BOOST_REDIS_WRITE_HPP #endif // BOOST_REDIS_WRITE_HPP

View File

@@ -93,13 +93,13 @@ enum class error
*/ */
auto make_error_code(error e) -> system::error_code; auto make_error_code(error e) -> system::error_code;
} // boost::redis } // namespace boost::redis
namespace std { namespace std {
template <> template <>
struct is_error_code_enum<::boost::redis::error> : std::true_type { }; struct is_error_code_enum<::boost::redis::error> : std::true_type { };
} // std } // namespace std
#endif // BOOST_REDIS_ERROR_HPP #endif // BOOST_REDIS_ERROR_HPP

View File

@@ -13,8 +13,7 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
namespace boost::redis namespace boost::redis {
{
/** @brief Type used to ignore responses. /** @brief Type used to ignore responses.
* @ingroup high-level-api * @ingroup high-level-api
@@ -44,6 +43,6 @@ using ignore_t = std::decay_t<decltype(std::ignore)>;
*/ */
extern ignore_t ignore; extern ignore_t ignore;
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_IGNORE_HPP #endif // BOOST_REDIS_IGNORE_HPP

View File

@@ -5,6 +5,7 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <cstddef> #include <cstddef>
namespace boost::redis { namespace boost::redis {
@@ -17,8 +18,7 @@ connection::connection(asio::io_context& ioc, asio::ssl::context ctx)
: impl_{ioc.get_executor(), std::move(ctx)} : impl_{ioc.get_executor(), std::move(ctx)}
{ } { }
void void connection::async_run_impl(
connection::async_run_impl(
config const& cfg, config const& cfg,
logger l, logger l,
asio::any_completion_handler<void(boost::system::error_code)> token) asio::any_completion_handler<void(boost::system::error_code)> token)
@@ -26,8 +26,7 @@ connection::async_run_impl(
impl_.async_run(cfg, l, std::move(token)); impl_.async_run(cfg, l, std::move(token));
} }
void void connection::async_exec_impl(
connection::async_exec_impl(
request const& req, request const& req,
any_adapter&& adapter, any_adapter&& adapter,
asio::any_completion_handler<void(boost::system::error_code, std::size_t)> token) asio::any_completion_handler<void(boost::system::error_code, std::size_t)> token)
@@ -35,9 +34,6 @@ connection::async_exec_impl(
impl_.async_exec(req, std::move(adapter), std::move(token)); impl_.async_exec(req, std::move(adapter), std::move(token));
} }
void connection::cancel(operation op) void connection::cancel(operation op) { impl_.cancel(op); }
{
impl_.cancel(op);
}
} // namespace boost::redis } // namespace boost::redis

View File

@@ -5,26 +5,25 @@
*/ */
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
namespace boost::redis { namespace boost::redis {
namespace detail { namespace detail {
struct error_category_impl : system::error_category { struct error_category_impl : system::error_category {
virtual ~error_category_impl() = default; virtual ~error_category_impl() = default;
auto name() const noexcept -> char const* override auto name() const noexcept -> char const* override { return "boost.redis"; }
{
return "boost.redis";
}
auto message(int ev) const -> std::string override auto message(int ev) const -> std::string override
{ {
switch (static_cast<error>(ev)) { switch (static_cast<error>(ev)) {
case error::invalid_data_type: return "Invalid resp3 type."; case error::invalid_data_type: return "Invalid resp3 type.";
case error::not_a_number: return "Can't convert string to number (maybe forgot to upgrade to RESP3?)."; case error::not_a_number:
case error::exceeeds_max_nested_depth: return "Exceeds the maximum number of nested responses."; return "Can't convert string to number (maybe forgot to upgrade to RESP3?).";
case error::exceeeds_max_nested_depth:
return "Exceeds the maximum number of nested responses.";
case error::unexpected_bool_value: return "Unexpected bool value."; case error::unexpected_bool_value: return "Unexpected bool value.";
case error::empty_field: return "Expected field value is empty."; case error::empty_field: return "Expected field value is empty.";
case error::expects_resp3_simple_type: return "Expects a resp3 simple type."; case error::expects_resp3_simple_type: return "Expects a resp3 simple type.";
@@ -42,7 +41,8 @@ struct error_category_impl : system::error_category {
case error::connect_timeout: return "Connect timeout."; case error::connect_timeout: return "Connect timeout.";
case error::pong_timeout: return "Pong timeout."; case error::pong_timeout: return "Pong timeout.";
case error::ssl_handshake_timeout: return "SSL handshake timeout."; case error::ssl_handshake_timeout: return "SSL handshake timeout.";
case error::sync_receive_push_failed: return "Can't receive server push synchronously without blocking."; case error::sync_receive_push_failed:
return "Can't receive server push synchronously without blocking.";
case error::incompatible_node_depth: return "Incompatible node depth."; case error::incompatible_node_depth: return "Incompatible node depth.";
case error::resp3_hello: return "RESP3 handshake error (hello command)."; case error::resp3_hello: return "RESP3 handshake error (hello command).";
default: BOOST_ASSERT(false); return "Boost.Redis error."; default: BOOST_ASSERT(false); return "Boost.Redis error.";
@@ -56,11 +56,11 @@ auto category() -> system::error_category const&
return instance; return instance;
} }
} // detail } // namespace detail
auto make_error_code(error e) -> system::error_code auto make_error_code(error e) -> system::error_code
{ {
return system::error_code{static_cast<int>(e), detail::category()}; return system::error_code{static_cast<int>(e), detail::category()};
} }
} // boost::redis::detail } // namespace boost::redis

View File

@@ -6,7 +6,6 @@
#include <boost/redis/ignore.hpp> #include <boost/redis/ignore.hpp>
namespace boost::redis namespace boost::redis {
{
ignore_t ignore; ignore_t ignore;
} }

View File

@@ -5,12 +5,13 @@
*/ */
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
namespace boost::redis namespace boost::redis {
{
void logger::write_prefix() void logger::write_prefix()
{ {
@@ -18,7 +19,9 @@ void logger::write_prefix()
std::clog << prefix_; std::clog << prefix_;
} }
void logger::on_resolve(system::error_code const& ec, asio::ip::tcp::resolver::results_type const& res) void logger::on_resolve(
system::error_code const& ec,
asio::ip::tcp::resolver::results_type const& res)
{ {
if (level_ < level::info) if (level_ < level::info)
return; return;
@@ -71,10 +74,7 @@ void logger::on_ssl_handshake(system::error_code const& ec)
std::clog << "SSL handshake: " << ec.message() << std::endl; std::clog << "SSL handshake: " << ec.message() << std::endl;
} }
void void logger::on_write(system::error_code const& ec, std::string_view payload)
logger::on_write(
system::error_code const& ec,
std::string_view payload)
{ {
if (level_ < level::info) if (level_ < level::info)
return; return;
@@ -104,10 +104,7 @@ void logger::on_read(system::error_code const& ec, std::size_t n)
std::clog << std::endl; std::clog << std::endl;
} }
void void logger::on_hello(system::error_code const& ec, generic_response const& resp)
logger::on_hello(
system::error_code const& ec,
generic_response const& resp)
{ {
if (level_ < level::info) if (level_ < level::info)
return; return;
@@ -145,4 +142,4 @@ void logger::trace(std::string_view op, system::error_code const& ec)
std::clog << op << ": " << ec.message() << std::endl; std::clog << op << ": " << ec.message() << std::endl;
} }
} // boost::redis } // namespace boost::redis

View File

@@ -9,8 +9,7 @@
#include <memory> #include <memory>
namespace boost::redis::detail namespace boost::redis::detail {
{
multiplexer::elem::elem(request const& req, pipeline_adapter_type adapter) multiplexer::elem::elem(request const& req, pipeline_adapter_type adapter)
: req_{&req} : req_{&req}
@@ -20,8 +19,7 @@ multiplexer::elem::elem(request const& req, pipeline_adapter_type adapter)
, ec_{{}} , ec_{{}}
, read_size_{0} , read_size_{0}
{ {
adapter_ = [this, adapter](resp3::node_view const& nd, system::error_code& ec) adapter_ = [this, adapter](resp3::node_view const& nd, system::error_code& ec) {
{
auto const i = req_->get_expected_responses() - remaining_responses_; auto const i = req_->get_expected_responses() - remaining_responses_;
adapter(i, nd, ec); adapter(i, nd, ec);
}; };
@@ -75,8 +73,7 @@ void multiplexer::add(std::shared_ptr<elem> const& info)
reqs_.push_back(info); reqs_.push_back(info);
if (info->get_request().has_hello_priority()) { if (info->get_request().has_hello_priority()) {
auto rend = auto rend = std::partition_point(std::rbegin(reqs_), std::rend(reqs_), [](auto const& e) {
std::partition_point(std::rbegin(reqs_), std::rend(reqs_), [](auto const& e) {
return e->is_waiting(); return e->is_waiting();
}); });
@@ -84,8 +81,7 @@ void multiplexer::add(std::shared_ptr<elem> const& info)
} }
} }
std::pair<tribool, std::size_t> std::pair<tribool, std::size_t> multiplexer::commit_read(system::error_code& ec)
multiplexer::commit_read(system::error_code& ec)
{ {
// We arrive here in two states: // We arrive here in two states:
// //
@@ -111,7 +107,9 @@ multiplexer::commit_read(system::error_code& ec)
return std::make_pair(std::make_optional(true), size); return std::make_pair(std::make_optional(true), size);
} }
BOOST_ASSERT_MSG(is_waiting_response(), "Not waiting for a response (using MONITOR command perhaps?)"); BOOST_ASSERT_MSG(
is_waiting_response(),
"Not waiting for a response (using MONITOR command perhaps?)");
BOOST_ASSERT(!reqs_.empty()); BOOST_ASSERT(!reqs_.empty());
BOOST_ASSERT(reqs_.front() != nullptr); BOOST_ASSERT(reqs_.front() != nullptr);
BOOST_ASSERT(reqs_.front()->get_remaining_responses() != 0); BOOST_ASSERT(reqs_.front()->get_remaining_responses() != 0);
@@ -148,8 +146,10 @@ std::size_t multiplexer::prepare_write()
{ {
// Coalesces the requests and marks them staged. After a // Coalesces the requests and marks them staged. After a
// successful write staged requests will be marked as written. // successful write staged requests will be marked as written.
auto const point = auto const point = std::partition_point(
std::partition_point(std::cbegin(reqs_), std::cend(reqs_), [](auto const& ri) { std::cbegin(reqs_),
std::cend(reqs_),
[](auto const& ri) {
return !ri->is_waiting(); return !ri->is_waiting();
}); });
@@ -166,11 +166,9 @@ std::size_t multiplexer::prepare_write()
return static_cast<std::size_t>(d); return static_cast<std::size_t>(d);
} }
std::size_t multiplexer::cancel_waiting() std::size_t multiplexer::cancel_waiting()
{ {
auto f = [](auto const& ptr) auto f = [](auto const& ptr) {
{
BOOST_ASSERT(ptr != nullptr); BOOST_ASSERT(ptr != nullptr);
return !ptr->is_waiting(); return !ptr->is_waiting();
}; };
@@ -196,8 +194,7 @@ auto multiplexer::cancel_on_conn_lost() -> std::size_t
} }
// Must return false if the request should be removed. // Must return false if the request should be removed.
auto cond = [](auto const& ptr) auto cond = [](auto const& ptr) {
{
BOOST_ASSERT(ptr != nullptr); BOOST_ASSERT(ptr != nullptr);
if (ptr->is_waiting()) { if (ptr->is_waiting()) {
@@ -305,17 +302,12 @@ bool multiplexer::is_waiting_response() const noexcept
return !reqs_.front()->is_waiting(); return !reqs_.front()->is_waiting();
} }
bool multiplexer::is_writing() const noexcept bool multiplexer::is_writing() const noexcept { return !write_buffer_.empty(); }
{
return !write_buffer_.empty();
}
auto auto make_elem(request const& req, multiplexer::pipeline_adapter_type adapter)
make_elem( -> std::shared_ptr<multiplexer::elem>
request const& req,
multiplexer::pipeline_adapter_type adapter) -> std::shared_ptr<multiplexer::elem>
{ {
return std::make_shared<multiplexer::elem>(req, std::move(adapter)); return std::make_shared<multiplexer::elem>(req, std::move(adapter));
} }
} } // namespace boost::redis::detail

View File

@@ -12,10 +12,13 @@ namespace boost::redis::detail {
auto has_response(std::string_view cmd) -> bool auto has_response(std::string_view cmd) -> bool
{ {
if (cmd == "SUBSCRIBE") return true; if (cmd == "SUBSCRIBE")
if (cmd == "PSUBSCRIBE") return true; return true;
if (cmd == "UNSUBSCRIBE") return true; if (cmd == "PSUBSCRIBE")
return true;
if (cmd == "UNSUBSCRIBE")
return true;
return false; return false;
} }
} // boost:redis::detail } // namespace boost::redis::detail

View File

@@ -6,8 +6,7 @@
#include <boost/redis/detail/resp3_handshaker.hpp> #include <boost/redis/detail/resp3_handshaker.hpp>
namespace boost::redis::detail namespace boost::redis::detail {
{
void push_hello(config const& cfg, request& req) void push_hello(config const& cfg, request& req)
{ {
@@ -24,4 +23,4 @@ void push_hello(config const& cfg, request& req)
req.push("SELECT", cfg.database_index.value()); req.push("SELECT", cfg.database_index.value());
} }
} // boost::redis::detail } // namespace boost::redis::detail

View File

@@ -4,12 +4,12 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/response.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/response.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
namespace boost::redis namespace boost::redis {
{
void consume_one(generic_response& r, system::error_code& ec) void consume_one(generic_response& r, system::error_code& ec)
{ {
@@ -29,8 +29,9 @@ void consume_one(generic_response& r, system::error_code& ec)
return; return;
} }
auto f = [depth](auto const& e) auto f = [depth](auto const& e) {
{ return e.depth == depth; }; return e.depth == depth;
};
auto match = std::find_if(std::next(std::cbegin(r.value())), std::cend(r.value()), f); auto match = std::find_if(std::next(std::cbegin(r.value())), std::cend(r.value()), f);
@@ -45,4 +46,4 @@ void consume_one(generic_response& r)
throw system::system_error(ec); throw system::system_error(ec);
} }
} // boost::redis::resp3 } // namespace boost::redis

View File

@@ -8,10 +8,14 @@
#define BOOST_REDIS_LOGGER_HPP #define BOOST_REDIS_LOGGER_HPP
#include <boost/redis/response.hpp> #include <boost/redis/response.hpp>
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <string> #include <string>
namespace boost::system {class error_code;} namespace boost::system {
class error_code;
}
namespace boost::redis { namespace boost::redis {
@@ -120,10 +124,7 @@ public:
* *
* @param prefix The prefix. * @param prefix The prefix.
*/ */
void set_prefix(std::string_view prefix) void set_prefix(std::string_view prefix) { prefix_ = prefix; }
{
prefix_ = prefix;
}
void trace(std::string_view message); void trace(std::string_view message);
void trace(std::string_view op, system::error_code const& ec); void trace(std::string_view op, system::error_code const& ec);
@@ -134,6 +135,6 @@ private:
std::string_view prefix_; std::string_view prefix_;
}; };
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_LOGGER_HPP #endif // BOOST_REDIS_LOGGER_HPP

View File

@@ -15,7 +15,8 @@ namespace boost::redis {
* The operations listed below can be passed to the * The operations listed below can be passed to the
* `boost::redis::connection::cancel` member function. * `boost::redis::connection::cancel` member function.
*/ */
enum class operation { enum class operation
{
/// Resolve operation. /// Resolve operation.
resolve, resolve,
/// Connect operation. /// Connect operation.
@@ -36,6 +37,6 @@ enum class operation {
all, all,
}; };
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_OPERATION_HPP #endif // BOOST_REDIS_OPERATION_HPP

View File

@@ -7,12 +7,12 @@
#ifndef BOOST_REDIS_REQUEST_HPP #ifndef BOOST_REDIS_REQUEST_HPP
#define BOOST_REDIS_REQUEST_HPP #define BOOST_REDIS_REQUEST_HPP
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/resp3/serialization.hpp> #include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/type.hpp>
#include <algorithm>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <algorithm>
// NOTE: For some commands like hset it would be a good idea to assert // NOTE: For some commands like hset it would be a good idea to assert
// the value type is a pair. // the value type is a pair.
@@ -80,23 +80,25 @@ public:
* *
* \param cfg Configuration options. * \param cfg Configuration options.
*/ */
explicit explicit request(config cfg = config{true, false, true, true})
request(config cfg = config{true, false, true, true}) : cfg_{cfg}
: cfg_{cfg} {} { }
//// Returns the number of responses expected for this request. //// Returns the number of responses expected for this request.
[[nodiscard]] auto get_expected_responses() const noexcept -> std::size_t [[nodiscard]] auto get_expected_responses() const noexcept -> std::size_t
{ return expected_responses_;}; {
return expected_responses_;
};
//// Returns the number of commands contained in this request. //// Returns the number of commands contained in this request.
[[nodiscard]] auto get_commands() const noexcept -> std::size_t [[nodiscard]] auto get_commands() const noexcept -> std::size_t { return commands_; };
{ return commands_;};
[[nodiscard]] auto payload() const noexcept -> std::string_view [[nodiscard]] auto payload() const noexcept -> std::string_view { return payload_; }
{ return payload_;}
[[nodiscard]] auto has_hello_priority() const noexcept -> auto const& [[nodiscard]] auto has_hello_priority() const noexcept -> auto const&
{ return has_hello_priority_;} {
return has_hello_priority_;
}
/// Clears the request preserving allocated memory. /// Clears the request preserving allocated memory.
void clear() void clear()
@@ -108,8 +110,7 @@ public:
} }
/// Calls std::string::reserve on the internal storage. /// Calls std::string::reserve on the internal storage.
void reserve(std::size_t new_cap = 0) void reserve(std::size_t new_cap = 0) { payload_.reserve(new_cap); }
{ payload_.reserve(new_cap); }
/// Returns a const reference to the config object. /// Returns a const reference to the config object.
[[nodiscard]] auto get_config() const noexcept -> auto const& { return cfg_; } [[nodiscard]] auto get_config() const noexcept -> auto const& { return cfg_; }
@@ -185,8 +186,7 @@ public:
* See cpp20_serialization.cpp * See cpp20_serialization.cpp
*/ */
template <class ForwardIterator> template <class ForwardIterator>
void void push_range(
push_range(
std::string_view const& cmd, std::string_view const& cmd,
std::string_view const& key, std::string_view const& key,
ForwardIterator begin, ForwardIterator begin,
@@ -238,8 +238,7 @@ public:
* See cpp20_serialization.cpp * See cpp20_serialization.cpp
*/ */
template <class ForwardIterator> template <class ForwardIterator>
void void push_range(
push_range(
std::string_view const& cmd, std::string_view const& cmd,
ForwardIterator begin, ForwardIterator begin,
ForwardIterator end, ForwardIterator end,
@@ -272,8 +271,7 @@ public:
* \tparam A type that can be passed to `std::cbegin()` and `std::cend()`. * \tparam A type that can be passed to `std::cbegin()` and `std::cend()`.
*/ */
template <class Range> template <class Range>
void void push_range(
push_range(
std::string_view const& cmd, std::string_view const& cmd,
std::string_view const& key, std::string_view const& key,
Range const& range, Range const& range,
@@ -294,8 +292,7 @@ public:
* \tparam A type that can be passed to `std::cbegin()` and `std::cend()`. * \tparam A type that can be passed to `std::cbegin()` and `std::cend()`.
*/ */
template <class Range> template <class Range>
void void push_range(
push_range(
std::string_view cmd, std::string_view cmd,
Range const& range, Range const& range,
decltype(std::cbegin(range))* = nullptr) decltype(std::cbegin(range))* = nullptr)
@@ -324,6 +321,6 @@ private:
bool has_hello_priority_ = false; bool has_hello_priority_ = false;
}; };
} // boost::redis::resp3 } // namespace boost::redis
#endif // BOOST_REDIS_REQUEST_HPP #endif // BOOST_REDIS_REQUEST_HPP

View File

@@ -4,8 +4,9 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/resp3/parser.hpp>
#include <boost/redis/error.hpp> #include <boost/redis/error.hpp>
#include <boost/redis/resp3/parser.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <charconv> #include <charconv>
@@ -20,10 +21,7 @@ void to_int(std::size_t& i, std::string_view sv, system::error_code& ec)
ec = error::not_a_number; ec = error::not_a_number;
} }
parser::parser() parser::parser() { reset(); }
{
reset();
}
void parser::reset() void parser::reset()
{ {
@@ -35,8 +33,7 @@ void parser::reset()
sizes_[0] = 2; // The sentinel must be more than 1. sizes_[0] = 2; // The sentinel must be more than 1.
} }
std::size_t std::size_t parser::get_suggested_buffer_growth(std::size_t hint) const noexcept
parser::get_suggested_buffer_growth(std::size_t hint) const noexcept
{ {
if (!bulk_expected()) if (!bulk_expected())
return hint; return hint;
@@ -47,20 +44,14 @@ parser::get_suggested_buffer_growth(std::size_t hint) const noexcept
return hint; return hint;
} }
std::size_t std::size_t parser::get_consumed() const noexcept { return consumed_; }
parser::get_consumed() const noexcept
{
return consumed_;
}
bool bool parser::done() const noexcept
parser::done() const noexcept
{ {
return depth_ == 0 && bulk_ == type::invalid && consumed_ != 0; return depth_ == 0 && bulk_ == type::invalid && consumed_ != 0;
} }
void void parser::commit_elem() noexcept
parser::commit_elem() noexcept
{ {
--sizes_[depth_]; --sizes_[depth_];
while (sizes_[depth_] == 0) { while (sizes_[depth_] == 0) {
@@ -69,8 +60,7 @@ parser::commit_elem() noexcept
} }
} }
auto auto parser::consume(std::string_view view, system::error_code& ec) noexcept -> parser::result
parser::consume(std::string_view view, system::error_code& ec) noexcept -> parser::result
{ {
switch (bulk_) { switch (bulk_) {
case type::invalid: case type::invalid:
@@ -88,8 +78,8 @@ parser::consume(std::string_view view, system::error_code& ec) noexcept -> parse
consumed_ = pos + 2; consumed_ = pos + 2;
if (!bulk_expected()) if (!bulk_expected())
return ret; return ret;
}
} [[fallthrough]]; [[fallthrough]];
default: // Handles bulk. default: // Handles bulk.
{ {
@@ -108,11 +98,8 @@ parser::consume(std::string_view view, system::error_code& ec) noexcept -> parse
} }
} }
auto auto parser::consume_impl(type t, std::string_view elem, system::error_code& ec)
parser::consume_impl( -> parser::node_type
type t,
std::string_view elem,
system::error_code& ec) -> parser::node_type
{ {
BOOST_ASSERT(!bulk_expected()); BOOST_ASSERT(!bulk_expected());
@@ -175,7 +162,8 @@ parser::consume_impl(
ec = error::empty_field; ec = error::empty_field;
return {}; return {};
} }
} [[fallthrough]]; }
[[fallthrough]];
case type::simple_error: case type::simple_error:
case type::simple_string: case type::simple_string:
case type::null: case type::null:
@@ -217,4 +205,4 @@ parser::consume_impl(
return ret; return ret;
} }
} // boost::redis::resp3 } // namespace boost::redis::resp3

View File

@@ -4,8 +4,8 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/parser.hpp> #include <boost/redis/resp3/parser.hpp>
#include <boost/redis/resp3/serialization.hpp>
namespace boost::redis::resp3 { namespace boost::redis::resp3 {
@@ -35,8 +35,5 @@ void add_blob(std::string& payload, std::string_view blob)
payload += parser::sep; payload += parser::sep;
} }
void add_separator(std::string& payload) void add_separator(std::string& payload) { payload += parser::sep; }
{ } // namespace boost::redis::resp3
payload += parser::sep;
}
} // boost::redis::resp3

View File

@@ -5,6 +5,7 @@
*/ */
#include <boost/redis/resp3/type.hpp> #include <boost/redis/resp3/type.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
namespace boost::redis::resp3 { namespace boost::redis::resp3 {
@@ -39,4 +40,4 @@ auto operator<<(std::ostream& os, type t) -> std::ostream&
return os; return os;
} }
} // boost::redis::resp3 } // namespace boost::redis::resp3

View File

@@ -48,10 +48,12 @@ struct basic_node {
template <class String> template <class String>
auto operator==(basic_node<String> const& a, basic_node<String> const& b) auto operator==(basic_node<String> const& a, basic_node<String> const& b)
{ {
// clang-format off
return a.aggregate_size == b.aggregate_size return a.aggregate_size == b.aggregate_size
&& a.depth == b.depth && a.depth == b.depth
&& a.data_type == b.data_type && a.data_type == b.data_type
&& a.value == b.value; && a.value == b.value;
// clang-format on
}; };
/** @brief A node in the response tree that owns its data /** @brief A node in the response tree that owns its data
@@ -64,6 +66,6 @@ using node = basic_node<std::string>;
*/ */
using node_view = basic_node<std::string_view>; using node_view = basic_node<std::string_view>;
} // boost::redis::resp3 } // namespace boost::redis::resp3
#endif // BOOST_REDIS_RESP3_NODE_HPP #endif // BOOST_REDIS_RESP3_NODE_HPP

View File

@@ -8,11 +8,13 @@
#define BOOST_REDIS_RESP3_PARSER_HPP #define BOOST_REDIS_RESP3_PARSER_HPP
#include <boost/redis/resp3/node.hpp> #include <boost/redis/resp3/node.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <array> #include <array>
#include <string_view>
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
#include <string_view>
namespace boost::redis::resp3 { namespace boost::redis::resp3 {
@@ -54,7 +56,9 @@ private:
// returns type::invalid. // returns type::invalid.
[[nodiscard]] [[nodiscard]]
auto bulk_expected() const noexcept -> bool auto bulk_expected() const noexcept -> bool
{ return bulk_ != type::invalid; } {
return bulk_ != type::invalid;
}
public: public:
parser(); parser();
@@ -76,12 +80,7 @@ public:
// parser is either done or an error occured, that can be checked on // parser is either done or an error occured, that can be checked on
// ec. // ec.
template <class Adapter> template <class Adapter>
bool bool parse(resp3::parser& p, std::string_view const& msg, Adapter& adapter, system::error_code& ec)
parse(
resp3::parser& p,
std::string_view const& msg,
Adapter& adapter,
system::error_code& ec)
{ {
while (!p.done()) { while (!p.done()) {
auto const res = p.consume(msg, ec); auto const res = p.consume(msg, ec);
@@ -99,6 +98,6 @@ parse(
return true; return true;
} }
} // boost::redis::resp3 } // namespace boost::redis::resp3
#endif // BOOST_REDIS_RESP3_PARSER_HPP #endif // BOOST_REDIS_RESP3_PARSER_HPP

View File

@@ -7,10 +7,11 @@
#ifndef BOOST_REDIS_RESP3_SERIALIZATION_HPP #ifndef BOOST_REDIS_RESP3_SERIALIZATION_HPP
#define BOOST_REDIS_RESP3_SERIALIZATION_HPP #define BOOST_REDIS_RESP3_SERIALIZATION_HPP
#include <boost/redis/resp3/parser.hpp>
#include <boost/redis/resp3/type.hpp> #include <boost/redis/resp3/type.hpp>
#include <boost/system/system_error.hpp> #include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <boost/redis/resp3/parser.hpp>
#include <string> #include <string>
#include <tuple> #include <tuple>
@@ -61,8 +62,7 @@ template <class ...Ts>
struct add_bulk_impl<std::tuple<Ts...>> { struct add_bulk_impl<std::tuple<Ts...>> {
static void add(std::string& payload, std::tuple<Ts...> const& t) static void add(std::string& payload, std::tuple<Ts...> const& t)
{ {
auto f = [&](auto const&... vs) auto f = [&](auto const&... vs) {
{
using namespace boost::redis::resp3; using namespace boost::redis::resp3;
(boost_redis_to_bulk(payload, vs), ...); (boost_redis_to_bulk(payload, vs), ...);
}; };
@@ -105,8 +105,7 @@ struct bulk_counter<std::pair<T, U>> {
void add_blob(std::string& payload, std::string_view blob); void add_blob(std::string& payload, std::string_view blob);
void add_separator(std::string& payload); void add_separator(std::string& payload);
namespace detail namespace detail {
{
template <class Adapter> template <class Adapter>
void deserialize(std::string_view const& data, Adapter adapter, system::error_code& ec) void deserialize(std::string_view const& data, Adapter adapter, system::error_code& ec)
@@ -137,8 +136,8 @@ void deserialize(std::string_view const& data, Adapter adapter)
BOOST_THROW_EXCEPTION(system::system_error{ec}); BOOST_THROW_EXCEPTION(system::system_error{ec});
} }
} } // namespace detail
} // boost::redis::resp3 } // namespace boost::redis::resp3
#endif // BOOST_REDIS_RESP3_SERIALIZATION_HPP #endif // BOOST_REDIS_RESP3_SERIALIZATION_HPP

View File

@@ -8,9 +8,10 @@
#define BOOST_REDIS_RESP3_TYPE_HPP #define BOOST_REDIS_RESP3_TYPE_HPP
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <ostream> #include <ostream>
#include <vector>
#include <string> #include <string>
#include <vector>
namespace boost::redis::resp3 { namespace boost::redis::resp3 {
@@ -145,6 +146,6 @@ constexpr auto to_type(char c) noexcept -> type
} }
} }
} // boost::redis::resp3 } // namespace boost::redis::resp3
#endif // BOOST_REDIS_RESP3_TYPE_HPP #endif // BOOST_REDIS_RESP3_TYPE_HPP

View File

@@ -7,16 +7,16 @@
#ifndef BOOST_REDIS_RESPONSE_HPP #ifndef BOOST_REDIS_RESPONSE_HPP
#define BOOST_REDIS_RESPONSE_HPP #define BOOST_REDIS_RESPONSE_HPP
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/adapter/result.hpp> #include <boost/redis/adapter/result.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/system.hpp> #include <boost/system.hpp>
#include <vector>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <vector>
namespace boost::redis namespace boost::redis {
{
/** @brief Response with compile-time size. /** @brief Response with compile-time size.
* @ingroup high-level-api * @ingroup high-level-api
@@ -75,6 +75,6 @@ void consume_one(generic_response& r, system::error_code& ec);
/// Throwing overload of `consume_one`. /// Throwing overload of `consume_one`.
void consume_one(generic_response& r); void consume_one(generic_response& r);
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_RESPONSE_HPP #endif // BOOST_REDIS_RESPONSE_HPP

View File

@@ -4,14 +4,14 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/impl/error.ipp>
#include <boost/redis/impl/logger.ipp>
#include <boost/redis/impl/request.ipp>
#include <boost/redis/impl/ignore.ipp>
#include <boost/redis/impl/connection.ipp> #include <boost/redis/impl/connection.ipp>
#include <boost/redis/impl/response.ipp> #include <boost/redis/impl/error.ipp>
#include <boost/redis/impl/resp3_handshaker.ipp> #include <boost/redis/impl/ignore.ipp>
#include <boost/redis/impl/logger.ipp>
#include <boost/redis/impl/multiplexer.ipp> #include <boost/redis/impl/multiplexer.ipp>
#include <boost/redis/resp3/impl/type.ipp> #include <boost/redis/impl/request.ipp>
#include <boost/redis/impl/resp3_handshaker.ipp>
#include <boost/redis/impl/response.ipp>
#include <boost/redis/resp3/impl/parser.ipp> #include <boost/redis/resp3/impl/parser.ipp>
#include <boost/redis/resp3/impl/serialization.ipp> #include <boost/redis/resp3/impl/serialization.ipp>
#include <boost/redis/resp3/impl/type.ipp>

View File

@@ -7,8 +7,7 @@
#ifndef BOOST_REDIS_USAGE_HPP #ifndef BOOST_REDIS_USAGE_HPP
#define BOOST_REDIS_USAGE_HPP #define BOOST_REDIS_USAGE_HPP
namespace boost::redis namespace boost::redis {
{
/** @brief Connection usage information. /** @brief Connection usage information.
* @ingroup high-level-api * @ingroup high-level-api
@@ -38,6 +37,6 @@ struct usage {
std::size_t push_bytes_received = 0; std::size_t push_bytes_received = 0;
}; };
} // boost::redis } // namespace boost::redis
#endif // BOOST_REDIS_USAGE_HPP #endif // BOOST_REDIS_USAGE_HPP

View File

@@ -4,7 +4,6 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/src.hpp> #include <boost/redis/src.hpp>

View File

@@ -4,7 +4,6 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/src.hpp> #include <boost/redis/src.hpp>

View File

@@ -4,7 +4,6 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/src.hpp> #include <boost/redis/src.hpp>

View File

@@ -1,8 +1,10 @@
#include "common.hpp"
#include <iostream>
#include <cstdlib>
#include <boost/asio/consign.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/consign.hpp>
#include "common.hpp"
#include <cstdlib>
#include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
@@ -18,8 +20,7 @@ struct run_callback {
} }
}; };
void void run(
run(
std::shared_ptr<boost::redis::connection> conn, std::shared_ptr<boost::redis::connection> conn,
boost::redis::config cfg, boost::redis::config cfg,
boost::system::error_code ec, boost::system::error_code ec,
@@ -43,10 +44,7 @@ static std::string safe_getenv(const char* name, const char* default_value)
return res ? res : default_value; return res ? res : default_value;
} }
std::string get_server_hostname() std::string get_server_hostname() { return safe_getenv("BOOST_REDIS_TEST_SERVER", "localhost"); }
{
return safe_getenv("BOOST_REDIS_TEST_SERVER", "localhost");
}
boost::redis::config make_test_config() boost::redis::config make_test_config()
{ {

View File

@@ -1,28 +1,29 @@
#pragma once #pragma once
#include <boost/system/error_code.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/operation.hpp> #include <boost/redis/operation.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/system/error_code.hpp>
#include <memory> #include <memory>
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
inline inline auto redir(boost::system::error_code& ec)
auto redir(boost::system::error_code& ec) {
{ return boost::asio::redirect_error(boost::asio::use_awaitable, ec); } return boost::asio::redirect_error(boost::asio::use_awaitable, ec);
}
auto start(boost::asio::awaitable<void> op) -> int; auto start(boost::asio::awaitable<void> op) -> int;
#endif // BOOST_ASIO_HAS_CO_AWAIT #endif // BOOST_ASIO_HAS_CO_AWAIT
boost::redis::config make_test_config(); boost::redis::config make_test_config();
std::string get_server_hostname(); std::string get_server_hostname();
void void run(
run(
std::shared_ptr<boost::redis::connection> conn, std::shared_ptr<boost::redis::connection> conn,
boost::redis::config cfg = make_test_config(), boost::redis::config cfg = make_test_config(),
boost::system::error_code ec = boost::asio::error::operation_aborted, boost::system::error_code ec = boost::asio::error::operation_aborted,
boost::redis::operation op = boost::redis::operation::receive, boost::redis::operation op = boost::redis::operation::receive,
boost::redis::logger::level l = boost::redis::logger::level::debug); boost::redis::logger::level l = boost::redis::logger::level::debug);

View File

@@ -4,9 +4,10 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/adapter/any_adapter.hpp>
#include <boost/redis/ignore.hpp> #include <boost/redis/ignore.hpp>
#include <boost/redis/response.hpp> #include <boost/redis/response.hpp>
#include <boost/redis/adapter/any_adapter.hpp>
#include <string> #include <string>
#define BOOST_TEST_MODULE any_adapter #define BOOST_TEST_MODULE any_adapter
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>

View File

@@ -6,12 +6,15 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/response.hpp> #include <boost/redis/response.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE check-health #define BOOST_TEST_MODULE check_health
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "common.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include "common.hpp"
namespace net = boost::asio; namespace net = boost::asio;
namespace redis = boost::redis; namespace redis = boost::redis;
@@ -122,4 +125,3 @@ BOOST_AUTO_TEST_CASE(check_health)
// to fail. // to fail.
std::this_thread::sleep_for(std::chrono::seconds{10}); std::this_thread::sleep_for(std::chrono::seconds{10});
} }

View File

@@ -5,15 +5,18 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/deferred.hpp> #include <boost/asio/deferred.hpp>
#include <boost/asio/detached.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE echo-stress #define BOOST_TEST_MODULE echo_stress
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
namespace net = boost::asio; namespace net = boost::asio;
@@ -30,8 +33,7 @@ using boost::redis::error;
std::ostream& operator<<(std::ostream& os, usage const& u) std::ostream& operator<<(std::ostream& os, usage const& u)
{ {
os os << "Commands sent: " << u.commands_sent << "\n"
<< "Commands sent: " << u.commands_sent << "\n"
<< "Bytes sent: " << u.bytes_sent << "\n" << "Bytes sent: " << u.bytes_sent << "\n"
<< "Responses received: " << u.responses_received << "\n" << "Responses received: " << u.responses_received << "\n"
<< "Pushes received: " << u.pushes_received << "\n" << "Pushes received: " << u.pushes_received << "\n"
@@ -65,11 +67,8 @@ auto push_consumer(std::shared_ptr<connection> conn, int expected) -> net::await
conn->cancel(); conn->cancel();
} }
auto auto echo_session(std::shared_ptr<connection> conn, std::shared_ptr<request> pubs, int n)
echo_session( -> net::awaitable<void>
std::shared_ptr<connection> conn,
std::shared_ptr<request> pubs,
int n) -> net::awaitable<void>
{ {
for (auto i = 0; i < n; ++i) for (auto i = 0; i < n; ++i)
co_await conn->async_exec(*pubs, ignore, net::deferred); co_await conn->async_exec(*pubs, ignore, net::deferred);
@@ -80,7 +79,9 @@ auto async_echo_stress(std::shared_ptr<connection> conn) -> net::awaitable<void>
auto ex = co_await net::this_coro::executor; auto ex = co_await net::this_coro::executor;
auto cfg = make_test_config(); auto cfg = make_test_config();
cfg.health_check_interval = std::chrono::seconds::zero(); cfg.health_check_interval = std::chrono::seconds::zero();
run(conn, cfg, run(
conn,
cfg,
boost::asio::error::operation_aborted, boost::asio::error::operation_aborted,
boost::redis::operation::receive, boost::redis::operation::receive,
boost::redis::logger::level::crit); boost::redis::logger::level::crit);
@@ -123,15 +124,9 @@ BOOST_AUTO_TEST_CASE(echo_stress)
net::co_spawn(ioc, async_echo_stress(conn), net::detached); net::co_spawn(ioc, async_echo_stress(conn), net::detached);
ioc.run(); ioc.run();
std::cout std::cout << "-------------------\n" << conn->get_usage() << std::endl;
<< "-------------------\n"
<< conn->get_usage()
<< std::endl;
} }
#else #else
BOOST_AUTO_TEST_CASE(dummy) BOOST_AUTO_TEST_CASE(dummy) { BOOST_TEST(true); }
{
BOOST_TEST(true);
}
#endif #endif

View File

@@ -6,14 +6,18 @@
#include <boost/redis/adapter/any_adapter.hpp> #include <boost/redis/adapter/any_adapter.hpp>
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/system/errc.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/system/errc.hpp>
#include <string> #include <string>
#define BOOST_TEST_MODULE conn-exec #define BOOST_TEST_MODULE conn_exec
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
// TODO: Test whether HELLO won't be inserted passt commands that have // TODO: Test whether HELLO won't be inserted passt commands that have
// been already writen. // been already writen.
// TODO: Test async_exec with empty request e.g. hgetall with an empty // TODO: Test async_exec with empty request e.g. hgetall with an empty
@@ -214,4 +218,3 @@ BOOST_AUTO_TEST_CASE(exec_any_adapter)
BOOST_TEST(std::get<0>(res).value() == "PONG"); BOOST_TEST(std::get<0>(res).value() == "PONG");
} }

View File

@@ -5,11 +5,14 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn-exec-cancel #define BOOST_TEST_MODULE conn_exec_cancel
#include <boost/test/included/unit_test.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/test/included/unit_test.hpp>
#include "common.hpp" #include "common.hpp"
#include <iostream> #include <iostream>
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
@@ -57,10 +60,7 @@ auto implicit_cancel_of_req_written() -> net::awaitable<void>
// Achieves implicit cancellation when the timer fires. // Achieves implicit cancellation when the timer fires.
boost::system::error_code ec1, ec2; boost::system::error_code ec1, ec2;
co_await ( co_await (conn->async_exec(req1, ignore, redir(ec1)) || st.async_wait(redir(ec2)));
conn->async_exec(req1, ignore, redir(ec1)) ||
st.async_wait(redir(ec2))
);
conn->cancel(); conn->cancel();
@@ -92,13 +92,11 @@ BOOST_AUTO_TEST_CASE(test_cancel_of_req_written_on_run_canceled)
req1.get_config().cancel_if_unresponded = true; req1.get_config().cancel_if_unresponded = true;
req1.push("BLPOP", "any", 0); req1.push("BLPOP", "any", 0);
auto c1 = [&](auto ec, auto) auto c1 = [&](auto ec, auto) {
{
BOOST_CHECK_EQUAL(ec, net::error::operation_aborted); BOOST_CHECK_EQUAL(ec, net::error::operation_aborted);
}; };
auto c0 = [&](auto ec, auto) auto c0 = [&](auto ec, auto) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req1, ignore, c1); conn->async_exec(req1, ignore, c1);
}; };
@@ -121,8 +119,5 @@ BOOST_AUTO_TEST_CASE(test_cancel_of_req_written_on_run_canceled)
} }
#else #else
BOOST_AUTO_TEST_CASE(dummy) BOOST_AUTO_TEST_CASE(dummy) { BOOST_TEST(true); }
{
BOOST_TEST(true);
}
#endif #endif

View File

@@ -5,11 +5,14 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn-exec-cancel #define BOOST_TEST_MODULE conn_exec_cancel
#include <boost/test/included/unit_test.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/test/included/unit_test.hpp>
#include "common.hpp" #include "common.hpp"
#include <iostream> #include <iostream>
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
@@ -90,8 +93,5 @@ BOOST_AUTO_TEST_CASE(test_ignore_explicit_cancel_of_req_written)
} }
#else #else
BOOST_AUTO_TEST_CASE(dummy) BOOST_AUTO_TEST_CASE(dummy) { BOOST_TEST(true); }
{
BOOST_TEST(true);
}
#endif #endif

View File

@@ -6,10 +6,13 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn-exec-error #define BOOST_TEST_MODULE conn_exec_error
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "common.hpp" #include "common.hpp"
#include <iostream> #include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
@@ -106,8 +109,7 @@ BOOST_AUTO_TEST_CASE(resp3_error_in_cmd_pipeline)
net::io_context ioc; net::io_context ioc;
auto conn = std::make_shared<connection>(ioc); auto conn = std::make_shared<connection>(ioc);
auto c2 = [&](auto ec, auto) auto c2 = [&](auto ec, auto) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
BOOST_TEST(std::get<0>(resp2).has_value()); BOOST_TEST(std::get<0>(resp2).has_value());
BOOST_CHECK_EQUAL(std::get<0>(resp2).value(), "req2-msg1"); BOOST_CHECK_EQUAL(std::get<0>(resp2).value(), "req2-msg1");
@@ -115,8 +117,7 @@ BOOST_AUTO_TEST_CASE(resp3_error_in_cmd_pipeline)
conn->cancel(operation::reconnection); conn->cancel(operation::reconnection);
}; };
auto c1 = [&](auto ec, auto) auto c1 = [&](auto ec, auto) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
BOOST_TEST(std::get<2>(resp1).has_error()); BOOST_TEST(std::get<2>(resp1).has_error());
BOOST_CHECK_EQUAL(std::get<2>(resp1).error().data_type, resp3::type::simple_error); BOOST_CHECK_EQUAL(std::get<2>(resp1).error().data_type, resp3::type::simple_error);
@@ -155,8 +156,8 @@ BOOST_AUTO_TEST_CASE(error_in_transaction)
ignore_t, // ping ignore_t, // ping
response<std::string, std::string, std::string>, // exec response<std::string, std::string, std::string>, // exec
std::string // ping std::string // ping
> resp; >
resp;
net::io_context ioc; net::io_context ioc;
@@ -178,7 +179,9 @@ BOOST_AUTO_TEST_CASE(error_in_transaction)
// The ping in the transaction that should be an error. // The ping in the transaction that should be an error.
BOOST_TEST(std::get<1>(std::get<5>(resp).value()).has_error()); BOOST_TEST(std::get<1>(std::get<5>(resp).value()).has_error());
BOOST_CHECK_EQUAL(std::get<1>(std::get<5>(resp).value()).error().data_type, resp3::type::simple_error); BOOST_CHECK_EQUAL(
std::get<1>(std::get<5>(resp).value()).error().data_type,
resp3::type::simple_error);
auto const diag = std::get<1>(std::get<5>(resp).value()).error().diagnostic; auto const diag = std::get<1>(std::get<5>(resp).value()).error().diagnostic;
BOOST_TEST(!std::empty(diag)); BOOST_TEST(!std::empty(diag));
@@ -225,14 +228,12 @@ BOOST_AUTO_TEST_CASE(subscriber_wrong_syntax)
net::io_context ioc; net::io_context ioc;
auto conn = std::make_shared<connection>(ioc); auto conn = std::make_shared<connection>(ioc);
auto c2 = [&](auto ec, auto) auto c2 = [&](auto ec, auto) {
{
std::cout << "async_exec: subscribe" << std::endl; std::cout << "async_exec: subscribe" << std::endl;
BOOST_TEST(!ec); BOOST_TEST(!ec);
}; };
auto c1 = [&](auto ec, auto) auto c1 = [&](auto ec, auto) {
{
std::cout << "async_exec: hello" << std::endl; std::cout << "async_exec: hello" << std::endl;
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c2); conn->async_exec(req2, ignore, c2);
@@ -243,8 +244,7 @@ BOOST_AUTO_TEST_CASE(subscriber_wrong_syntax)
generic_response gresp; generic_response gresp;
conn->set_receive_response(gresp); conn->set_receive_response(gresp);
auto c3 = [&](auto ec, auto) auto c3 = [&](auto ec, auto) {
{
std::cout << "async_receive" << std::endl; std::cout << "async_receive" << std::endl;
BOOST_TEST(!ec); BOOST_TEST(!ec);
BOOST_TEST(gresp.has_error()); BOOST_TEST(gresp.has_error());
@@ -261,4 +261,3 @@ BOOST_AUTO_TEST_CASE(subscriber_wrong_syntax)
ioc.run(); ioc.run();
} }

View File

@@ -5,14 +5,17 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn-exec-retry #define BOOST_TEST_MODULE conn_exec_retry
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
using error_code = boost::system::error_code; using error_code = boost::system::error_code;
using connection = boost::redis::connection; using connection = boost::redis::connection;
@@ -75,13 +78,13 @@ BOOST_AUTO_TEST_CASE(request_retry_false)
conn->async_exec(req0, ignore, c0); conn->async_exec(req0, ignore, c0);
auto cfg = make_test_config(); auto cfg = make_test_config();
conn->async_run(cfg, {boost::redis::logger::level::debug}, conn->async_run(
[&](boost::system::error_code const& ec) cfg,
{ {boost::redis::logger::level::debug},
[&](boost::system::error_code const& ec) {
std::cout << "async_run: " << ec.message() << std::endl; std::cout << "async_run: " << ec.message() << std::endl;
conn->cancel(); conn->cancel();
} });
);
ioc.run(); ioc.run();
} }

View File

@@ -6,15 +6,18 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/system/errc.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/as_tuple.hpp> #include <boost/asio/as_tuple.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn - push #define BOOST_TEST_MODULE conn - push
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
namespace redis = boost::redis; namespace redis = boost::redis;
@@ -47,19 +50,16 @@ BOOST_AUTO_TEST_CASE(receives_push_waiting_resps)
auto conn = std::make_shared<connection>(ioc); auto conn = std::make_shared<connection>(ioc);
auto c3 =[](auto ec, auto...) auto c3 = [](auto ec, auto...) {
{
std::cout << "c3: " << ec.message() << std::endl; std::cout << "c3: " << ec.message() << std::endl;
}; };
auto c2 =[&, conn](auto ec, auto...) auto c2 = [&, conn](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req3, ignore, c3); conn->async_exec(req3, ignore, c3);
}; };
auto c1 =[&, conn](auto ec, auto...) auto c1 = [&, conn](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c2); conn->async_exec(req2, ignore, c2);
}; };
@@ -116,7 +116,9 @@ BOOST_AUTO_TEST_CASE(push_received1)
// Tries to receive a third push synchronously. // Tries to receive a third push synchronously.
ec2 = {}; ec2 = {};
res = conn->receive(ec2); res = conn->receive(ec2);
BOOST_CHECK_EQUAL(ec2, boost::redis::make_error_code(boost::redis::error::sync_receive_push_failed)); BOOST_CHECK_EQUAL(
ec2,
boost::redis::make_error_code(boost::redis::error::sync_receive_push_failed));
conn->cancel(); conn->cancel();
}); });
@@ -157,8 +159,7 @@ BOOST_AUTO_TEST_CASE(push_filtered_out)
} }
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
net::awaitable<void> net::awaitable<void> push_consumer1(std::shared_ptr<connection> conn, bool& push_received)
push_consumer1(std::shared_ptr<connection> conn, bool& push_received)
{ {
{ {
auto [ec, ev] = co_await conn->async_receive(as_tuple(net::use_awaitable)); auto [ec, ev] = co_await conn->async_receive(as_tuple(net::use_awaitable));
@@ -177,22 +178,22 @@ struct response_error_tag{};
response_error_tag error_tag_obj; response_error_tag error_tag_obj;
struct response_error_adapter { struct response_error_adapter {
void void operator()(
operator()( std::size_t,
std::size_t, boost::redis::resp3::basic_node<std::string_view> const&, boost::system::error_code& ec) boost::redis::resp3::basic_node<std::string_view> const&,
boost::system::error_code& ec)
{ {
ec = boost::redis::error::incompatible_size; ec = boost::redis::error::incompatible_size;
} }
[[nodiscard]] [[nodiscard]]
auto get_supported_response_size() const noexcept auto get_supported_response_size() const noexcept
{ return static_cast<std::size_t>(-1);} {
return static_cast<std::size_t>(-1);
}
}; };
auto boost_redis_adapt(response_error_tag&) auto boost_redis_adapt(response_error_tag&) { return response_error_adapter{}; }
{
return response_error_adapter{};
}
BOOST_AUTO_TEST_CASE(test_push_adapter) BOOST_AUTO_TEST_CASE(test_push_adapter)
{ {
@@ -255,63 +256,51 @@ BOOST_AUTO_TEST_CASE(many_subscribers)
net::io_context ioc; net::io_context ioc;
auto conn = std::make_shared<connection>(ioc); auto conn = std::make_shared<connection>(ioc);
auto c11 =[&](auto ec, auto...) auto c11 = [&](auto ec, auto...) {
{
std::cout << "quit sent: " << ec.message() << std::endl; std::cout << "quit sent: " << ec.message() << std::endl;
conn->cancel(operation::reconnection); conn->cancel(operation::reconnection);
}; };
auto c10 =[&](auto ec, auto...) auto c10 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req3, ignore, c11); conn->async_exec(req3, ignore, c11);
}; };
auto c9 =[&](auto ec, auto...) auto c9 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c10); conn->async_exec(req2, ignore, c10);
}; };
auto c8 =[&](auto ec, auto...) auto c8 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req1, ignore, c9); conn->async_exec(req1, ignore, c9);
}; };
auto c7 =[&](auto ec, auto...) auto c7 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c8); conn->async_exec(req2, ignore, c8);
}; };
auto c6 =[&](auto ec, auto...) auto c6 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c7); conn->async_exec(req2, ignore, c7);
}; };
auto c5 =[&](auto ec, auto...) auto c5 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req1, ignore, c6); conn->async_exec(req1, ignore, c6);
}; };
auto c4 =[&](auto ec, auto...) auto c4 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c5); conn->async_exec(req2, ignore, c5);
}; };
auto c3 =[&](auto ec, auto...) auto c3 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req1, ignore, c4); conn->async_exec(req1, ignore, c4);
}; };
auto c2 =[&](auto ec, auto...) auto c2 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c3); conn->async_exec(req2, ignore, c3);
}; };
auto c1 =[&](auto ec, auto...) auto c1 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c2); conn->async_exec(req2, ignore, c2);
}; };
auto c0 =[&](auto ec, auto...) auto c0 = [&](auto ec, auto...) {
{
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req1, ignore, c1); conn->async_exec(req1, ignore, c1);
}; };

View File

@@ -5,12 +5,15 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/system/errc.hpp> #include <boost/system/errc.hpp>
#define BOOST_TEST_MODULE conn-quit #define BOOST_TEST_MODULE conn_quit
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
using boost::redis::connection; using boost::redis::connection;
using boost::system::error_code; using boost::system::error_code;
@@ -40,21 +43,18 @@ BOOST_AUTO_TEST_CASE(test_async_run_exits)
req3.get_config().cancel_if_not_connected = true; req3.get_config().cancel_if_not_connected = true;
req3.push("PING"); req3.push("PING");
auto c3 = [](auto ec, auto) auto c3 = [](auto ec, auto) {
{
std::clog << "c3: " << ec.message() << std::endl; std::clog << "c3: " << ec.message() << std::endl;
BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted); BOOST_CHECK_EQUAL(ec, boost::asio::error::operation_aborted);
}; };
auto c2 = [&](auto ec, auto) auto c2 = [&](auto ec, auto) {
{
std::clog << "c2: " << ec.message() << std::endl; std::clog << "c2: " << ec.message() << std::endl;
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req3, ignore, c3); conn->async_exec(req3, ignore, c3);
}; };
auto c1 = [&](auto ec, auto) auto c1 = [&](auto ec, auto) {
{
std::cout << "c1: " << ec.message() << std::endl; std::cout << "c1: " << ec.message() << std::endl;
BOOST_TEST(!ec); BOOST_TEST(!ec);
conn->async_exec(req2, ignore, c2); conn->async_exec(req2, ignore, c2);
@@ -71,4 +71,3 @@ BOOST_AUTO_TEST_CASE(test_async_run_exits)
ioc.run(); ioc.run();
} }

View File

@@ -5,12 +5,15 @@
*/ */
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#define BOOST_TEST_MODULE conn-reconnect #define BOOST_TEST_MODULE conn_reconnect
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
#ifdef BOOST_ASIO_HAS_CO_AWAIT #ifdef BOOST_ASIO_HAS_CO_AWAIT
#include <boost/asio/experimental/awaitable_operators.hpp> #include <boost/asio/experimental/awaitable_operators.hpp>
@@ -43,7 +46,8 @@ net::awaitable<void> test_reconnect_impl()
logger l; logger l;
co_await conn->async_exec(req, ignore, net::redirect_error(net::use_awaitable, ec1)); co_await conn->async_exec(req, ignore, net::redirect_error(net::use_awaitable, ec1));
//BOOST_TEST(!ec); //BOOST_TEST(!ec);
std::cout << "test_reconnect: " << i << " " << ec2.message() << " " << ec1.message() << std::endl; std::cout << "test_reconnect: " << i << " " << ec2.message() << " " << ec1.message()
<< std::endl;
} }
conn->cancel(); conn->cancel();
@@ -76,10 +80,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
st.expires_after(std::chrono::seconds{1}); st.expires_after(std::chrono::seconds{1});
auto cfg = make_test_config(); auto cfg = make_test_config();
co_await ( co_await (conn->async_exec(req1, ignore, redir(ec1)) || st.async_wait(redir(ec3)));
conn->async_exec(req1, ignore, redir(ec1)) ||
st.async_wait(redir(ec3))
);
//BOOST_TEST(!ec1); //BOOST_TEST(!ec1);
//BOOST_TEST(!ec3); //BOOST_TEST(!ec3);
@@ -93,8 +94,7 @@ auto async_test_reconnect_timeout() -> net::awaitable<void>
st.expires_after(std::chrono::seconds{1}); st.expires_after(std::chrono::seconds{1});
co_await ( co_await (
conn->async_exec(req1, ignore, net::redirect_error(net::use_awaitable, ec1)) || conn->async_exec(req1, ignore, net::redirect_error(net::use_awaitable, ec1)) ||
st.async_wait(net::redirect_error(net::use_awaitable, ec3)) st.async_wait(net::redirect_error(net::use_awaitable, ec3)));
);
conn->cancel(); conn->cancel();
std::cout << "ccc" << std::endl; std::cout << "ccc" << std::endl;
@@ -109,8 +109,5 @@ BOOST_AUTO_TEST_CASE(test_reconnect_and_idle)
ioc.run(); ioc.run();
} }
#else #else
BOOST_AUTO_TEST_CASE(dummy) BOOST_AUTO_TEST_CASE(dummy) { BOOST_TEST(true); }
{
BOOST_TEST(true);
}
#endif #endif

View File

@@ -4,11 +4,13 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/connection.hpp>
#include <boost/asio/ssl/host_name_verification.hpp> #include <boost/asio/ssl/host_name_verification.hpp>
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#include <boost/redis/connection.hpp> #define BOOST_TEST_MODULE conn_tls
#define BOOST_TEST_MODULE conn-tls
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "common.hpp" #include "common.hpp"
namespace net = boost::asio; namespace net = boost::asio;

View File

@@ -8,6 +8,7 @@
#include "boost/system/detail/error_code.hpp" #include "boost/system/detail/error_code.hpp"
#define BOOST_TEST_MODULE conversions #define BOOST_TEST_MODULE conversions
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "common.hpp" #include "common.hpp"
@@ -43,8 +44,8 @@ BOOST_AUTO_TEST_CASE(ints)
long, long,
unsigned long, unsigned long,
long long, long long,
unsigned long long unsigned long long>
> resp; resp;
conn->async_exec(req, resp, [conn](error_code ec, std::size_t) { conn->async_exec(req, resp, [conn](error_code ec, std::size_t) {
BOOST_TEST(!ec); BOOST_TEST(!ec);

View File

@@ -6,16 +6,19 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp> #include <boost/asio/use_awaitable.hpp>
#define BOOST_TEST_MODULE conn-quit #define BOOST_TEST_MODULE conn_quit
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include "common.hpp"
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
#include "common.hpp"
namespace net = boost::asio; namespace net = boost::asio;
using boost::redis::request; using boost::redis::request;

View File

@@ -8,19 +8,22 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp> #include <boost/redis/logger.hpp>
#include <boost/asio/as_tuple.hpp> #include <boost/asio/as_tuple.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/consign.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/awaitable.hpp> #include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/consign.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/redirect_error.hpp>
#include <boost/asio/use_awaitable.hpp>
#define BOOST_TEST_MODULE conn - quit #define BOOST_TEST_MODULE conn - quit
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <tuple>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
#include <tuple>
#if defined(BOOST_ASIO_HAS_CO_AWAIT) #if defined(BOOST_ASIO_HAS_CO_AWAIT)
namespace net = boost::asio; namespace net = boost::asio;
@@ -38,8 +41,7 @@ using boost::asio::redirect_error;
using namespace std::chrono_literals; using namespace std::chrono_literals;
// Push consumer // Push consumer
auto auto receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
{ {
std::cout << "uuu" << std::endl; std::cout << "uuu" << std::endl;
while (conn->will_reconnect()) { while (conn->will_reconnect()) {
@@ -59,8 +61,7 @@ receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
std::cout << "Exiting the receiver." << std::endl; std::cout << "Exiting the receiver." << std::endl;
} }
auto auto periodic_task(std::shared_ptr<connection> conn) -> net::awaitable<void>
periodic_task(std::shared_ptr<connection> conn) -> net::awaitable<void>
{ {
net::steady_timer timer{co_await net::this_coro::executor}; net::steady_timer timer{co_await net::this_coro::executor};
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
@@ -107,8 +108,6 @@ BOOST_AUTO_TEST_CASE(issue_50)
#else // defined(BOOST_ASIO_HAS_CO_AWAIT) #else // defined(BOOST_ASIO_HAS_CO_AWAIT)
BOOST_AUTO_TEST_CASE(issue_50) BOOST_AUTO_TEST_CASE(issue_50) { }
{
}
#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) #endif // defined(BOOST_ASIO_HAS_CO_AWAIT)

View File

@@ -4,17 +4,18 @@
* accompanying file LICENSE.txt) * accompanying file LICENSE.txt)
*/ */
#include <boost/redis/detail/resp3_handshaker.hpp>
#include <boost/redis/detail/multiplexer.hpp>
#include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/resp3/type.hpp>
#include <boost/redis/adapter/adapt.hpp> #include <boost/redis/adapter/adapt.hpp>
#include <boost/redis/adapter/any_adapter.hpp> #include <boost/redis/adapter/any_adapter.hpp>
#define BOOST_TEST_MODULE conn-quit #include <boost/redis/detail/multiplexer.hpp>
#include <boost/redis/detail/resp3_handshaker.hpp>
#include <boost/redis/resp3/node.hpp>
#include <boost/redis/resp3/serialization.hpp>
#include <boost/redis/resp3/type.hpp>
#define BOOST_TEST_MODULE conn_quit
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <string>
#include <iostream> #include <iostream>
#include <string>
using boost::redis::request; using boost::redis::request;
using boost::redis::config; using boost::redis::config;
@@ -82,7 +83,8 @@ BOOST_AUTO_TEST_CASE(config_to_hello_cmd_clientname)
push_hello(cfg, req); push_hello(cfg, req);
std::string_view const expected = "*4\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$7\r\nSETNAME\r\n$11\r\nBoost.Redis\r\n"; std::string_view const
expected = "*4\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$7\r\nSETNAME\r\n$11\r\nBoost.Redis\r\n";
BOOST_CHECK_EQUAL(req.payload(), expected); BOOST_CHECK_EQUAL(req.payload(), expected);
} }
@@ -96,21 +98,20 @@ BOOST_AUTO_TEST_CASE(config_to_hello_cmd_auth)
push_hello(cfg, req); push_hello(cfg, req);
std::string_view const expected = "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"; std::string_view const
expected = "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$3\r\nbar\r\n";
BOOST_CHECK_EQUAL(req.payload(), expected); BOOST_CHECK_EQUAL(req.payload(), expected);
} }
BOOST_AUTO_TEST_CASE(issue_210_empty_set) BOOST_AUTO_TEST_CASE(issue_210_empty_set)
{ {
try { try {
result< result<std::tuple<
std::tuple<
result<int>, result<int>,
result<std::vector<std::string>>, result<std::vector<std::string>>,
result<std::string>, result<std::string>,
result<int> result<int>>>
> resp;
> resp;
char const* wire = "*4\r\n:1\r\n~0\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n"; char const* wire = "*4\r\n:1\r\n~0\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
@@ -130,16 +131,15 @@ BOOST_AUTO_TEST_CASE(issue_210_empty_set)
BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_one) BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_one)
{ {
try { try {
result< result<std::tuple<
std::tuple<
result<int>, result<int>,
result<std::vector<std::string>>, result<std::vector<std::string>>,
result<std::string>, result<std::string>,
result<int> result<int>>>
> resp;
> resp;
char const* wire = "*4\r\n:1\r\n~1\r\n$3\r\nfoo\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n"; char const*
wire = "*4\r\n:1\r\n~1\r\n$3\r\nfoo\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
deserialize(wire, adapt2(resp)); deserialize(wire, adapt2(resp));
@@ -158,16 +158,15 @@ BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_one)
BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_two) BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_two)
{ {
try { try {
result< result<std::tuple<
std::tuple<
result<int>, result<int>,
result<std::vector<std::string>>, result<std::vector<std::string>>,
result<std::string>, result<std::string>,
result<int> result<int>>>
> resp;
> resp;
char const* wire = "*4\r\n:1\r\n~2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n"; char const* wire =
"*4\r\n:1\r\n~2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n:2\r\n";
deserialize(wire, adapt2(resp)); deserialize(wire, adapt2(resp));
@@ -185,16 +184,11 @@ BOOST_AUTO_TEST_CASE(issue_210_non_empty_set_size_two)
BOOST_AUTO_TEST_CASE(issue_210_no_nested) BOOST_AUTO_TEST_CASE(issue_210_no_nested)
{ {
try { try {
result< result<std::tuple<result<int>, result<std::string>, result<std::string>, result<std::string>>>
std::tuple< resp;
result<int>,
result<std::string>,
result<std::string>,
result<std::string>
>
> resp;
char const* wire = "*4\r\n:1\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n"; char const*
wire = "*4\r\n:1\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$25\r\nthis_should_not_be_in_set\r\n";
deserialize(wire, adapt2(resp)); deserialize(wire, adapt2(resp));

View File

@@ -7,10 +7,10 @@
#include <iostream> #include <iostream>
#define BOOST_TEST_MODULE request #define BOOST_TEST_MODULE request
#include <boost/test/included/unit_test.hpp>
#include <boost/redis/request.hpp> #include <boost/redis/request.hpp>
#include <boost/test/included/unit_test.hpp>
using boost::redis::request; using boost::redis::request;
// TODO: Serialization. // TODO: Serialization.
@@ -39,9 +39,14 @@ BOOST_AUTO_TEST_CASE(multiple_args)
BOOST_AUTO_TEST_CASE(container_and_range) BOOST_AUTO_TEST_CASE(container_and_range)
{ {
std::map<std::string, std::string> in{{"key1", "value1"}, {"key2", "value2"}}; std::map<std::string, std::string> in{
{"key1", "value1"},
{"key2", "value2"}
};
char const* res = "*6\r\n$4\r\nHSET\r\n$3\r\nkey\r\n$4\r\nkey1\r\n$6\r\nvalue1\r\n$4\r\nkey2\r\n$6\r\nvalue2\r\n"; char const* res =
"*6\r\n$4\r\nHSET\r\n$3\r\nkey\r\n$4\r\nkey1\r\n$6\r\nvalue1\r\n$4\r\nkey2\r\n$"
"6\r\nvalue2\r\n";
request req1; request req1;
req1.push_range("HSET", "key", in); req1.push_range("HSET", "key", in);

View File

@@ -7,9 +7,11 @@
#include <boost/redis/connection.hpp> #include <boost/redis/connection.hpp>
#define BOOST_TEST_MODULE run #define BOOST_TEST_MODULE run
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#include <iostream>
#include "common.hpp" #include "common.hpp"
#include <iostream>
namespace net = boost::asio; namespace net = boost::asio;
namespace redis = boost::redis; namespace redis = boost::redis;
@@ -22,8 +24,10 @@ using namespace std::chrono_literals;
bool is_host_not_found(error_code ec) bool is_host_not_found(error_code ec)
{ {
if (ec == net::error::netdb_errors::host_not_found) return true; if (ec == net::error::netdb_errors::host_not_found)
if (ec == net::error::netdb_errors::host_not_found_try_again) return true; return true;
if (ec == net::error::netdb_errors::host_not_found_try_again)
return true;
return false; return false;
} }
@@ -97,4 +101,3 @@ BOOST_AUTO_TEST_CASE(connect_bad_port)
// run(conn, cfg, boost::redis::error::connect_timeout); // run(conn, cfg, boost::redis::error::connect_timeout);
// ioc.run(); // ioc.run();
//} //}