valdemargr / sdis

Redis for scala

Version Matrix

sdis

Redis for scala

Usage

The library returns Either[String, T] on successfully executed queries, where successful implies queries that return non-error RESP types (https://redis.io/topics/protocol).
The library can also return Try[T], typically caused from connection issues such as timeouts. It is a user choice whether to throw the exception or handle it.

To use the library, a connection to your redis instance is required.

val client: Try[RedisClient] = sdis.client.RedisClient.getInstance("localhost", 6379)

Queries are detached from the client, so batched queries that utilize pipelining for maximum efficiency (https://redis.io/topics/pipelining).
Queries are typely defined through interfaces representing the Redis operations for some type, like a string operation.

val insertion: sdis.operations.RedisQuery.StringRedisQuery = sdis.operations.RedisStringOperations.set("1", "1")

The StringRedisQuery class is just a wrapper for the query which is a RESP array sdis.parser.RESPInterface.Array, and some associated methods for handling Redis strings.
Such classes exist for all the query results.

A query can be executed by simply passing it to the client.

import scala.util.Try
import sdis.redistypes._
import sdis.operations.RedisQuery._
import sdis.client._

val client = RedisClient.getInstance("localhost", 6379).get

val insertion: StringRedisQuery = sdis.operations.RedisStringOperations.set("1", "1")

val result: Try[Either[String, RedisString]] = client.run(insertion)

Pipelining

Much focus of this library has been to make pipelining elegant and easy to use, since doing things fast is a selling point for redis (personally I have met up to 15x speedups by pipelining some benchmark queries).

Pipelining can be done in two ways, either using the tuple run function (with a 22 argument limitation :)) or using a sequence of queries.

Using tupled run

import scala.util.Try
import sdis.redistypes._
import sdis.operations.RedisQuery._
import sdis.client._

val client = RedisClient.getInstance("localhost", 6379).get

val insertion1: StringRedisQuery = sdis.operations.RedisStringOperations.set("1", "1")
val insertion2: StringRedisQuery = sdis.operations.RedisStringOperations.set("2", "2")
val insertion3: StringRedisQuery = sdis.operations.RedisStringOperations.set("3", "3")

val insertionResult = client.run(insertion1, insertion2, insertion3)

val get1: StringRedisQuery = sdis.operations.RedisStringOperations.get("1")
val get2: StringRedisQuery = sdis.operations.RedisStringOperations.get("2")
val get3: StringRedisQuery = sdis.operations.RedisStringOperations.get("3")

val getResults: Try[(Either[String, RedisString], Either[String, RedisString], Either[String, RedisString])] = client.run(insertion1, insertion2, insertion3)

val (r1, r2, r3) = getResults.get

assert(r3.right.get.get == "3")

Using list of queries

import scala.util.Try
import sdis.redistypes._
import sdis.operations.RedisQuery._
import sdis.operations._
import sdis.client._

val client = RedisClient.getInstance("localhost", 6379).get

val insertion1: StringRedisQuery = sdis.operations.RedisStringOperations.set("1", "1")
val insertion2: StringRedisQuery = sdis.operations.RedisStringOperations.set("2", "2")
val insertion3: StringRedisQuery = sdis.operations.RedisStringOperations.set("3", "3")

val insertions: Seq[RedisQuery] = Seq(
    insertion1,
    insertion2,
    insertion3
)

val insertionResult: RedisMultiQueryResult = client.run(insertions)

val get1: StringRedisQuery = sdis.operations.RedisStringOperations.get("1")
val get2: StringRedisQuery = sdis.operations.RedisStringOperations.get("2")
val get3: StringRedisQuery = sdis.operations.RedisStringOperations.get("3")

val gets: Seq[RedisQuery] = Seq(
    get1,
    get2,
    get3
)

val getResults: RedisMultiQueryResult = client.run(gets)

val getResult1: Either[String, RedisString] = getResults.get(get1)
val getResult2: Either[String, RedisString] = getResults.get(get2)
val getResult3: RedisString = getResults.get(get3).right.get

assert(getResult3.get == "3")

Motivation

I was using redis in a project, I disliked the scala-redis library for various reasons such as the very java-like way it has been written. Other libraries seemed a bit overkill for what I think redis is supposed to be, so I wrote my own.

It runs faster than the scala-redis client anyways
benchmark