All Downloads are FREE. Search and download functionalities are using the official Maven repository.

redis.Redis.scala Maven / Gradle / Ivy

The newest version!
package redis

import akka.actor._
import akka.util.Helpers
import redis.commands._
import scala.concurrent._
import java.net.InetSocketAddress
import redis.actors.{RedisSubscriberActorWithCallback, RedisClientActor}
import redis.api.pubsub._
import java.util.concurrent.atomic.AtomicLong
import akka.event.Logging

import scala.concurrent.duration.FiniteDuration

trait RedisCommands
  extends Keys
  with Strings
  with Hashes
  with Lists
  with Sets
  with SortedSets
  with Publish
  with Scripting
  with Connection
  with Server
  with HyperLogLog
  with Clusters
  with Geo

abstract class RedisClientActorLike(system: ActorSystem, redisDispatcher: RedisDispatcher, connectTimeout: Option[FiniteDuration] = None) extends ActorRequest {
  var host: String
  var port: Int
  val name: String
  val password: Option[String] = None
  val db: Option[Int] = None
  implicit val executionContext = system.dispatchers.lookup(redisDispatcher.name)

  val redisConnection: ActorRef = system.actorOf(RedisClientActor.props(new InetSocketAddress(host, port),
    getConnectOperations, onConnectStatus, redisDispatcher.name, connectTimeout)
      .withDispatcher(redisDispatcher.name),
    name + '-' + Redis.tempName()
  )

  def reconnect(host: String = host, port: Int = port) = {
    if (this.host != host || this.port != port ) {
      this.host = host
      this.port = port
      redisConnection ! new InetSocketAddress(host, port)
    }
  }

  def onConnect(redis: RedisCommands): Unit = {
    password.foreach(redis.auth(_)) // TODO log on auth failure
    db.foreach(redis.select(_))
  }

  def onConnectStatus: (Boolean) => Unit = (status: Boolean) => {

  }

  def getConnectOperations: () => Seq[Operation[_, _]] = () => {
    val self = this
    val redis = new BufferedRequest with RedisCommands {
      implicit val executionContext: ExecutionContext = self.executionContext
    }
    onConnect(redis)
    redis.operations.result()
  }

  /**
   * Disconnect from the server (stop the actor)
   */
  def stop(): Unit = {
    system stop redisConnection
  }
}

case class RedisClient(var host: String = "localhost",
                       var port: Int = 6379,
                       override val password: Option[String] = None,
                       override val db: Option[Int] = None,
                       name: String = "RedisClient",
                       connectTimeout: Option[FiniteDuration] = None)
                      (implicit _system: ActorSystem,
                       redisDispatcher: RedisDispatcher = Redis.dispatcher
                      ) extends RedisClientActorLike(_system, redisDispatcher, connectTimeout) with RedisCommands with Transactions {

}

case class RedisBlockingClient(var host: String = "localhost",
                               var port: Int = 6379,
                               override val password: Option[String] = None,
                               override val db: Option[Int] = None,
                               name: String = "RedisBlockingClient",
                               connectTimeout: Option[FiniteDuration] = None)
                              (implicit _system: ActorSystem,
                               redisDispatcher: RedisDispatcher = Redis.dispatcher
                              ) extends RedisClientActorLike(_system, redisDispatcher, connectTimeout) with BLists {
}

case class RedisPubSub(
                        host: String = "localhost",
                        port: Int = 6379,
                        channels: Seq[String],
                        patterns: Seq[String],
                        onMessage: Message => Unit = _ => {},
                        onPMessage: PMessage => Unit = _ => {},
                        authPassword: Option[String] = None,
                        name: String = "RedisPubSub"
                        )(implicit system: ActorRefFactory,
                          redisDispatcher: RedisDispatcher = Redis.dispatcher) {

  val redisConnection: ActorRef = system.actorOf(
    Props(classOf[RedisSubscriberActorWithCallback],
      new InetSocketAddress(host, port), channels, patterns, onMessage, onPMessage, authPassword,onConnectStatus)
      .withDispatcher(redisDispatcher.name),
    name + '-' + Redis.tempName()
  )

  /**
   * Disconnect from the server (stop the actor)
   */
  def stop(): Unit = {
    system stop redisConnection
  }

  def subscribe(channels: String*): Unit = {
    redisConnection ! SUBSCRIBE(channels: _*)
  }

  def unsubscribe(channels: String*): Unit = {
    redisConnection ! UNSUBSCRIBE(channels: _*)
  }

  def psubscribe(patterns: String*): Unit = {
    redisConnection ! PSUBSCRIBE(patterns: _*)
  }

  def punsubscribe(patterns: String*): Unit = {
    redisConnection ! PUNSUBSCRIBE(patterns: _*)
  }

  def onConnectStatus(): (Boolean) => Unit = (status: Boolean) => {

  }
}

case class SentinelMonitoredRedisClient( sentinels: Seq[(String, Int)] = Seq(("localhost", 26379)),
                                         master: String,
                                         password: Option[String] = None,
                                         db: Option[Int] = None,
                                         name: String = "SMRedisClient")
                                       (implicit system: ActorSystem,
                                        redisDispatcher: RedisDispatcher = Redis.dispatcher
                                        ) extends SentinelMonitoredRedisClientLike(system, redisDispatcher) with RedisCommands with Transactions {

  val redisClient: RedisClient = withMasterAddr((ip, port) => {
    new RedisClient(ip, port, password, db, name)
  })
  override val onNewSlave  =  (ip: String, port: Int) => {}
  override val onSlaveDown =  (ip: String, port: Int) => {}
}


case class SentinelMonitoredRedisBlockingClient( sentinels: Seq[(String, Int)] = Seq(("localhost", 26379)),
                                                 master: String,
                                                 password: Option[String] = None,
                                                 db: Option[Int] = None,
                                                 name: String = "SMRedisBlockingClient")
                                               (implicit system: ActorSystem,
                                                redisDispatcher: RedisDispatcher = Redis.dispatcher
                                                ) extends SentinelMonitoredRedisClientLike(system, redisDispatcher) with BLists {
  val redisClient: RedisBlockingClient = withMasterAddr((ip, port) => {
    new RedisBlockingClient(ip, port, password, db, name)
  })
  override val onNewSlave =  (ip: String, port: Int) => {}
  override val onSlaveDown =  (ip: String, port: Int) => {}
}

case class RedisDispatcher(name: String)

private[redis] object Redis {
  val dispatcher = RedisDispatcher("rediscala.rediscala-client-worker-dispatcher")

  val tempNumber = new AtomicLong

  def tempName() = Helpers.base64(tempNumber.getAndIncrement())

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy