Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ccb17f8
Draft version without consume_one implementation
Jun 27, 2025
7d959c1
Addressed some comments
Jun 27, 2025
b78cf81
reserve function
Jun 28, 2025
9419c85
Corrected and cleaner implementation with comments
Jul 2, 2025
ecd1573
Call prepare_done function to form response
Jul 5, 2025
5444e07
Defined done_fn_type in adapters.hpp
Jul 5, 2025
1d9f9ab
Moved implementation of push_back to general_aggregate
Jul 5, 2025
53e5ae0
Avoid turning throwing consume_one into template
Jul 12, 2025
019a080
Get rid of type erasion in details::prepare_done
Jul 12, 2025
84fa399
Added API for generic_flat_response, replaced generic_response with n…
Jul 12, 2025
b1420d3
Adjust code base to new changes
Aug 18, 2025
c284960
Replaced generic_response with generic_flat_response in tests
Aug 18, 2025
bd799af
create flat_response_value::add_node()
Aug 18, 2025
6ff4740
Cosmetic changes
Aug 18, 2025
2c1f1c4
Concludes the work started by Nikolai Vladimirov on the generic_flat_…
mzimbres Oct 3, 2025
b365b96
Fixup Adds generic_flat_response typedef
mzimbres Nov 10, 2025
00f3ec9
Merge pull request #340 from boostorg/263-marcelo
mzimbres Nov 18, 2025
bdd9c32
Adds Sentinel support (#345)
anarthal Nov 19, 2025
91afb4a
Fixes SBO problem and adds some tests (#356)
mzimbres Nov 20, 2025
d9e4b2c
Improves flat_tree implementation (#358)
anarthal Nov 29, 2025
755d14a
Renames test_setup_request_utils to test_compose_setup_request (#359)
anarthal Nov 29, 2025
6005ebd
Fixes std::tuple serialization and adds tests (#363)
anarthal Dec 2, 2025
02632b3
Removes ostream inclusion from public headers (#364)
anarthal Dec 2, 2025
2bbf009
Mark consume_one as deprecated (#365)
anarthal Dec 2, 2025
7750a6b
Splits read_buffer tests to a separate file (#368)
anarthal Dec 3, 2025
3b07119
Makes flat_tree aware of incremental parsing to avoid race conditions…
anarthal Jan 7, 2026
bea5474
Adds support for PubSub state restoration (#375)
anarthal Jan 9, 2026
c11a519
Reworks test_conn_push and test_conn_push2 (#380)
anarthal Jan 14, 2026
002b616
Replaces --with-system with --with-headers when building Boost in CI …
anarthal Jan 18, 2026
89e44dc
Makes async_receive2 not cancel on reconnection (#381)
anarthal Jan 18, 2026
18ee728
Makes flat_tree a proper container (#383)
anarthal Jan 18, 2026
d3013c4
Refactors the Sentinel response parser to use flat_tree (#391)
anarthal Jan 28, 2026
bd1e22f
Adds request::hello and deprecates config::username, password (#392)
anarthal Jan 30, 2026
b7b93c9
Increases the level at which error messages are logged (#389)
anarthal Jan 30, 2026
1360155
Generates TLS certificates dynamically in CI (#396)
anarthal Feb 18, 2026
fb9b40e
Adds a convenient way of iterating PubSub messages (#390)
anarthal Feb 23, 2026
3a45ebb
Remove dependencies on Boost.StaticAssert. (#386)
Lastique Feb 24, 2026
455b2e1
Revert "Remove dependencies on Boost.StaticAssert. (#386)"
anarthal Feb 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Generate TLS certificates
run: |
./tools/gen-certificates.sh

- name: Set up the required containers
run: |
BUILDER_IMAGE=${{ matrix.container }} SERVER_IMAGE=${{ matrix.server }} docker compose -f tools/docker-compose.yml up -d --wait || (docker compose logs; exit 1)
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ if (BOOST_REDIS_MAIN_PROJECT)
test
json
endian
compat
)

foreach(dep IN LISTS deps)
Expand Down
57 changes: 36 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,43 +87,58 @@ them are:
* [Client-side caching](https://redis.io/docs/manual/client-side-caching/).

The connection class supports server pushes by means of the
`connection::async_receive` function, which can be
`connection::async_receive2` function, which can be
called in the same connection that is being used to execute commands.
The coroutine below shows how to use it:
The coroutine below shows how to use it


```cpp
auto
receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
auto receiver(std::shared_ptr<connection> conn) -> asio::awaitable<void>
{
generic_flat_response resp;
conn->set_receive_response(resp);

// Subscribe to the channel 'mychannel'. You can add any number of channels here.
request req;
req.push("SUBSCRIBE", "channel");
req.subscribe({"mychannel"});
co_await conn->async_exec(req);

generic_response resp;
conn->set_receive_response(resp);
// You're now subscribed to 'mychannel'. Pushes sent over this channel will be stored
// in resp. If the connection encounters a network error and reconnects to the server,
// it will automatically subscribe to 'mychannel' again. This is transparent to the user.
// You need to use specialized request::subscribe() function (instead of request::push)
// to enable this behavior.

// Loop while reconnection is enabled
// Loop to read Redis push messages.
while (conn->will_reconnect()) {
// Wait for pushes
auto [ec] = co_await conn->async_receive2(asio::as_tuple);

// Reconnect to channels.
co_await conn->async_exec(req, ignore);

// Loop reading Redis pushes.
for (;;) {
error_code ec;
co_await conn->async_receive(resp, net::redirect_error(net::use_awaitable, ec));
if (ec)
break; // Connection lost, break so we can reconnect to channels.
// Check for errors and cancellations
if (ec) {
std::cerr << "Error during receive: " << ec << std::endl;
break;
}

// Use the response resp in some way and then clear it.
...
// This can happen if a SUBSCRIBE command errored (e.g. insufficient permissions)
if (resp.has_error()) {
std::cerr << "The receive response contains an error: " << resp.error().diagnostic
<< std::endl;
break;
}

consume_one(resp);
// The response must be consumed without suspending the
// coroutine i.e. without the use of async operations.
for (push_view elem : push_parser(resp.value())) {
std::cout << "Received message from channel " << elem.channel << ": " << elem.payload
<< "\n";
}

resp.value().clear();
}
}
```

## Further reading

Full documentation is [here](https://www.boost.org/doc/libs/master/libs/redis/index.html).
Full documentation is [here](https://www.boost.org/doc/libs/master/libs/redis/index.html).
3 changes: 3 additions & 0 deletions doc/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
* xref:index.adoc[Introduction]
* xref:requests_responses.adoc[]
* xref:pushes.adoc[Server pushes]
* xref:cancellation.adoc[]
* xref:serialization.adoc[]
* xref:auth.adoc[]
* xref:logging.adoc[]
* xref:sentinel.adoc[]
* xref:benchmarks.adoc[]
* xref:comparison.adoc[]
* xref:examples.adoc[]
Expand Down
49 changes: 49 additions & 0 deletions doc/modules/ROOT/pages/auth.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Copyright (c) 2026 Marcelo Zimbres Silva (mzimbres@gmail.com),
// Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

= Authentication

Boost.Redis supports connecting to servers that require authentication.
To achieve it, you must send a
https://redis.io/commands/hello/[HELLO] command with the appropriate
`AUTH` parameters during connection establishment. Boost.Redis allows you
to customize this handshake by using a _setup request_: a request that
is run automatically before any other request,
every time a physical connection to the server is established.

Configuration is done on xref:reference:boost/redis/config.adoc[`config`].
Set `use_setup` to `true` (required for backwards compatibility)
and build the desired setup request in
`config::setup`. By default, the library sends a plain `HELLO 3` (RESP3
without auth). To authenticate, clear the default setup and push a
`HELLO` command that includes your credentials:

[source,cpp]
----
config cfg;
cfg.use_setup = true;
cfg.setup.clear(); // Remove the default HELLO 3
cfg.setup.hello("my_username", "my_password");

co_await conn.async_run(cfg);
----

Authentication is just one use of this mechanism.
For example, to select a particular logical database (see the Redis
https://redis.io/commands/select/[SELECT] command), add a `SELECT`
command after the `HELLO`:

[source,cpp]
----
config cfg;
cfg.use_setup = true;
cfg.setup.push("SELECT", 42); // select the logical database 42 after the default HELLO 3

co_await conn.async_run(cfg);
----

2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/examples.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The examples below show how to use the features discussed throughout this docume
* {site-url}/example/cpp20_containers.cpp[cpp20_containers.cpp]: Shows how to send and receive STL containers and how to use transactions.
* {site-url}/example/cpp20_json.cpp[cpp20_json.cpp]: Shows how to serialize types using Boost.Json.
* {site-url}/example/cpp20_protobuf.cpp[cpp20_protobuf.cpp]: Shows how to serialize types using protobuf.
* {site-url}/example/cpp20_resolve_with_sentinel.cpp[cpp20_resolve_with_sentinel.cpp]: Shows how to resolve a master address using sentinels.
* {site-url}/example/cpp20_sentinel.cpp[cpp20_sentinel.cpp]: Shows how to use the library with a Sentinel deployment.
* {site-url}/example/cpp20_subscriber.cpp[cpp20_subscriber.cpp]: Shows how to implement pubsub with reconnection re-subscription.
* {site-url}/example/cpp20_echo_server.cpp[cpp20_echo_server.cpp]: A simple TCP echo server.
* {site-url}/example/cpp20_chat_room.cpp[cpp20_chat_room.cpp]: A command line chat built on Redis pubsub.
Expand Down
50 changes: 2 additions & 48 deletions doc/modules/ROOT/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -87,60 +87,14 @@ The roles played by the `async_run` and `async_exec` functions are:
be called from multiple places in your code concurrently.
* xref:reference:boost/redis/basic_connection/async_run-04.adoc[`connection::async_run`]: keeps the connection healthy. It takes care of hostname resolution, session establishment, health-checks, reconnection and coordination of low-level read and write operations. It should be called only once per connection, regardless of the number of requests to execute.

== Server pushes

Redis servers can also send a variety of pushes to the client. Some of
them are:

* https://redis.io/docs/manual/pubsub/[Pubsub messages].
* https://redis.io/docs/manual/keyspace-notifications/[Keyspace notifications].
* https://redis.io/docs/manual/client-side-caching/[Client-side caching].

The connection class supports server pushes by means of the
xref:reference:boost/redis/basic_connection/async_receive.adoc[`connection::async_receive`] function, which can be
called in the same connection that is being used to execute commands.
The coroutine below shows how to use it:


[source,cpp]
----
auto
receiver(std::shared_ptr<connection> conn) -> net::awaitable<void>
{
request req;
req.push("SUBSCRIBE", "channel");

generic_response resp;
conn->set_receive_response(resp);

// Loop while reconnection is enabled
while (conn->will_reconnect()) {

// Reconnect to channels.
co_await conn->async_exec(req, ignore);

// Loop reading Redis pushes.
for (;;) {
error_code ec;
co_await conn->async_receive(resp, net::redirect_error(net::use_awaitable, ec));
if (ec)
break; // Connection lost, break so we can reconnect to channels.

// Use the response resp in some way and then clear it.
...

consume_one(resp);
}
}
}
----

== Further reading

Here is a list of topics that you might be interested in:

* xref:cancellation.adoc[Setting timeouts to requests and managing cancellation].
* xref:requests_responses.adoc[More on requests and responses].
* xref:pushes.adoc[Reading server pushes].
* xref:cancellation.adoc[Setting timeouts to requests and managing cancellation].
* xref:serialization.adoc[Serializing and parsing into custom types].
* xref:logging.adoc[Configuring logging].
* xref:examples.adoc[Examples].
Loading