@@ -743,7 +743,7 @@ class basic_connection {
743743 return async_run (config{}, std::forward<CompletionToken>(token));
744744 }
745745
746- /* * @brief Receives server side pushes asynchronously.
746+ /* * @brief (Deprecated) Receives server side pushes asynchronously.
747747 *
748748 * When pushes arrive and there is no `async_receive` operation in
749749 * progress, pushed data, requests, and responses will be paused
@@ -773,12 +773,76 @@ class basic_connection {
773773 * @param token Completion token.
774774 */
775775 template <class CompletionToken = asio::default_completion_token_t <executor_type>>
776+ BOOST_DEPRECATED (" Please use async_receive2 instead." )
776777 auto async_receive(CompletionToken&& token = {})
777778 {
778779 return impl_->receive_channel_ .async_receive (std::forward<CompletionToken>(token));
779780 }
780781
781- /* * @brief Receives server pushes synchronously without blocking.
782+ /* * @brief Wait for server pushes asynchronously
783+ *
784+ * This function suspends until a server push is received by the
785+ * connection. On completion an unspecified number of pushes will
786+ * have been added to the response object set with @ref
787+ * boost::redis::connection::set_receive_response.
788+ *
789+ * To prevent receiving an unbound number of pushes the connection
790+ * blocks further read operations on the socket when 256 pushes
791+ * accumulate internally (we don't make any commitment to this
792+ * exact number). When that happens calls to `async_exec` won't be
793+ * able to make progress including the health-checks, which might
794+ * result in a connection timeout. To avoid that Apps should call
795+ * async_receive2 continuously in a loop.
796+ *
797+ * @Note To avoid deadlocks the task calling `async_receive2 should
798+ * not call `async_exec` in a way where they could block each
799+ * other.
800+ *
801+ * For an example see cpp20_subscriber.cpp. The completion token
802+ * must have the following signature
803+ *
804+ * @code
805+ * void f(system::error_code);
806+ * @endcode
807+ *
808+ * @par Per-operation cancellation
809+ * This operation supports the following cancellation types:
810+ *
811+ * @li `asio::cancellation_type_t::terminal`.
812+ * @li `asio::cancellation_type_t::partial`.
813+ * @li `asio::cancellation_type_t::total`.
814+ *
815+ * Calling `basic_connection::cancel(operation::receive)` will
816+ * also cancel any ongoing receive operations.
817+ *
818+ * @param token Completion token.
819+ */
820+ template <class CompletionToken = asio::default_completion_token_t <executor_type>>
821+ auto async_receive2 (CompletionToken&& token = {})
822+ {
823+ return
824+ impl_->receive_channel_ .async_receive (
825+ asio::deferred (
826+ [&conn = *this ](system::error_code ec, std::size_t )
827+ {
828+ if (!ec) {
829+ auto f = [](system::error_code, std::size_t ) {
830+ // There is no point in checking for errors
831+ // here since async_receive just completed
832+ // without errors.
833+ };
834+
835+ // We just want to drain the channel.
836+ while (conn.impl_ ->receive_channel_ .try_receive (f));
837+ }
838+
839+ return asio::deferred.values (ec);
840+ }
841+ )
842+ )(std::forward<CompletionToken>(token));
843+ }
844+
845+ /* * @brief (Deprecated) Receives server pushes synchronously without blocking.
782846 *
783847 * Receives a server push synchronously by calling `try_receive` on
784848 * the underlying channel. If the operation fails because
@@ -788,6 +852,7 @@ class basic_connection {
788852 * @param ec Contains the error if any occurred.
789853 * @returns The number of bytes read from the socket.
790854 */
855+ BOOST_DEPRECATED (" Please use async_receive2." )
791856 std::size_t receive(system::error_code& ec)
792857 {
793858 std::size_t size = 0 ;
@@ -987,7 +1052,7 @@ class basic_connection {
9871052 " the other member functions to interact with the connection." )
9881053 auto const & next_layer() const noexcept { return impl_->stream_ .next_layer (); }
9891054
990- // / Sets the response object of @ref async_receive operations.
1055+ // / Sets the response object of @ref async_receive2 operations.
9911056 template <class Response >
9921057 void set_receive_response (Response& resp)
9931058 {
@@ -1178,12 +1243,21 @@ class connection {
11781243
11791244 // / @copydoc basic_connection::async_receive
11801245 template <class CompletionToken = asio::deferred_t >
1246+ BOOST_DEPRECATED (" Please use async_receive2 instead." )
11811247 auto async_receive(CompletionToken&& token = {})
11821248 {
11831249 return impl_.async_receive (std::forward<CompletionToken>(token));
11841250 }
11851251
1252+ // / @copydoc basic_connection::async_receive2
1253+ template <class CompletionToken = asio::deferred_t >
1254+ auto async_receive2 (CompletionToken&& token = {})
1255+ {
1256+ return impl_.async_receive2 (std::forward<CompletionToken>(token));
1257+ }
1258+
11861259 // / @copydoc basic_connection::receive
1260+ BOOST_DEPRECATED (" Please use async_receive2 instead." )
11871261 std::size_t receive(system::error_code& ec) { return impl_.receive (ec); }
11881262
11891263 /* *
0 commit comments