Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
79 changes: 79 additions & 0 deletions content/develop/clients/hiredis/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,83 @@ freeReplyObject(reply);
redisFree(c);
```

## Asynchronous connection

You can also connect to Redis using an asynchronous API.
The `redisAsyncConnect()` call that creates the context is
similar to the synchronous function `redisConnect()`, but it returns the
context object immediately before the connection is complete.
It lets you supply callbacks to respond when a connection is successful
or to handle any errors that may occur.

The following code creates an asynchronous connection and
sets the context callbacks:

```c
#include <stdio.h>

#include "hiredis.h"
#include "async.h"
.
.
.

redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);

if (c->err) {
printf("Error: %s\n", c->errstr);
return 1;
}

// Set callbacks to respond to successful or unsuccessful
// connection and disconnection.
redisAsyncSetConnectCallback(c, connectCallback);
redisAsyncSetDisconnectCallback(c, disconnectCallback);

char *key = "testkey";
char *value = "testvalue";

// Status reply is ignored.
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);

// Reply handled by `getCallback()` function.
redisAsyncCommand(c, getCallback, key, "GET %s", key);
```

The callback functions have a simple signature that receives
the context object and a status code. See
[Handling errors]({{< relref "/develop/clients/hiredis/handle-replies#handling-errors" >}})
for a list of the possible status codes.

```c
void connectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}

void disconnectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Disconnected...\n");
}
```

Use the `redisAsyncCommand()` function to issue Redis commands
with an asynchronous connection. This is similar to the equivalent
synchronous function `redisCommand()` but also lets you supply a callback
and a custom data pointer to process the response to the command. See
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}}) for more
information.

Note that you should normally disconnect asynchronously from a
callback when you have finished using the connection.
Use `redisAsyncDisconnect()` to disconnect gracefully, letting
pending commands execute and activate their callbacks.
Use `redisAsyncFree()` to disconnect immediately. If you do this then
any pending callbacks from commands that have already executed will be
called with a `NULL` reply pointer.
22 changes: 22 additions & 0 deletions content/develop/clients/hiredis/int-examples/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
categories:
- docs
- develop
- stack
- oss
- rs
- rc
- oss
- kubernetes
- clients
description: Integrate hiredis with C++ and external frameworks.
linkTitle: Integration guides
title: Integration guides
weight: 50
---

`hiredis` is compatible with C++ and the library source includes a set of
[adapters](https://github.com/redis/hiredis/tree/master/adapters)
to help you use it in conjunction with C and C++ libraries and frameworks.
The pages in this section explain how to integrate `hiredis` into
your app.
176 changes: 176 additions & 0 deletions content/develop/clients/hiredis/int-examples/libevent-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
categories:
- docs
- develop
- stack
- oss
- rs
- rc
- oss
- kubernetes
- clients
description: Use `hiredis` in conjunction with the `libevent` framework.
linkTitle: libevent integration
title: Integrate hiredis with a libevent app
weight: 60
---

The [`libevent`](https://libevent.org/) library provides an
implementation of an event loop that lets you call functions
asynchronously in response to events. This guide explains
how to use `hiredis` to connect to a Redis server from a
`libevent` app.

## Install `libevent`

The [`libevent` home page](https://libevent.org/) has links to download
all versions of the library, but you should use the latest version
unless there is a specific version you need to target.

When you have downloaded `libevent`, follow the instructions in the
`README` file to compile and install the library.

## Create a simple app

For a real project, you would build your code with a makefile, but for
this simple test, you can just place it in a file called `main.c` and
build it with the following command (assuming you used `make install` to
install the `libhiredis` and `libevent` libraries):

```bash
cc main.c -L/usr/local/lib -lhiredis -levent
```

See [Build and install]({{< relref "/develop/clients/hiredis#build-and-install" >}})
to learn how to build `hiredis`, if you have not already done so.

Add the following header files from the `hiredis` folder to your project folder:

- `hiredis.h`
- `async.h`
- `adapters/libevent.h`

You should include the `libevent.h` file in a folder called `adapters` but you
don't need the other headers in the original `adapters` folder for this
example.

Now, add the following code in `main.c`. An explanation follows the
code example:

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include "hiredis.h"
#include "async.h"
#include "adapters/libevent.h"

// Callback for the `GET` command.
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
char *key = privdata;

if (reply == NULL) {
if (c->errstr) {
printf("errstr: %s\n", c->errstr);
}
return;
}

printf("Key: %s, value: %s\n", key, reply->str);

/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect(c);
}

// Callback to respond to successful or unsuccessful connection.
void connectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Connected...\n");
}

// Callback to respond to intentional or unexpected disconnection.
void disconnectCallback(const redisAsyncContext *c, int status) {
if (status != REDIS_OK) {
printf("Error: %s\n", c->errstr);
return;
}
printf("Disconnected...\n");
}


int main (int argc, char **argv) {
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif

// Create the libevent `event_base` object to track all
// events.
struct event_base *base = event_base_new();

redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);

if (c->err) {
printf("Error: %s\n", c->errstr);
return 1;
}

// Use the Redis libevent adapter to attach the Redis connection
// to the libevent main loop.
redisLibeventAttach(c,base);

redisAsyncSetConnectCallback(c, connectCallback);
redisAsyncSetDisconnectCallback(c, disconnectCallback);

char *key = "testkey";
char *value = "testvalue";

redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
redisAsyncCommand(c, getCallback, key, "GET %s", key);

// Run the event loop.
event_base_dispatch(base);

return 0;
}
```

The code calls
[`event_base_new()`](https://libevent.org/doc/event_8h.html#af34c025430d445427a2a5661082405c3)
to initialize the core
[`event_base`](https://libevent.org/doc/structevent__base.html)
object that manages the event loop. It then creates a standard
[asynchronous connection]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}})
to Redis and uses the `libevent` adapter function `redisLibeventAttach()` to
attach the connection to the event loop.

After setting the [connection callbacks]({{< relref "/develop/clients/hiredis/connect#asynchronous-connection" >}}), the code issues two asynchronous
Redis commands (see
[Construct asynchronous commands]({{< relref "/develop/clients/hiredis/issue-commands#construct-asynchronous-commands" >}})
for more information).
The final step is to call
[`event_base_dispatch()`](https://libevent.org/doc/event_8h.html#a19d60cb72a1af398247f40e92cf07056)
to start the event loop. This will wait for the commands to be processed and
then exit when the Redis connection is closed in the `getCallback()` function.

## Run the code

If you compile and run the code, you will see the following output,
showing that the callbacks executed correctly:

```
Connected...
Key: testkey, value: testvalue
Disconnected...
```

You can use the
[`KEYS`]({{< relref "/commands/keys" >}}) command from
[`redis-cli`]({{< relref "/develop/tools/cli" >}}) or
[Redis Insight]({{< relref "/develop/tools/insight" >}}) to check
that the "testkey" string key was added to the Redis database.
Loading