Skip to content
This repository has been archived by the owner on Feb 9, 2019. It is now read-only.

added support for JedisSentinelPool #101

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
8 changes: 6 additions & 2 deletions redis/project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ object MinimalBuild extends Build {
lazy val typesafe = "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
lazy val repo = if (buildVersion.endsWith("SNAPSHOT")) typesafeSnapshot else typesafe
lazy val pk11 = "pk11 repo" at "http://pk11-scratch.googlecode.com/svn/trunk"
// for jedis-2.2.2-SNAPSHOT which sedis 1.2.0 depends on
lazy val sonatype = "sonatype repo" at "http://oss.sonatype.org/content/groups/public"
lazy val root = Project(id = "play-plugins-redis", base = file("."), settings = Project.defaultSettings).settings(
version := "2.2.0",
version := "2.2.1-SNAPSHOT",
scalaVersion := "2.10.2",
//publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/.m2/repository"))),
publishTo <<= (version) { version: String =>
val nexus = "https://private-repo.typesafe.com/typesafe/"
if (version.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "maven-snapshots/")
Expand All @@ -20,10 +23,11 @@ object MinimalBuild extends Build {
organization := "com.typesafe",
resolvers += repo,
resolvers += pk11,
resolvers += sonatype,
javacOptions += "-Xlint:unchecked",
libraryDependencies += "biz.source_code" % "base64coder" % "2010-12-19",
libraryDependencies += "com.typesafe" %% "play-plugins-util" % buildVersion,
libraryDependencies += "com.typesafe.play" %% "play-cache" % buildVersion % "provided",
libraryDependencies += "org.sedis" % "sedis_2.10.0" % "1.1.1"
libraryDependencies += "org.sedis" % "sedis_2.10.0" % "1.2.0"
)
}
2 changes: 2 additions & 0 deletions redis/sample/app/Global.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class Global extends GlobalSettings {

public void onStart(Application app) {
JedisPool p = app.plugin(RedisPlugin.class).jedisPool();
// uncomment to test sentinel setup
//JedisSentinelPool p = app.plugin(RedisPlugin.class).jedisSentinelPool();
Jedis j = p.getResource();
j.set("foo","yay");
p.returnResource(j);
Expand Down
2 changes: 2 additions & 0 deletions redis/sample/app/controllers/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class Application extends Controller {

public static Result index() {
JedisPool p = Play.application().plugin(RedisPlugin.class).jedisPool();
// uncomment to test sentinel setup
//JedisSentinelPool p = Play.application().plugin(RedisPlugin.class).jedisSentinelPool();
Jedis j = p.getResource();
String r = j.get("foo") + " - foo2:" + j.get("foo2");
p.returnResource(j);
Expand Down
6 changes: 6 additions & 0 deletions redis/sample/conf/application.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# This is the main configuration file for the application.
# ~~~~~

# enable to test sentinel setup
redis.sentinel.mode=false
redis.sentinel.hosts=["localhost:26379", "localhost:26380"]
redis.master.name=mymaster
#redis.key.prefix=AppName

# Secret key
# ~~~~~
# The secret key is used to secure cryptographics functions.
Expand Down
2 changes: 1 addition & 1 deletion redis/sample/project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object ApplicationBuild extends Build {
val appVersion = "1.0-SNAPSHOT"

val appDependencies = Seq(
"com.typesafe" %% "play-plugins-redis" % "2.2.0",
"com.typesafe" %% "play-plugins-redis" % "2.2.1-SNAPSHOT",
"com.typesafe.play" %% "play-cache" % "2.2.0"
)

Expand Down
109 changes: 80 additions & 29 deletions redis/src/main/scala/com/typesafe/plugin/RedisPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import play.api._
import org.sedis._
import redis.clients.jedis._
import play.api.cache._
import java.util._
import java.io._
import java.net.URI
import biz.source_code.base64Coder._
import org.apache.commons.lang3.builder._
import org.apache.commons.pool.impl.GenericObjectPool
import play.api.mvc.Result
import scala.collection.JavaConversions._

/**
* provides a redis client and a CachePlugin implementation
Expand All @@ -37,6 +36,17 @@ class RedisPlugin(app: Application) extends CachePlugin {
private lazy val timeout = app.configuration.getInt("redis.timeout")
.getOrElse(2000)

private lazy val sentinelMode = app.configuration.getBoolean("redis.sentinel.mode")
.getOrElse(false)

private lazy val sentinelHosts : java.util.List[String] = app.configuration.getStringList("redis.sentinel.hosts")
.getOrElse(seqAsJavaList(List("localhost:26379")))

private lazy val masterName = app.configuration.getString("redis.master.name")
.getOrElse("mymaster")

private lazy val keyPrefix = app.configuration.getString("redis.key.prefix")
.getOrElse("")

/**
* provides access to the underlying jedis Pool
Expand All @@ -53,36 +63,54 @@ class RedisPlugin(app: Application) extends CachePlugin {
*/
lazy val sedisPool = new Pool(jedisPool)

/**
* provides access to the underlying jedis sentinel Pool
*/
lazy val jedisSentinelPool = {
val poolConfig = createPoolConfig(app)
Logger.info(s"Redis Plugin enabled. Connecting to Redis sentinels ${sentinelHosts} with timeout ${timeout}.")
Logger.info("Redis Plugin pool configuration: " + new ReflectionToStringBuilder(poolConfig).toString())
val sentinelSet = new java.util.HashSet[String]()
sentinelSet.addAll(sentinelHosts)
new JedisSentinelPool(masterName, sentinelSet, poolConfig, timeout, password)
}

/**
* provides access to the sedis sentinel Pool
*/
lazy val sedisSentinelPool = new SentinelPool(jedisSentinelPool)

private def createPoolConfig(app: Application) : JedisPoolConfig = {
val poolConfig : JedisPoolConfig = new JedisPoolConfig()
app.configuration.getInt("redis.pool.maxIdle").map { poolConfig.maxIdle = _ }
app.configuration.getInt("redis.pool.minIdle").map { poolConfig.minIdle = _ }
app.configuration.getInt("redis.pool.maxActive").map { poolConfig.maxActive = _ }
app.configuration.getInt("redis.pool.maxWait").map { poolConfig.maxWait = _ }
app.configuration.getBoolean("redis.pool.testOnBorrow").map { poolConfig.testOnBorrow = _ }
app.configuration.getBoolean("redis.pool.testOnReturn").map { poolConfig.testOnReturn = _ }
app.configuration.getBoolean("redis.pool.testWhileIdle").map { poolConfig.testWhileIdle = _ }
app.configuration.getLong("redis.pool.timeBetweenEvictionRunsMillis").map { poolConfig.timeBetweenEvictionRunsMillis = _ }
app.configuration.getInt("redis.pool.numTestsPerEvictionRun").map { poolConfig.numTestsPerEvictionRun = _ }
app.configuration.getLong("redis.pool.minEvictableIdleTimeMillis").map { poolConfig.minEvictableIdleTimeMillis = _ }
app.configuration.getLong("redis.pool.softMinEvictableIdleTimeMillis").map { poolConfig.softMinEvictableIdleTimeMillis = _ }
app.configuration.getBoolean("redis.pool.lifo").map { poolConfig.lifo = _ }
app.configuration.getString("redis.pool.whenExhaustedAction").map { setting =>
poolConfig.whenExhaustedAction = setting match {
case "fail" | "0" => GenericObjectPool.WHEN_EXHAUSTED_FAIL
case "block" | "1" => GenericObjectPool.WHEN_EXHAUSTED_BLOCK
case "grow" | "2" => GenericObjectPool.WHEN_EXHAUSTED_FAIL
}
}
app.configuration.getInt("redis.pool.maxIdle").map { poolConfig.setMaxIdle(_) }
app.configuration.getInt("redis.pool.minIdle").map { poolConfig.setMinIdle(_) }
app.configuration.getInt("redis.pool.maxTotal").map { poolConfig.setMaxTotal(_) }
app.configuration.getBoolean("redis.pool.testOnBorrow").map { poolConfig.setTestOnBorrow(_) }
app.configuration.getBoolean("redis.pool.testOnReturn").map { poolConfig.setTestOnReturn(_) }
app.configuration.getBoolean("redis.pool.testWhileIdle").map { poolConfig.setTestWhileIdle(_) }
app.configuration.getLong("redis.pool.timeBetweenEvictionRunsMillis").map { poolConfig.setTimeBetweenEvictionRunsMillis(_) }
app.configuration.getInt("redis.pool.numTestsPerEvictionRun").map { poolConfig.setNumTestsPerEvictionRun(_) }
app.configuration.getLong("redis.pool.minEvictableIdleTimeMillis").map { poolConfig.setMinEvictableIdleTimeMillis(_) }
app.configuration.getLong("redis.pool.softMinEvictableIdleTimeMillis").map { poolConfig.setSoftMinEvictableIdleTimeMillis(_) }
app.configuration.getBoolean("redis.pool.lifo").map { poolConfig.setLifo(_) }
app.configuration.getBoolean("redis.pool.blockWhenExhausted").map { poolConfig.setBlockWhenExhausted(_) }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the new version of jedis now depends on commons pool 2

poolConfig
}

override def onStart() {
sedisPool
if (sentinelMode) {
sedisSentinelPool
} else {
sedisPool
}
}

override def onStop() {
jedisPool.destroy()
if (sentinelMode) {
jedisSentinelPool.destroy()
} else {
jedisPool.destroy()
}
}

override lazy val enabled = {
Expand Down Expand Up @@ -132,10 +160,11 @@ class RedisPlugin(app: Application) extends CachePlugin {
}
val redisV = prefix + "-" + new String( Base64Coder.encode( baos.toByteArray() ) )
Logger.trace(s"Setting key ${key} to ${redisV}")

sedisPool.withJedisClient { client =>
client.set(key,redisV)
if (expiration != 0) client.expire(key,expiration)

if (sentinelMode) {
sedisSentinelPool.withJedisClient { client => setValue(client, key, redisV, expiration) }
} else {
sedisPool.withJedisClient { client => setValue(client, key, redisV, expiration) }
}
} catch {case ex: IOException =>
Logger.warn("could not serialize key:"+ key + " and value:"+ value.toString + " ex:"+ex.toString)
Expand All @@ -145,7 +174,23 @@ class RedisPlugin(app: Application) extends CachePlugin {
}

}
def remove(key: String): Unit = sedisPool.withJedisClient { client => client.del(key) }

private def getFullKey(key: String): String = {
if (keyPrefix.length > 0) keyPrefix + ":" + key else key
}

private def setValue(client: Jedis, key: String, value: String, expiration: Int) {
client.set(getFullKey(key), value)
if (expiration != 0) client.expire(getFullKey(key), expiration)
}

def remove(key: String): Unit = {
if (sentinelMode) {
sedisSentinelPool.withJedisClient { client => client.del(getFullKey(key)) }
} else {
sedisPool.withJedisClient { client => client.del(getFullKey(key)) }
}
}

class ClassLoaderObjectInputStream(stream:InputStream) extends ObjectInputStream(stream) {
override protected def resolveClass(desc: ObjectStreamClass) = {
Expand All @@ -159,7 +204,13 @@ class RedisPlugin(app: Application) extends CachePlugin {
var ois: ObjectInputStream = null
var dis: DataInputStream = null
try {
val rawData = sedisPool.withJedisClient { client => client.get(key) }
val rawData = {
if (sentinelMode) {
sedisSentinelPool.withJedisClient { client => client.get(getFullKey(key)) }
} else {
sedisPool.withJedisClient { client => client.get(getFullKey(key)) }
}
}
rawData match {
case null =>
None
Expand Down