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

Improvements in the docs.

This commit is contained in:
Marcelo Zimbres
2022-01-29 19:31:07 +01:00
parent 5ddffce4ee
commit 4fe47eb245
21 changed files with 154 additions and 165 deletions

View File

@@ -31,6 +31,9 @@ EXTRA_PROGRAMS += echo_server
EXTRA_PROGRAMS += chat_room
EXTRA_PROGRAMS += commands
CLEANFILES =
CLEANFILES += $(EXTRA_PROGRAMS)
.PHONY: all
all: $(check_PROGRAMS) $(EXTRA_PROGRAMS)
@@ -52,10 +55,8 @@ echo_server_SOURCES = $(top_srcdir)/examples/echo_server.cpp
chat_room_SOURCES = $(top_srcdir)/examples/chat_room.cpp
transaction_SOURCES = $(top_srcdir)/examples/transaction.cpp
nobase_nodist_include_HEADERS =\
$(top_srcdir)/aedis/config.hpp
nobase_include_HEADERS =\
$(top_srcdir)/aedis/config.hpp\
$(top_srcdir)/aedis/src.hpp\
$(top_srcdir)/aedis/redis/command.hpp\
$(top_srcdir)/aedis/sentinel/command.hpp\
@@ -97,8 +98,6 @@ EXTRA_DIST += $(top_srcdir)/doc/aedis.css
EXTRA_DIST += $(top_srcdir)/doc/htmlfooter.html
EXTRA_DIST += $(top_srcdir)/doc/htmlheader.html
CLEANFILES =
.PHONY: doc
doc:
rm -rf /tmp/aedis

View File

@@ -22,12 +22,13 @@
*
* \b Overview
*
* Aedis is low-level redis client built on top of Boost.Asio that
* implements communication with a Redis server over its native
* Aedis is low-level redis client library built on top of Boost.Asio
* that implements communication with a Redis server over its native
* protocol RESP3. It has first-class support for STL containers and
* C++ built in types. You will be able to implement your own redis
* client or use a general purpose provided by the library. For more
* information about Redis see https://redis.io/
* C++ built in types among other things. You will be able to
* implement your own redis client or use a general purpose provided
* by the library. For more information about Redis see
* https://redis.io/
*
* \b Using \b Aedis
*
@@ -54,12 +55,7 @@
- intro.cpp
Some commands are sent to the Redis server and the responses are
printed to screen.
- key_expiration.cpp
Shows how to use \c std::optional to deal with keys that may
have expired or do not exist.
printed to screen. A good starting point.
- transaction.cpp
@@ -73,7 +69,8 @@
Shows how to read responses to commands that cannot be
translated in a C++ built-in type like std::string or STL
containers, for example all commands contained in a transaction
will be nested by Redis in a single response.
will be nested by Redis in a single response. Users may have to
convert into their own desired format.
- subscriber.cpp
@@ -83,6 +80,11 @@
Shows hot to use the Aedis synchronous api.
- key_expiration.cpp
Shows how to use \c std::optional to deal with keys that may
have expired or do not exist.
\b STL \b Containers: Many of the Redis data structures can be
directly translated in to STL containers, below you will find some
example code. For a list of Redis data types see
@@ -105,7 +107,8 @@
\b Customization \b points: Shows how de/serialize user types
avoiding copies. This is particularly useful for low latency
applications.
applications that want to avoid unneeded copies, for examples when
storing json strings in Redis keys.
- serialization.cpp
@@ -114,7 +117,7 @@
- response_adapter.cpp
Customization point for users that want to de/serialize their
own data-structures.
own data-structures like containers for example.
\b Asynchronous \b servers: Contains some non-trivial examples
servers that interact with users and Redis asynchronously over
@@ -130,7 +133,7 @@
Shows the basic principles behind asynchronous communication
with a database in an asynchronous server. In this case, the
server is a proxy between the user and the database.
server is a proxy between the user and Redis.
- chat_room.cpp
@@ -139,31 +142,31 @@
*/
/** \page installation Installation
* \tableofcontents
*
* \section Requirements
*
* To use Aedis you will need
* Aedis installation requires
*
* Required
* - \b Boost \b 1.78 or greater
* - \b Unix \b Shell
* - \b Make
*
* To use Aedis and build its examples and tests you will need
*
* - \b C++20 with \b coroutine support.
* - \b Boost \b 1.78 or greater.
* - \b Redis \b server.
* - \b Bash to configure that package for installation.
*
* Optional
* Some examples will also require interaction with
*
* - \b Redis \b Sentinel \b server: used in some examples..
* - \b Redis \b client: used in some examples.
* - \b Make to build the examples and tests.
* - \b Redis-client: used in on example.
* - \b Redis \b Sentinel \b server: used in some examples.
*
* \section Installing
*
* Download
*
* Get the latest release and follow the steps
*
* ```bash
* ```
* # Download the libray on github.
* $ wget github-link
*
@@ -176,17 +179,22 @@
*
* ```
*
* Install
* To install the library run
*
* ```bash
* # Optional: Build aedis examples.
* ```
* # Install Aedis in the path specified in --prefix
* $ sudo make install
*
* ```
*
* To build the examples and test the library in your machine
*
* ```
* # Build aedis examples.
* $ make examples
*
* # Optional: Test aedis in your machine.
* # Test aedis in your machine.
* $ make check
*
* # Install the aedis.
* $ sudo make install
* ```
*
* \section using Using Aedis
@@ -205,7 +213,7 @@
* Aedis uses Autotools for its build system. To generate the build
* system run
*
* ```bash
* ```
* $ autoreconf -i
* ```
*
@@ -213,11 +221,10 @@
* run as explained above, for example, to use a compiler other that
* the system compiler use
*
* ```bash
* ```
* CC=/opt/gcc-10.2.0/bin/gcc-10.2.0\
* CXX=/opt/gcc-10.2.0/bin/g++-10.2.0\
* CXXFLAGS="-std=c++20 -fcoroutines -g -Wall -Wno-subobject-linkage -Werror"\
* ./configure ...
* CXXFLAGS="-std=c++20 -fcoroutines -g -Wall -Wno-subobject-linkage -Werror" ./configure ...
* ```
*/

