I am trying to figure out the best way to establish a Redis Pool and then make calls to Redis from within a Spray route. I want to make sure that I can use the connection pool for Redis connections. What would be the best way to instantiate the pool and use it within my spray routes? Is there a better way to establish a "global" pool that can be used? Should I create an actor instead and use that to make the redis calls? I am obviously a bit ignorant here.
Crude Redis Client:
object RedisClient {
val pool = new JedisPool(new JedisPoolConfig(), "localhost")
def getValue(key: String): String= {
try{
val jedis = pool.getResource()
//returns redis value
jedis.get(key)
}
}
}
Route that ends up calling a function that uses the Redis Client
trait DemoService extends HttpService {
val messageApiRouting =
path("summary" / Segment / Segment) { (dataset, timeslice) =>
onComplete(getSummary(dataset, timeslice)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete(s"An error occurred: ${ex.getMessage}")
}
}
def getSummary(dataset: String, timeslice: String): Future[String] = Future {
val key = dataset + timeslice
RedisClient.getValue(key)
}
}
As far as I know the Jedis client is not non-blocking and async. So you may not get all the benefits of using Spray if you use a blocking client. I would suggest looking at Rediscala.
Second I would delegate the actual interaction to another actor which has a RedisClient interacting with your Redis instance/cluster.
Finally, you can
complete
a Spray route by giving it aFuture
. This essentially means that your entire pipeline will be async and non-blocking.NOTE: Redis is still single threaded and I don't think there is anyway around that AFAIK.
In general, you should use a reactive driver if possible (e.g., Slick, ReactiveMongo )