# Vert.x-redis

Vert.x-redis is redis client to be used with Vert.x.

This module allows data to be saved, retrieved, searched for, and deleted in a Redis. Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. To use this module you must have a Redis server instance running on your network.

Redis has a rich API and it can be organized in the following groups:

- Cluster - Commands related to cluster management, note that using most of these commands you will need a redis server with version >=3.0.0

- Connection - Commands that allow you to switch DBs, connect, disconnect and authenticate to a server.

- Hashes - Commands that allow operations on hashes.

- HyperLogLog - Commands to approximating the number of distinct elements in a multiset, a HyperLogLog.

- Keys - Commands to work with Keys.

- List - Commands to work with Lists.

- Pub/Sub - Commands to create queues and pub/sub clients.

- Scripting - Commands to run Lua Scripts in redis.

- Server - Commands to manage and get server configurations.

- Sets - Commands to work with un ordered sets.

- Sorted Sets - Commands to work with sorted sets.

- Strings - Commands to work with Strings.

- Transactions - Commands to handle transaction lifecycle.

## Using Vert.x-Redis

To use the Vert.x Redis client, add the following dependency to the dependencies section of your build descriptor:

- Maven (in your `pom.xml`):

    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-redis-client-scala_2.12</artifactId>
      <version>3.4.1</version>
    </dependency>

- Gradle (in your `build.gradle` file):

    compile 'io.vertx:vertx-redis-client-scala_2.12:3.4.1'

## Connecting to Redis

In order to connect to Redis there is a config required. This config is provided in the form of `RedisOptions` containing the following values:

- `host`: default is `localhost`

- `port`: default is `6379`

- `encoding`: default is `UTF-8`

- `tcpKeepAlive`: default `true`

- `tcpNoDelay`: default `true`

An connection example can then be:

    var config = RedisOptions()
      .setHost("127.0.0.1")

    var redis = RedisClient.create(vertx, config)

The client attempts to reconnect to the server on connection errors, for this reason if you are connecting to a server that requires authentication and/or you are not using the default database you must provide the authentication password and/or database id to the config object, the properties names are:

- `auth`

- `select`

If you do not do this and manually call the `auth` or `select` then the client will not know how to recover the connection in case of socket error.

## Running commands

Given that the redis client is connected to the server, all commands are now possible to execute using this module. The module offers a clean API for executing commands without the need to hand write the command itself, for example if one wants to get a value of a key it can be done as:

    var redis = RedisClient.create(vertx, RedisOptions())

    redis.getFuture("mykey").onComplete{
      case Success(result) => {
        // so something...
      }
      case Failure(cause) => println("Failure")
    }

In order to know more about the commands available you should look at: <a href="http://redis.io/commands">redis documentation</a>.

## Pub/Sub mode

Redis supports queues and pub/sub mode, when operated in this mode once a connection invokes a subscriber mode then it cannot be used for running other commands than the command to leave that mode.

To start a subscriber one would do:

    // register a handler for the incoming message the naming the Redis module will use is base address + '.' + redis channel
    vertx.eventBus().consumer("io.vertx.redis.channel1", (received: io.vertx.scala.core.eventbus.Message<io.vertx.scala.core.json.JsonObject>) => {
      // do whatever you need to do with your message
      var value = received.body().getValue("value")
      // the value is a JSON doc with the following properties
      // channel - The channel to which this message was sent
      // pattern - Pattern is present if you use psubscribe command and is the pattern that matched this message channel
      // message - The message payload
    })

    var redis = RedisClient.create(vertx, RedisOptions())

    redis.subscribeFuture("channel1").onComplete{
      case Success(result) => {
        // so something...
      }
      case Failure(cause) => println("Failure")
    }

And from another place in the code publish messages to the queue:

    var redis = RedisClient.create(vertx, RedisOptions())

    redis.publishFuture("channel1", "Hello World!").onComplete{
      case Success(result) => {
        // so something...
      }
      case Failure(cause) => println("Failure")
    }

## Friendlier hash commands

Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings. When dealing with hash values, there are a couple of useful exceptions to this.

### Command hgetall

The reply from an hgetall command will be converted into a JSON Object. That way you can interact with the responses using JSON syntax which is handy for the EventBus communication.

### command mset

Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings.

    {
      keyName: "value",
      otherKeyName: "other value"
    }

### command msetnx

Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings.

    {
      keyName: "value",
      otherKeyName: "other value"
    }

### command hmset

Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings.

    {
      keyName: "value",
      otherKeyName: "other value"
    }

### command zadd

Multiple values in a hash can be set by supplying an object. Note however that key and value will be coerced to strings.

    {
      score: "member",
      otherScore: "other member"
    }

## Server Info

In order to make it easier to work with the info response you don’t need to parse the data yourself and the module will return it in a easy to understand JSON format. The format is as follows: A JSON object for each section filled with properties that belong to that section. If for some reason there is no section the properties will be visible at the top level object.

    {
      server: {
        redis_version: "2.5.13",
        redis_git_sha1: "2812b945",
        redis_git_dirty: "0",
        os: "Linux 2.6.32.16-linode28 i686",
        arch_bits: "32",
        multiplexing_api: "epoll",
        gcc_version: "4.4.1",
        process_id: "8107",
        ...
      },
      memory: {...},
      client: {...},
      ...
    }

## Eval and Evalsha

Eval and Evalsha commands are special due to its return value can be any type. Vert.x is built on top of Java and the language adheres to strong typing so returning any type turns to be problematic since we want to avoid having `Object` type being used. The reason to avoid the type `Object` is that we also are polyglot and the conversion between languages would become rather complicated and hard to implement. For all these reasons the commands eval and evalsha will always return a JsonArray, even for example for scripts such as:

    return 10

In this case the return value will be a json array with the value 10 on index 0.