View File

@@ -7,8 +7,6 @@
#pragma once
#define AEDIS_VERSION @PACKAGE_VERSION@
#include <boost/asio.hpp>
namespace aedis {

View File

@@ -432,6 +432,7 @@ enum class command {
zscore,
/// https://redis.io/commands/zunionstore
zunionstore,
/// Unknown/invalid command.
unknown
};

View File

@@ -291,7 +291,7 @@ template <class Container>
class set {
private:
Container* result_;
Container::iterator hint_;
typename Container::iterator hint_;
public:
set(Container* c = nullptr)
@@ -334,7 +334,7 @@ template <class Container>
class map {
private:
Container* result_;
Container::iterator current_;
typename Container::iterator current_;
bool on_key_ = true;
public:

View File

@@ -21,21 +21,37 @@ namespace sentinel {
* help of the command \c command.
*/
enum class command {
/// https://redis.io/commands/acl
acl,
/// https://redis.io/commands/auth
auth,
/// https://redis.io/commands/client
client,
/// https://redis.io/commands/command
command,
/// https://redis.io/commands/hello
hello,
/// https://redis.io/commands/info
info,
/// https://redis.io/commands/ping
ping,
/// https://redis.io/commands/psubscribe
psubscribe,
/// https://redis.io/commands/publish
publish,
/// https://redis.io/commands/punsubscribe
punsubscribe,
/// https://redis.io/commands/role
role,
/// https://redis.io/topics/sentinel
sentinel,
/// https://redis.io/commands/shutdown
shutdown,
/// https://redis.io/commands/subscribe
subscribe,
/// https://redis.io/commands/unsubscribe
unsubscribe,
/// Unknown/invalid command.
unknown
};

View File

@@ -18,5 +18,5 @@ AC_CHECK_HEADER_STDBOOL
AC_TYPE_UINT64_T
AC_CHECK_TYPES([ptrdiff_t])
AC_CONFIG_FILES([Makefile aedis/config.hpp])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

View File

@@ -44,7 +44,7 @@ PROJECT_NUMBER = 1.0.0
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF = "Redis client library"
PROJECT_BRIEF = "A low level Redis client library"
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55

View File

@@ -24,7 +24,9 @@ div.contents {
padding: 15px;
}
/*
code
{
background-color:#EFD25E;
}
*/

View File

@@ -35,28 +35,28 @@ public:
void on_message(std::error_code ec, command cmd)
{
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
switch (cmd) {
case command::incr:
{
std::cout << "Message so far: " << resps_.number << std::endl;
} break;
case command::unknown: // Push
{
// TODO: Delete sessions lazily on traversal.
for (auto& weak: sessions_) {
if (auto session = weak.lock()) {
session->deliver(resps_.general.at(3).data);
} else {
std::cout << "Session expired." << std::endl;
}
}
case command::incr:
{
std::cout << "Message so far: " << resps_.number << std::endl;
} break;
case command::unknown: // Push
{
// TODO: Delete sessions lazily on traversal.
for (auto& weak: sessions_) {
if (auto session = weak.lock()) {
session->deliver(resps_.general.at(3).data);
} else {
std::cout << "Session expired." << std::endl;
}
}
resps_.general.clear();
} break;
resps_.general.clear();
} break;
default: { /* Ignore */ }
}
}

View File

@@ -35,26 +35,26 @@ public:
void on_message(std::error_code ec, command cmd)
{
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
switch (cmd) {
case command::ping:
{
if (auto session = sessions_.front().lock()) {
session->deliver(resps_.simple_string);
} else {
std::cout << "Session expired." << std::endl;
}
case command::ping:
{
if (auto session = sessions_.front().lock()) {
session->deliver(resps_.simple_string);
} else {
std::cout << "Session expired." << std::endl;
}
sessions_.pop();
resps_.simple_string.clear();
} break;
case command::incr:
{
std::cout << "Echos so far: " << resps_.number << std::endl;
} break;
sessions_.pop();
resps_.simple_string.clear();
} break;
case command::incr:
{
std::cout << "Echos so far: " << resps_.number << std::endl;
} break;
default: { assert(false); }
}
}
@@ -80,9 +80,9 @@ net::awaitable<void> listener()
auto on_user_msg = [db, recv, session](std::string const& msg)
{
db->send(command::ping, msg);
db->send(command::incr, "echo-counter");
recv->add_user_session(session);
db->send(command::ping, msg);
db->send(command::incr, "echo-counter");
recv->add_user_session(session);
};
session->start(on_user_msg);

View File

@@ -25,17 +25,16 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
// Shows how to serialize and read redis hashes in C++ containers.
net::awaitable<void> containers()
{
try {
auto socket = co_await connect();
std::map<std::string, std::string> map
{ {"key1", "value1"}
, {"key2", "value2"}
, {"key3", "value3"}
};
{ {"key1", "value1"}
, {"key2", "value2"}
, {"key3", "value3"}
};
// Creates and sends the request.
std::string request;
@@ -63,7 +62,7 @@ net::awaitable<void> containers()
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(hgetall1));
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(hgetall2));
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(hgetall3));
co_await resp3::async_read(socket, dynamic_buffer(buffer));
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // quit
// Prints the responses.
std::cout << "hset: " << hset;

View File

@@ -37,17 +37,17 @@ net::awaitable<void> ping()
sr.push(command::quit);
co_await async_write(socket, buffer(request));
// Expected responses.
// Responses we are interested in.
int incr;
std::string ping;
// Reads the responses.
// Reads the responses to ping and incr, ignore the others.
std::string buffer;
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // hello (ignored)
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // flushall
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // hello
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // flushall
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(ping));
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(incr));
co_await resp3::async_read(socket, dynamic_buffer(buffer));
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // quit
// Print the responses.
std::cout

View File

@@ -25,8 +25,6 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/// Shows how to deal with keys that may not exist.
net::awaitable<void> key_expiration()
{
try {
@@ -48,12 +46,12 @@ net::awaitable<void> key_expiration()
std::string rbuffer;
co_await resp3::async_read(socket, dynamic_buffer(rbuffer)); // hello
co_await resp3::async_read(socket, dynamic_buffer(rbuffer)); // flushall
co_await resp3::async_read(socket, dynamic_buffer(rbuffer));
co_await resp3::async_read(socket, dynamic_buffer(rbuffer)); // set
co_await resp3::async_read(socket, dynamic_buffer(rbuffer), adapt(get));
std::cout
<< "Before expiration: " << get.has_value() << ", "
<< *get << "\n";
<< *get << std::endl;
// Waits some seconds for the key to expire.
timer tm{socket.get_executor(), std::chrono::seconds{3}};

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com)
/* Copyright (c) 2019 Marcelo Zimbres Silva (mzimbres@gmail.com)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -26,15 +26,6 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/* Shows how to work with redis lists.
First we store a list of elements in a redis list, then the list is
read back in different C++ containers to give the user a feeling of
what is possible.
To store your own types in the lists see serialization.cpp.
*/
net::awaitable<void> ping()
{
try {

View File

@@ -26,9 +26,6 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
// Reads the response to a transaction in a general format that is
// suitable for all kinds of responses, but which users may have to
// convert into their own desired format.
net::awaitable<void> nested_response()
{
try {

View File

@@ -23,28 +23,28 @@ int main()
auto on_msg = [&resps](std::error_code ec, command cmd)
{
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
if (ec) {
std::cerr << "Error: " << ec.message() << std::endl;
return;
}
switch (cmd) {
case command::ping:
{
std::cout << "ping: " << resps.simple_string << std::endl;
resps.simple_string.clear();
} break;
case command::quit:
{
std::cout << "quit: " << resps.simple_string << std::endl;
resps.simple_string.clear();
} break;
case command::incr:
{
std::cout << "incr: " << resps.number << std::endl;
} break;
default: { assert(false); }
}
switch (cmd) {
case command::ping:
{
std::cout << "ping: " << resps.simple_string << std::endl;
resps.simple_string.clear();
} break;
case command::quit:
{
std::cout << "quit: " << resps.simple_string << std::endl;
resps.simple_string.clear();
} break;
case command::incr:
{
std::cout << "incr: " << resps.number << std::endl;
} break;
default: { assert(false); }
}
};
net::io_context ioc{1};

View File

@@ -24,12 +24,6 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/* In the serialization.cpp example we saw how to serialize and
deserialize Redis responses in user custom types. When serializing
in custom containers users have to define their own response
adapter. This example illustrates how to do this.
*/
// An adapter that prints the data it receives in the screen.
struct myadapter {
void operator()(

View File

@@ -24,17 +24,8 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/* Illustrates how to serialize your own data.
Some use cases for this functionality are
1. Improve performance and reduce latency by avoiding copies.
2. Store json objets in redis.
3. etc.
Proceedure: Define the to_string and from_string functions for your
own data types.
*/
// Define the to_string and from_string functions for your own data
// types.
// The struct we would like to store in redis using our own
// serialization.

View File

@@ -25,15 +25,13 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/// Shows how to serialize and read redis sets in C++ containers.
net::awaitable<void> containers()
{
try {
auto socket = co_await connect();
std::set<std::string> set
{"one", "two", "three", "four"};
{"one", "two", "three", "four"};
// Creates and sends the request.
std::string request;
@@ -61,7 +59,7 @@ net::awaitable<void> containers()
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(smembers1));
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(smembers2));
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(smembers3));
co_await resp3::async_read(socket, dynamic_buffer(buffer));
co_await resp3::async_read(socket, dynamic_buffer(buffer)); // quit
// Prints the responses.
std::cout << "sadd: " << sadd;

View File

@@ -24,16 +24,14 @@ using net::async_write;
using net::buffer;
using net::dynamic_buffer;
/* In previous examples we sent some commands (ping) to redis and
quit (closed) the connection. In this example we send a
subscription to a channel and start reading server side messages
indefinitely.
/* In this example we send a subscription to a channel and start
reading server side messages indefinitely.
Notice we store the id of the connection (attributed by the redis
server) to be able to identify it (in the logs for example).
After starting the example you can test it by sending messages with
the redis-client like this
redis-cli like this
$ redis-cli -3
127.0.0.1:6379> PUBLISH channel1 some-message
@@ -66,12 +64,12 @@ net::awaitable<void> subscriber()
// Loops to receive server pushes.
for (;;) {
resp.clear();
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(resp));
resp.clear();
co_await resp3::async_read(socket, dynamic_buffer(buffer), adapt(resp));
std::cout
<< "Subscriber " << id << ":\n"
<< resp << std::endl;
std::cout
<< "Subscriber " << id << ":\n"
<< resp << std::endl;
}
} catch (std::exception const& e) {
std::cerr << e.what() << std::endl;