Current cluster state known by RedisClusterClient.
Typeclass that steers flat-mapping of RedisBatches and RedisOps with each other.
Typeclass that steers flat-mapping of RedisBatches and RedisOps with each other. It could be defined simpler as:
trait FlatMapper[-L[_],-R[_]] { def flatMap[A,B](left: L[A])(rightFun: A => R[B]): RedisOp[B] }
but unfortunately IntelliJ Scala plugin (3.0.7.31) does not understand that well (in flatMap
callsites)
Represents a sequence of commands that is always executed atomically, using a single network call on a single Redis connection.
One or more RawCommandPacks.
One or more RawCommandPacks. Conceptually pretty much the same as Traversable[RawCommandPack]]
but more lightweight.
One or more raw Redis commands.
One or more raw Redis commands. More lightweight than regular Scala collection (avoids wrapping in case of single element).
Represents a Redis command or a set of commands sent to Redis as a single batch (usually in a single network message).
Represents a Redis command or a set of commands sent to Redis as a single batch (usually in a single network message).
RedisBatch yields a result of type A
which is decoded from responses to commands from this batch.
Execution of a batch may also fail for various reasons. Therefore, RedisBatch contains API that allows
to recover from failures, e.g. RedisBatch.tried.
RedisBatches may be combined with each other to form bigger batches. The simpliest primitive for combining batches is RedisBatch.map2 operation while the most convenient way is by using RedisBatch.sequence operation which is powered by Sequencer typeclass.
RedisBatch can be turned into a RedisOp or executed by RedisExecutor (e.g. one of Redis client implementations).
result yield by this batch
Redis client implementation for Redis Cluster deployments.
Redis client implementation for Redis Cluster deployments. Internally, it uses single RedisNodeClient instance for every known master in the cluster plus a separate connection for monitoring of every known master. RedisNodeClient instances are dynamically created and destroyed as the cluster changes its state.
The cluster client is only able to execute commands or transactions containing keys which determine which master should be contacted. However, it's possible to gain access to RedisNodeClient instances that RedisClusterClient internally uses to connect to every master (see ClusterState and masterClient).
RedisClusterClient can directly execute only RedisBatches. It automatically distributes every batch over multiple cluster masters and handles cluster redirections if necessary. See executeBatch for more details.
RedisClusterClient cannot directly execute RedisOps (e.g. WATCH
-MULTI
-EXEC
transactions).
You must manually access node client for appropriate master through currentState and execute the operation using it.
However, be aware that you must manually handle cluster redirections and cluster state changes while doing so.
Redis client that uses a single, non-reconnectable connection.
Redis client that uses a single, non-reconnectable connection.
This is the most "raw" client implementation and the only one capable of directly executing connection state
changing commands like AUTH
, CLIENT SETNAME
, WATCH
, etc.
However, note that connection-setup commands like AUTH
may also be specified in
ConnectionConfig
(which may also be specified for connections used by RedisNodeClient and RedisClusterClient).
This type of client should only be used when requiring capability of manual handling of connection state. If you simply need a single-connection, reconnectable client, use RedisNodeClient with connection pool size configured to 1.
Marker subtype of RedisExecutor which guarantees ability to execute all commands implemented by the driver, including the ones that change or access connection state.
Typeclass which expresses that values of some type are serializable to binary form (ByteString
) and deserializable
from it in order to use them as keys, hash keys and values in Redis commands.
Typeclass which expresses that values of some type are serializable to binary form (ByteString
) and deserializable
from it in order to use them as keys, hash keys and values in Redis commands.
By default, RedisDataCodec
is provided for simple types like String
, ByteString
, Array[Byte]
,
Boolean
, Char
, all primitive numeric types and NamedEnum
s
(which have NamedEnumCompanion
).
Also, all types which have an instance of GenCodec
automatically have an instance of RedisDataCodec.
Base trait for Redis clients with ability to execute RedisBatches.
Marker subtype of RedisExecutor which guarantees ability to execute Redis commands which contain keys.
Redis client implementation for a single Redis node using a connection pool.
Redis client implementation for a single Redis node using a connection pool. Connection pool size is constant and batches and operations are distributed over connections using round-robin scheme. Connections are automatically reconnected upon failure (possibly with an appropriate delay, see NodeConfig for details).
Marker subtype of RedisExecutor which guarantees ability to execute commands which do NOT access or change state of a single Redis connection (e.g.
Marker subtype of RedisExecutor which guarantees ability to execute commands which do NOT access or change
state of a single Redis connection (e.g. CLIENT SETNAME
).
Represents a sequence of Redis operations executed using a single Redis connection.
Represents a sequence of Redis operations executed using a single Redis connection.
Any operation may depend on the result of some previous operation (therefore, flatMap
is available).
RedisOp is guaranteed to be executed fully and exclusively on a single Redis connection
(no other concurrent commands can be executed on that connection during execution of RedisOp).
Because of that, RedisOps may execute WATCH
and UNWATCH
commands.
In fact, the primary purpose of RedisOp is to allow execution of Redis transactions with optimistic locking. For this purpose, RedisOp may be created by flat-mapping RedisBatches.
For example, below is an implementation of Redis transaction which fetches a value of some key (as Int
)
multiplies it by 3 and saves it back to Redis. During this operation, the key being modified is watched so that
saving fails with OptimisticLockException
if some other client concurrently modifies that key.
val api = RedisApi.Batches.StringTyped.valueType[Int] import api._ val transactionOp: RedisOp[Unit] = for { // we're sending WATCH and GET commands in a single batch value <- watch("number") *> get("number").map(_.getOrElse(1)) // SET command is wrapped in MULTI-EXEC block _ <- set("number", value * 3).transaction } yield ()
RedisOp can be passed for execution to RedisOpExecutor (implemented by e.g. RedisNodeClient).
Base trait for Redis clients with ability to execute RedisOps.
Something that translates incoming RedisMsg messages and emits a single RedisReply.
Something that translates incoming RedisMsg
messages and emits a single RedisReply.
For example, it may handle transactions by extracting actual responses for every command from
the EXEC
response and returning them in a TransactionReply
(see Transaction).
Typeclass for easy merging ("sequencing") of multiple RedisBatch instances into one.
Typeclass for easy merging ("sequencing") of multiple RedisBatch instances into one. This is done in order to guarantee that some set of operations is sent to Redis as a single batch (most likely single network message).
The parameter Ops
represents batches that will be sequenced into one. It may be a collection, a tuple or
any other "collection-like" type for which type class instance is provided.
Res
is the type of result of the batch created by "sequencing". This type is automatically inferred from
the Ops
type. For example, if Ops
is (RedisBatch[Int], RedisBatch[String])
(tuple) then Res
will be
(Int, String)
. If Ops
is List[RedisBatch[Int]]
then Res
will be List[Int]
.
Nesting is also possible. For example, if Ops
is (List[RedisBatch[Int]], RedisBatch[String])
then
Res
will be (List[Int], String)
.
In order to perform "sequencing", simply call sequence on your collection of batches, e.g.
import RedisApi.Batches.StringTyped._ val tupleBatch: RedisBatch[(Long, Opt[String])] = (incr("key1"), get("key2")).sequence val listBatch: RedisBatch[List[Long]] = List("key1", "key2").map(key => incr(key)).sequence
Implementation of key hashing function used in Redis Cluster, as specified in Redis Cluster Specification
Object which contains implementations of various variants of Redis API that this driver provides.
Object which contains implementations of various variants of Redis API that this driver provides.
Each variant implements a set of methods corresponding directly to Redis commands, e.g.
get method represents Redis GET
command.
API variants may differ from each other in several independent aspects:
The most important one is the result type returned by every method corresponding to a Redis command:
Future
s.Async
counterparts but execution is blocking and results are returned as unwrapped values.Async
and Blocking
API variants additionally come in three different "levels", each one exposing different
subset of Redis commands. This reflects the fact that not every RedisExecutor (client implementation) supports
every command (e.g. you can't execute unkeyed commands using RedisClusterClient).
Every API variant may also use different types to represent Redis keys, hash keys and values. You can define your own API variants for arbitrary combination of key, hash key and value types as long as there is an instance of RedisDataCodec for every of these types.
For example, if you keep only numeric values on a Redis Cluster installation, you might define an API variant like this one:
class NumericKeyedAsyncApi(executor: RedisKeyedExecutor, config: ExecutionConfig = ExecutionConfig.Default) extends RedisApi.Keyed.Async[String,String,Long](executor, config)
API variants which use only String
s (textual) or only ByteString
s (binary) are already implemented by the driver, e.g.
RedisApi.Keyed.Async.StringTyped, RedisApi.Batches.BinaryTyped.
Note that RedisDataCodec is automatically provided for many simple types and also all types which have a
GenCodec
. This effectively gives you a complete serialization
framework for keys, hash keys and values stored in Redis.
Note that chosen key, hash key and value types can be adjusted "on the fly" with a convenient syntax. For example, if you need to use some case class as a value type in a single, specific place, you can do it without defining a completely separate API variant. For example:
case class Person(name: String, birthYear: Int) object Person { implicit val codec: GenCodec[Person] = GenCodec.materialize[Person] } import scala.concurrent.duration._ implicit val system: ActorSystem = ActorSystem() val api = RedisApi.Keyed.Blocking.StringTyped(new RedisClusterClient) // normally, we're just using String-typed API api.set("key", "value") // but in one specific place, we might want to use Person as the value // Person has an instance of GenCodec, so it will be automatically serialized to binary format api.valueType[Person].set("binaryDataKey", Person("Fred", 1990))
Current cluster state known by RedisClusterClient.
mapping between slot ranges and node clients that serve them, sorted by slot ranges
direct mapping between master addresses and node clients
non-empty if there's actually only one, non-clustered Redis node - see fallbackToSingleNode