### Configure Standalone Redis Instance Source: https://github.com/karelcemus/play-redis/wiki/Configuration Sets up a single Redis instance for the play-redis cache. It specifies the host, port, optional database number, and password for authentication. ```HOCON play.cache.redis { host: localhost # redis server: port port: 6379 # redis server: database number (optional) database: 0 # authentication password (optional) password: null } ``` -------------------------------- ### Add play-redis Dependency Source: https://github.com/karelcemus/play-redis/blob/master/doc/10-integration.md Add the play-redis library to your project's build.sbt file. This includes enabling the Play cache API and specifying the play-redis library with its version. ```sbt // enable Play cache API (based on your Play version) libraryDependencies += play.sbt.PlayImport.cacheApi // include play-redis library libraryDependencies += "com.github.karelcemus" %% "play-redis" % "5.4.0" ``` -------------------------------- ### Configure Redis Connection String Mode Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Enables connection-string mode for Play Redis, allowing configuration via an environmental variable like REDIS_URL. This simplifies setup in dynamic environments such as Heroku. ```HOCON play.cache.redis { # enable connection-string mode, i.e., a standalone # configured through a connection string source: "connection-string" # HOCOON automatically injects the environmental variable # and the module parses the string. connection-string: "${REDIS_URL}" } ``` -------------------------------- ### Play-Redis Configuration Changes Source: https://github.com/karelcemus/play-redis/blob/master/doc/40-migration.md Details key configuration property renames and redesigns introduced in Play-Redis versions, affecting how Redis instances and their settings are defined. ```APIDOC Configuration Property Renames and Redesigns: - **Invocation Policy**: Changed from an implicit parameter in 2.0.x to a static configurable property in 2.1.x. Refer to documentation for details on eager and lazy invocation. - **Named Caches Annotation**: Updated from `@Named` in 2.0.x to `@NamedCache` in 2.1.0 for consistency with Play framework conventions. Deprecations will be removed in 2.2.0. - **Timeout Property**: Renamed from `timeout` to `sync-timeout` in 2.1.0 to avoid ambiguity. A new `redis-timeout` property was introduced. The original `timeout` property is deprecated and will be removed in 2.2.0. - **Default Database**: Changed from 1 to 0 (Redis default) in 2.0.x to align with Redis defaults. - **Named Caches Support**: Introduced `instances` property in 2.0.x to support named caches. The cache instance defined directly under `play.cache.redis` is the default instance. - **Source Property Redesign**: Renamed and redesigned from `configuration` to `source` in 2.0.x. Valid values are now `standalone`, `cluster`, `connection-string`, and `custom`. - **Connection String Property**: `connection-string-variable` was replaced by `connection-string` in 2.0.x, allowing direct value passing via HOCON variables (e.g., `${REDIS_URL}`). This applies when `source: connection-string`. - **Wait Property Rename**: Renamed to `timeout` in 2.0.x. - **Default Configuration Scope**: `source`, `timeout`, `dispatcher`, and `recovery` define defaults and can be overridden locally within each named cache configuration. - **Bind Default Property**: Introduced `bind-default` (default `true`) to control binding the default instance to unqualified APIs. - **Default Cache Property**: Introduced `default-cache` (default `play`) to define the name of the default instance. ``` -------------------------------- ### Play-Redis Runtime DI (Guice) Changes Source: https://github.com/karelcemus/play-redis/blob/master/doc/40-migration.md Describes changes in the RedisCacheModule for Runtime Dependency Injection (Guice), noting internal component registration adjustments. ```APIDOC Runtime DI (Guice) Changes: - **`RedisCacheModule` Redesign**: Major redesign of `RedisCacheModule` in 2.0.x. No changes in usage are expected for users. - **Internal Component Registration**: Internal components are no longer registered into the DI container. ``` -------------------------------- ### Compile-time DI with RedisCacheComponents Source: https://github.com/karelcemus/play-redis/blob/master/doc/10-integration.md Demonstrates how to use `play.api.cache.redis.RedisCacheComponents` for compile-time dependency injection. It shows how to obtain a `RedisCaches` instance for a specific cache name and access its asynchronous API. ```scala // 'play' is the name of the named cache // (play is default name of the default cache) // // the 'play' literal is implicitly converted into // the instance but has to be configured in 'application.conf' val playCache: RedisCaches = cacheApi( "play" ) // expose `play.api.cache.redis.CacheAsyncApi` val asynchronousRedis = playCache.async ``` -------------------------------- ### Configure Standalone Redis (HOCON) Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Sets up a connection to a single Redis instance. Specifies host, port, and database number. Authentication via username and password is also supported. ```hocon play.cache.redis { host: localhost # redis server: port port: 6379 # redis server: database number (optional) database: 0 # authentication username (optional) with "redis" as fallback username: null # authentication password (optional) password: null } ``` -------------------------------- ### Compile-time DI API Usage Source: https://github.com/karelcemus/play-redis/wiki/Migration-Guide Details on how to create new API instances using `cacheApi` with compile-time DI in play-redis. It covers providing instance names or custom configurations and managing multiple APIs. ```APIDOC Compile-time DI API Usage: To create new API instances, call `cacheApi(instance)`. Parameters for `cacheApi`: - `instance`: Can be a String representing the instance name or a `RedisInstance` object for custom configuration. Returns: A `RedisCaches` object encapsulating all available APIs for the specified instance. Recommendations: - Reuse the `RedisCaches` object when using multiple different APIs to prevent duplicate instance creation. - For custom instance configuration: - Override `redisInstanceResolver` to map names to `RedisInstance` objects. - Pass the `RedisInstance` object directly to the `cacheApi` call. - For custom recovery policy, override `recoveryPolicyResolver`. ``` -------------------------------- ### Play Redis Configuration: Source Options Source: https://github.com/karelcemus/play-redis/wiki/Configuration Details the available options for the `play.cache.redis.source` configuration key, which determines how the Redis instance is resolved. Options include `standalone`, `cluster`, `connection-string`, and `custom`. ```APIDOC play.cache.redis.source: Type: String Default: `standalone` Description: Specifies the Redis instance source. Accepted values are `standalone`, `cluster`, `connection-string`, and `custom`. - `standalone`: Uses default standalone configuration. - `cluster`: Uses default cluster configuration. - `connection-string`: Configures Redis using a connection string (e.g., `${REDIS_URL}`). - `custom`: Requires a custom `RedisInstanceResolver` to be provided via DI. ``` -------------------------------- ### Enable Redis Cache Module (Runtime DI) Source: https://github.com/karelcemus/play-redis/blob/master/doc/10-integration.md Configure application.conf to enable the redis cache module for runtime dependency injection. This binds all necessary components for Redis caching. ```hocon # enable redis cache module play.modules.enabled += "play.api.cache.redis.RedisCacheModule" ``` -------------------------------- ### Custom Recovery Policy Implementation in Scala Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Provides an example of extending the `RecoveryPolicy` trait to create a custom error handling strategy. The `recoverFrom` method can be overridden to define specific behavior, such as returning a default value or re-running a failed command. ```scala import play.api.cache.redis.RecoveryPolicy import scala.concurrent.Future class MyPolicy extends RecoveryPolicy { def recoverFrom[ T ]( rerun: => Future[ T ], default: => Future[ T ], failure: RedisException ) = default } ``` -------------------------------- ### Basic Cache Operations (Set, Get, Remove) Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Demonstrates fundamental cache operations for setting, retrieving, and removing single key-value pairs. Supports various data types and custom case classes. Retrieving a non-existent key returns None. ```scala import play.api.cache.redis.CacheApi // Assuming 'cache' is an instance of CacheApi // Set a String value cache.set( "key", "value" ) // Get a String value (returns Option[String]) val stringValue: Option[String] = cache.get[String]( "key" ) // Remove a key cache.remove( "key" ) // Set a custom case class value case class MyCaseClass(id: Int, name: String) cache.set( "object", MyCaseClass(1, "test") ) // Get a custom case class value (returns Option[MyCaseClass]) val objectValue: Option[MyCaseClass] = cache.get[MyCaseClass]( "object" ) // Set a Double value cache.set( "key", 1.23 ) // Get a Double value (returns Option[Double]) val doubleValue: Option[Double] = cache.get[Double]( "key" ) ``` -------------------------------- ### Play-Redis API Changes Source: https://github.com/karelcemus/play-redis/blob/master/doc/40-migration.md Details modifications to the Play-Redis API, including removal of deprecated interfaces and updates to expiration computation helpers. ```APIDOC API Modifications: - **Deprecated Interface Removal**: Implementation of deprecated `play.cache.CacheApi` and `play.api.cache.CacheApi` removed. - **`RecoveryPolicy` Location**: Moved from `play.api.cache.redis.impl` to `play.api.cache.redis`. - **Expiration Computation Implicits**: Joda-time implicit helpers for expiration computation in `ExpirationImplicits` deprecated due to Play 2.6 deprecating Joda-time. Implicits for `java.time.LocalDateTime` introduced as replacements. ``` -------------------------------- ### Play Redis Configuration: Module Wide Settings Source: https://github.com/karelcemus/play-redis/wiki/Configuration Defines module-wide settings for the Play Redis cache, including whether to bind default unqualified APIs and the name of the default cache. ```APIDOC play.cache.redis.bind-default: Type: Boolean Default: `true` Description: Whether to bind default unqualified APIs. Applies only with runtime DI. play.cache.redis.default-cache: Type: String Default: `play` Description: Named of the default cache, applies with `bind-default`. ``` -------------------------------- ### Redis Cache Configuration Properties Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Configuration keys for the Redis cache, covering source, timeouts, prefix, dispatcher, and recovery policy. These settings allow for fine-tuning the Redis integration within the application. ```APIDOC play.cache.redis.source: Type: String Default: "standalone" Description: Defines the source of the configuration. Accepted values are `standalone`, `cluster`, `connection-string`, `master-slaves` and `custom`. play.cache.redis.sync-timeout: Type: Duration Default: "1s" Description: Conversion timeout applied by `SyncAPI` to convert `Future[T]` to `T`. play.cache.redis.redis-timeout: Type: Duration Default: null Description: Waiting for the response from the Redis server. play.cache.redis.prefix: Type: String Default: null Description: Optional namespace, i.e., key prefix. play.cache.redis.dispatcher: Type: String Default: "pekko.actor.default-dispatcher" Description: Pekko actor dispatcher to use for Redis operations. play.cache.redis.recovery: Type: String Default: "log-and-default" Description: Defines behavior when command execution fails. For accepted values and more see [recovery-policy](#recovery-policy). ``` -------------------------------- ### Namespace Prefix Configuration Source: https://github.com/karelcemus/play-redis/wiki/Configuration Applies a namespace prefix to all keys within a specific cache instance. This helps prevent key collisions when multiple caches share the same Redis database. ```HOCON play.cache.redis { # ... other configurations ... instances { myNamedCache { # ... other configurations ... prefix: "my-prefix" } } } ``` -------------------------------- ### Define Named Redis Caches Source: https://github.com/karelcemus/play-redis/wiki/Configuration Configures multiple named Redis cache instances, allowing for different configurations or connections. The default cache can be managed via `bind-default` and `default-cache` properties. ```HOCON play.cache.redis { # source property; standalone is default source: standalone instances { play { # source property fallbacks to the value under play.cache.redis host: localhost port: 6379 } myNamedCache { source: cluster cluster: [ { host: localhost, port: 6380 } ] } } } ``` -------------------------------- ### Play Redis Timeout Configuration Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Details the various timeout settings available for Play Redis. This includes synchronization timeout for SyncAPI, Redis command timeout, and connection timeout for establishing connections. ```APIDOC play.cache.redis.sync-timeout - Description: Timeout for converting internal Futures to T when using SyncAPI. Applies to Redis communication, serialization, and orElse logic. - Type: scala.concurrent.duration.Duration - Default: Not specified (requires definition for SyncAPI) - Notes: Set to a high value or use AsyncAPI to avoid timeouts. play.cache.redis.redis-timeout - Description: Limits waiting time for a response from the Redis server. Expected to be smooth, so disabled by default. - Type: scala.concurrent.duration.Duration - Default: Disabled - Notes: Can be enabled if Redis response times are a concern. play.cache.redis.connection-timeout - Description: Limits waiting time for a response when a connection is not established. Prevents requests from hanging during connection attempts. - Type: scala.concurrent.duration.Duration - Default: 500 millis - Notes: Optional, can be disabled. Ensures cache operations resolve or reject within a defined window. ``` -------------------------------- ### Registering Custom Recovery Policy with Guice Source: https://github.com/karelcemus/play-redis/wiki/Configuration Shows how to bind a custom `RecoveryPolicy` implementation to a specific name using Guice for runtime dependency injection. The named policy must match the configuration key. ```scala import play.api.cache.redis.RecoveryPolicy import play.api.inject._ import play.api.{Configuration, Environment} class ApplicationModule extends Module { def bindings( environment: Environment, configuration: Configuration ) = Seq( // "custom" is the name in the configuration file bind[ RecoveryPolicy ].qualifiedWith( "custom" ).to( classOf[ MyPolicy ] ) ) } ``` -------------------------------- ### Configure Redis Cluster (HOCON) Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Enables cluster mode for connecting to a Redis cluster. Requires defining the cluster nodes with their host, port, and optional authentication credentials. ```hocon play.cache.redis { # enable cluster mode source: cluster # nodes are defined as a sequence of objects: cluster: [ { # required string, defining a host the node is running on host: localhost # required integer, defining a port the node is running on port: 6379 # optional string, defines a username to use with "redis" as fallback username: null # optional string, defines a password to use password: null } ] } ``` -------------------------------- ### Configure Master-Slaves Redis (HOCON) Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Sets up a master-slave replication configuration. Defines a single master node and a list of slave nodes, including optional database, username, and password for each. ```hocon play.cache.redis { source: master-slaves # username to your redis hosts (optional) username: some-username # password to your redis hosts, use if not specified for a specific node (optional) password: "my-password" # number of your redis database, use if not specified for a specific node (optional) database: 1 # master node master: { host: "localhost" port: 6380 # number of your redis database on master (optional) database: 1 # username on master host (optional) username: some-username # password on master host (optional) password: something } # slave nodes slaves: [ { host: "localhost" port: 6381 # number of your redis database on slave (optional) database: 1 # username on slave host (optional) username: some-username # password on slave host (optional) password: something } ] } ``` -------------------------------- ### Play Redis Configuration: Recovery Policy Source: https://github.com/karelcemus/play-redis/wiki/Configuration Configuration snippet to specify a custom recovery policy by name. The name 'custom' should match the qualified name used in DI bindings. ```conf play.cache.redis.recovery: custom ``` -------------------------------- ### Configure Redis Cluster Mode Source: https://github.com/karelcemus/play-redis/wiki/Configuration Enables and configures play-redis to connect to a Redis cluster. It requires setting the `source` to `cluster` and defining the cluster nodes with their host and port. ```HOCON play.cache.redis { # enable cluster mode source: cluster # nodes are defined as a sequence of objects: cluster: [ { # required string, defining a host the node is running on host: localhost # required integer, defining a port the node is running on port: 6379 # optional string, defines a password to use password: null } ] } ``` -------------------------------- ### Play Redis Configuration: Connection String Mode Source: https://github.com/karelcemus/play-redis/wiki/Configuration Configures the Play Redis module to use a connection string, typically sourced from an environment variable like REDIS_URL. This is useful for dynamic environments such as Heroku. ```conf play.cache.redis { # enable connection-string mode, i.e., a standalone # configured through a connection string source: connection-string # HOCOON automatically injects the environmental variable # and the module parses the string. connection-string: "${REDIS_URL}" } ``` -------------------------------- ### Configure Redis Sentinel Mode (HOCON) Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Enables Sentinel mode for high availability. Requires specifying the master group name and a list of Sentinel nodes with their host and port. ```hocon play.cache.redis { source: sentinel # master name that you specify when using the `sentinel # get-master-addr-by-name NAME` command master-group: r0 # Number of your redis database (optional) database: 1 # Username to your redis hosts (optional) userame: some-username # Password to your redis hosts (optional) password: something # List of sentinels sentinels: [ { host: localhost port: 16380 }, { host: localhost port: 16381 }, { host: localhost port: 16382 } ] } ``` -------------------------------- ### Guice Module for Custom Recovery Policy Binding Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Demonstrates how to bind a custom `RecoveryPolicy` implementation to a specific name (e.g., 'custom') within a Guice module for runtime dependency injection. This allows the custom policy to be referenced in the Play configuration. ```scala import play.api.cache.redis.RecoveryPolicy import play.api.inject._ import play.api.{Configuration, Environment} class ApplicationModule extends Module { def bindings( environment: Environment, configuration: Configuration ) = Seq( // "custom" is the name in the configuration file bind[ RecoveryPolicy ].qualifiedWith( "custom" ).to( classOf[ MyPolicy ] ) ) } ``` -------------------------------- ### Redis Set Operations in Play Scala Source: https://github.com/karelcemus/play-redis/wiki/How-to-Use Demonstrates common operations on Redis Sets using the Play Redis cache API. Includes adding elements, checking for existence, retrieving the entire set, and getting the size of the set. ```scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi class MyController @Inject() ( cache: CacheApi ) { // enables Set operations // Scala wrapper over the set at this key cache.set[ String ]( "my-set" ) // get the whole set cache.set[ String ]( "my-set" ).toSet // add values into the set cache.set[ String ]( "my-set" ).add( "ABC", "EDF" ) // test existence in the set cache.set[ String ]( "my-set" ).contains( "ABC" ) // size of the set cache.set[ String ]( "my-set" ).size cache.set[ String ]( "my-set" ).isEmpty cache.set[ String ]( "my-set" ).nonEmpty // remove the value cache.set[ String ]( "my-set" ).remove( "ABC" ) } ``` -------------------------------- ### Redis List Operations in Play Scala Source: https://github.com/karelcemus/play-redis/wiki/How-to-Use Demonstrates various operations on Redis Lists using the Play Redis cache API. Includes prepending, appending, getting elements by index or head/last, setting values, removing elements by value or index, and viewing/modifying the list. ```scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi class MyController @Inject() ( cache: CacheApi ) { // enables List operations // Scala wrapper over the list at this key cache.list[ String ]( "my-list" ) // get the whole list cache.list[ String ]( "my-list" ).toList // prepend values, beware, values are prepended in the reversed order! // result List( "EFG", "ABC" ) cache.list[ String ]( "my-list" ).prepend( "ABC" ).prepend( "EFG" ) "EFG" +: "ABC" +: cache.list[ String ]( "my-list" ) List( "ABC", "EFG" ) ++: cache.list[ String ]( "my-list" ) // append values to the list // result List( "ABC", "EFG" ) cache.list[ String ]( "my-list" ).append( "ABC" ).append( "EFG" ) cache.list[ String ]( "my-list" ) :+ "ABC" :+ "EFG" cache.list[ String ]( "my-list" ) :++ List( "ABC", "EFG" ) // getting a value cache.list[ String ]( "my-list" ).apply( index = 1 ) // get or an exception cache.list[ String ]( "my-list" ).get( index = 1 ) // Some or None cache.list[ String ]( "my-list" ).head // get or an exception cache.list[ String ]( "my-list" ).headOption // Some or None cache.list[ String ]( "my-list" ).headPop // Some or None and REMOVE the head cache.list[ String ]( "my-list" ).last // get or an exception cache.list[ String ]( "my-list" ).lastOption // Some or None // size of the list cache.list[ String ]( "my-list" ).size // overwrite the value at index cache.list[ String ]( "my-list" ).set( position = 1, element = "HIJ" ) // remove the value cache.list[ String ]( "my-list" ).remove( "ABC", count = 2 ) // remove by value cache.list[ String ]( "my-list" ).removeAt( position = 1 ) // remove by index // returns an API to reading but not modifying the list cache.list[ String ]( "my-list" ).view // returns an API to modify the underlying list cache.list[ String ]( "my-list" ).modify } ``` -------------------------------- ### Inject Named Cache in Scala Controller Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Demonstrates how to inject a specific named cache instance into a Scala controller using the @NamedCache annotation. This allows for easy access to different cache configurations within the application. ```Scala import play.api.cache.NamedCache import play.api.cache.CacheAsyncApi import javax.inject.Inject class MyController @Inject()( @NamedCache( "myNamedCache" ) local: CacheAsyncApi ) { // my implementation } ``` -------------------------------- ### Custom Recovery Policy Implementation (Scala) Source: https://github.com/karelcemus/play-redis/wiki/Configuration Demonstrates how to create a custom recovery policy by extending the `RecoveryPolicy` trait. This policy defines the behavior when a cache request fails, allowing for custom error handling or fallback logic. ```scala import play.api.cache.redis.RecoveryPolicy import scala.concurrent.Future class MyPolicy extends RecoveryPolicy { def recoverFrom[ T ]( rerun: => Future[ T ], default: => Future[ T ], failure: RedisException ) = default } ``` -------------------------------- ### Configure Play Redis Thread Pools Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Configures the thread pool sizes for the underlying Lettuce Redis client. These settings control the number of threads used for I/O operations and computation tasks. ```HOCON play.cache.redis { io-thread-pool-size: 8 // default 8, min 3 computation-thread-pool-size: 8 // default 8, min 3 } ``` -------------------------------- ### Redis Map Operations in Play Scala Source: https://github.com/karelcemus/play-redis/wiki/How-to-Use Demonstrates common operations on Redis Maps (Hashes) using the Play Redis cache API. Includes adding key-value pairs, retrieving values by key, checking for key existence, getting the entire map, and managing map size. ```scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi class MyController @Inject() ( cache: CacheApi ) { // enables Set operations // Scala wrapper over the map at this key cache.map[ Int ]( "my-map" ) // get the whole map cache.map[ Int ]( "my-map" ).toMap cache.map[ Int ]( "my-map" ).keySet cache.map[ Int ]( "my-map" ).values // test existence in the map cache.map[ Int ]( "my-map" ).contains( "ABC" ) // get single value cache.map[ Int ]( "my-map" ).get( "ABC" ) // add values into the map cache.map[ Int ]( "my-map" ).add( "ABC", 5 ) // size of the map cache.map[ Int ]( "my-map" ).size cache.map[ Int ]( "my-map" ).isEmpty cache.map[ Int ]( "my-map" ).nonEmpty // remove the value cache.map[ Int ]( "my-map" ).remove( "ABC" ) } ``` -------------------------------- ### HOCON Configuration for Recovery Policies Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Defines the global recovery policy for Redis cache failures. Options include 'log-and-fail', 'log-and-default', and custom implementations, controlling how errors are handled and whether the application continues with a neutral value or an exception. ```hocon recovery: log-and-default ``` -------------------------------- ### Configure Play Redis Named Caches Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Defines named cache instances for Play Redis, specifying connection details for standalone or cluster modes. Configuration can be inherited from the root 'play.cache.redis' node or overridden locally for each instance. ```HOCON play.cache.redis { # source property; standalone is default source: standalone instances { play { # source property fallbacks to the value under play.cache.redis host: localhost port: 6379 } myNamedCache { source: cluster cluster: [ { host: localhost, port: 6380 } ] } } } ``` -------------------------------- ### Scala Redis List Operations Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Demonstrates Scala operations for Redis Lists using `play.api.cache.redis.CacheApi`. This API provides a Scala wrapper for list manipulation, including prepending, appending, retrieving elements by index, and removing elements. It offers methods for safe access (e.g., `get`, `headOption`) and destructive operations (e.g., `headPop`). ```scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi class MyController @Inject() ( cache: CacheApi ) { // enables List operations // Scala wrapper over the list at this key cache.list[ String ]( "my-list" ) // get the whole list cache.list[ String ]( "my-list" ).toList // prepend values, beware, values are prepended in the reversed order! // result List( "EFG", "ABC" ) cache.list[ String ]( "my-list" ).prepend( "ABC" ).prepend( "EFG" ) "EFG" +: "ABC" +: cache.list[ String ]( "my-list" ) List( "ABC", "EFG" ) ++: cache.list[ String ]( "my-list" ) // append values to the list // result List( "ABC", "EFG" ) cache.list[ String ]( "my-list" ).append( "ABC" ).append( "EFG" ) cache.list[ String ]( "my-list" ) :+ "ABC" :+ "EFG" cache.list[ String ]( "my-list" ) :++ List( "ABC", "EFG" ) // getting a value cache.list[ String ]( "my-list" ).apply( index = 1 ) // get or an exception cache.list[ String ]( "my-list" ).get( index = 1 ) // Some or None cache.list[ String ]( "my-list" ).head // get or an exception cache.list[ String ]( "my-list" ).headOption // Some or None cache.list[ String ]( "my-list" ).headPop // Some or None and REMOVE the head cache.list[ String ]( "my-list" ).last // get or an exception cache.list[ String ]( "my-list" ).lastOption // Some or None // size of the list cache.list[ String ]( "my-list" ).size // overwrite the value at index cache.list[ String ]( "my-list" ).set( position = 1, element = "HIJ" ) // remove the value cache.list[ String ]( "my-list" ).remove( "ABC", count = 2 ) // remove by value cache.list[ String ]( "my-list" ).removeAt( position = 1 ) // remove by index // returns an API to reading but not modifying the list cache.list[ String ]( "my-list" ).view // returns an API to modify the underlying list cache.list[ String ]( "my-list" ).modify } ``` -------------------------------- ### Compile-time DI with RedisCacheComponents (Scala) Source: https://github.com/karelcemus/play-redis/wiki/Integration-Guide Demonstrates how to use compile-time dependency injection by mixing `RedisCacheComponents` into a Play Framework application's components. It shows how to obtain a `RedisCaches` instance for a named cache and access its asynchronous API. ```scala // 'play' is the name of the named cache // (play is default name of the default cache) // // the 'play' literal is implicitly converted into // the instance but has to be configured in 'application.conf' val playCache: RedisCaches = cacheApi( "play" ) // expose `play.api.cache.redis.CacheAsyncApi` val asynchronousRedis = playCache.async ``` -------------------------------- ### Existence Check and Pattern Matching Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Checks for the presence of a key and retrieves keys matching a given pattern. `exists` returns a boolean indicating presence. `matching` uses the Redis KEYS command, which can be resource-intensive on large datasets. ```scala import play.api.cache.redis.CacheApi // Assuming 'cache' is an instance of CacheApi // Check if a key exists val keyExists: Boolean = cache.exists( "key" ) // Get all keys matching a pattern (uses KEYS command, O(n) complexity) val matchingKeys: Seq[String] = cache.matching( "page/1/*" ) ``` -------------------------------- ### Bulk Cache Operations (SetAll, GetAll) Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Enables setting multiple key-value pairs atomically and retrieving multiple values efficiently. `setAll` stores provided pairs, while `setAllIfNotExist` only stores pairs if all keys are absent. `getAll` retrieves values for specified keys. ```scala import play.api.cache.redis.CacheApi // Assuming 'cache' is an instance of CacheApi // Set multiple values at once cache.setAll( "key" -> 1.23, "key2" -> 5, "key3" -> 6 ) // Set values only if all keys do not exist cache.setAllIfNotExist( "key" -> 1.23, "key2" -> 5, "key3" -> 6 ) // Get multiple keys at once, returns a list of options corresponding to the keys val values: List[Option[Double]] = cache.getAll[Double]( "key", "key2", "key3", "key6" ) ``` -------------------------------- ### Play Redis Cache API Operations Source: https://github.com/karelcemus/play-redis/wiki/How-to-Use This Scala code snippet illustrates the comprehensive usage of the `CacheApi` for Redis caching. It covers setting and retrieving values with different types, removing keys, performing batch operations like `setAll` and `getAll`, using `getOrElse` and `getOrFuture` for default values, invalidating the cache, managing key expiration, checking key existence, and performing atomic increments and decrements. ```Scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi import org.joda.time.DateTime class MyController @Inject() ( cache: CacheApi ) { cache.set( "key", "value" ) // returns Option[ T ] where T stands for String in this example cache.get[ String ]( "key" ) cache.remove( "key" ) cache.set( "object", MyCaseClass() ) // returns Option[ T ] where T stands for MyCaseClass cache.get[ MyCaseClass ]( "object" ) // returns Unit cache.set( "key", 1.23 ) // returns Option[ Double ] cache.get[ Double ]( "key" ) // returns Option[ MyCaseClass ] cache.get[ MyCaseClass ]( "object" ) // set multiple values at once cache.setAll( "key" -> 1.23, "key2" -> 5, "key3" -> 6 ) // set only when all keys are unused cache.setAllIfNotExist( "key" -> 1.23, "key2" -> 5, "key3" -> 6 ) // get multiple keys at once, returns a list of options cache.getAll[ Double ]( "key", "key2", "key3", "key6" ) // returns T where T is Double. If the value is not in the cache // the computed result is saved cache.getOrElse( "key" )( 1.24 ) // same as getOrElse but works for Futures. It returns Future[ T ] cache.getOrFuture( "key" )( Future.successful( 1.24 ) ) // returns Unit and removes a key/keys from the storage cache.remove( "key" ) cache.remove( "key1", "key2" ) cache.remove( "key1", "key2", "key3" ) // remove all expects a sequence of keys, it performs same be behavior // as remove methods, they are just syntax sugar cache.removeAll( "key1", "key2", "key3" ) // removes all keys in the redis database! Beware using it cache.invalidate() // refreshes expiration of the key if present cache.expire( "key", 1.second ) // stores the value for infinite time if the key is not used // returns true when store performed successfully // returns false when some value was already defined cache.setIfNotExists( "key", 1.23 ) // stores the value for limited time if the key is not used // this is not atomic operation, redis does not provide direct support cache.setIfNotExists( "key", 1.23, 5.seconds ) // returns true if the key is in the storage, false otherwise cache.exists( "key" ) // returns all keys matching given pattern. Beware, complexity is O(n), // where n is the size of the database. It executes KEYS command. cache.matching( "page/1/*" ) // removes all keys matching given pattern. Beware, complexity is O(n), // where n is the size of the database. It internally uses method matching. // It executes KEYS and DEL commands in a transaction. cache.removeMatching( "page/1/*" ) // importing `play.api.cache.redis._` enables us // using both `java.util.Date` and `org.joda.time.DateTime` as expiration // dates instead of duration. These implicits are useful when // we know the data regularly changes, e.g., at midnight, at 3 AM, etc. // We do not have compute the duration ourselves, the library // can do it for us import play.api.cache.redis._ cache.set( "key", "value", DateTime.parse( "2015-12-01T00:00" ).asExpiration ) // atomically increments stored value by one // initializes with 0 if not exists cache.increment( "integer" ) // returns 1 cache.increment( "integer" ) // returns 2 cache.increment( "integer", 5 ) // returns 7 // atomically decrements stored value by one // initializes with 0 if not exists cache.decrement( "integer" ) // returns -1 cache.decrement( "integer" ) // returns -2 cache.decrement( "integer", 5 ) // returns -7 } ``` -------------------------------- ### Timeout Configuration for SyncAPI Source: https://github.com/karelcemus/play-redis/wiki/Configuration Defines the timeout for operations when using the synchronous API (`SyncAPI`). This timeout covers Redis communication, serialization, and `orElse` calls. For asynchronous operations, this timeout is not directly applied by the library. ```HOCON play.cache.redis { # ... other configurations ... timeout: "5s" # Example: 5 seconds } ``` -------------------------------- ### Enable Redis Cache Module (application.conf) Source: https://github.com/karelcemus/play-redis/wiki/Integration-Guide Configures the Play Framework application to use the Redis cache module by enabling `RedisCacheModule` in `application.conf`. This makes Redis components available through runtime dependency injection. ```conf # enable redis cache module play.modules.enabled += "play.api.cache.redis.RedisCacheModule" ``` -------------------------------- ### Configure AWS Cluster Redis (HOCON) Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Connects to Redis clusters managed by platforms like AWS that use a single DNS record resolving to multiple cluster nodes. The 'aws-cluster' source type is used. ```hocon play.cache.redis { instances { play { host: cluster.domain.name.com source: aws-cluster } } } ``` -------------------------------- ### Cache GetOrElse and GetOrFuture Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Provides methods to retrieve a value from the cache or compute and store it if it's not present. `getOrElse` uses a direct value computation, while `getOrFuture` handles asynchronous computation via Futures. ```scala import scala.concurrent.Future import play.api.cache.redis.CacheApi // Assuming 'cache' is an instance of CacheApi // Get value or compute and store if not present val value: Double = cache.getOrElse( "key" )( 1.24 ) // Get value or compute asynchronously and store if not present val futureValue: Future[Double] = cache.getOrFuture( "key" )( Future.successful( 1.24 ) ) ``` -------------------------------- ### HOCON Configuration for Invocation Policies Source: https://github.com/karelcemus/play-redis/blob/master/doc/20-configuration.md Configures the invocation policy for methods like `getOrElse`. It determines whether the cache operation waits for the side-effect (e.g., `set`) to complete ('lazy') or returns immediately, ignoring potential errors ('eager'). ```hocon invocation: lazy ``` -------------------------------- ### Scala Redis Set Operations Source: https://github.com/karelcemus/play-redis/blob/master/doc/30-how-to-use.md Illustrates Scala operations for Redis Sets using `play.api.cache.redis.CacheApi`. This API provides a Scala wrapper for set management, enabling adding elements, checking for membership, and removing elements. It also provides methods to retrieve the size and check the emptiness of a set. ```scala import scala.concurrent.Future import scala.concurrent.duration._ import play.api.cache.redis.CacheApi class MyController @Inject() ( cache: CacheApi ) { // enables Set operations // Scala wrapper over the set at this key cache.set[ String ]( "my-set" ) // get the whole set cache.set[ String ]( "my-set" ).toSet // add values into the set cache.set[ String ]( "my-set" ).add( "ABC", "EDF" ) // test existence in the set cache.set[ String ]( "my-set" ).contains( "ABC" ) // size of the set cache.set[ String ]( "my-set" ).size cache.set[ String ]( "my-set" ).isEmpty cache.set[ String ]( "my-set" ).nonEmpty // remove the value cache.set[ String ]( "my-set" ).remove( "ABC" ) } ```