Redis
Using Redis as an output adapter in a hexagonal architecture means that Redis will handle data storage and retrieval for your application's domain entities. Redis, being an in-memory data structure store, is ideal for use cases requiring fast read and write operations, such as caching, session storage, and real-time analytics.
Role of Redis as an Output Adapter
-
Interfacing with Redis:
- The adapter manages interactions with the Redis data store, including setting and getting data.
-
Data Translation:
- It translates domain objects into data models suitable for Redis storage and vice versa.
-
Decoupling:
- It decouples the core application logic from Redis-specific implementation details, ensuring flexibility and maintainability.
Benefits of Using Redis as an Output Adapter
- Speed: Redis provides very fast read and write operations due to its in-memory nature, making it ideal for applications requiring high performance.
- Flexibility: Redis supports various data structures (strings, hashes, lists, sets, etc.), allowing for flexible storage solutions.
- Scalability: Redis can handle a large number of operations and can be scaled horizontally by using sharding or clustering.
- Decoupling: The core application remains decoupled from Redis-specific details, ensuring flexibility and maintainability.
Spec definition
The spec definition can be set via $.spec.adapters.output.redis. An example of it could be:
Output adapter Redis sample
- The
ttl
attribute let you configure the entity object Time To Live value into Redis cache. This is set inmilliseconds
.
Optional metadata
The metadata configuration is optional and if it has not been set defaults values will be used by Torpedo. For the TTL the default value is zero which means that object live forever or till a delete operation happens.
Torpedo Query Language
This adapter doesn't support TQL query
Redis Repository Implementation
The Redis repository has been implemented on top of the library github.com/go-redis/redis.
This adapter will provide 2 repository classes that implements the output repository port interface and would look like:
classDiagram
class RedisRepository
class redisRepositoryBase
interface IRepository
interface IRepositoryBase
IRepositoryBase <|-- IRepository
IRepositoryBase <|.. redisRepositoryBase
IRepository <|.. RedisRepository
redisRepositoryBase <|-- RedisRepository
redisRepositoryBase : redis.client data
redisRepositoryBase : []byte cryptoKey
redisRepositoryBase: +Save(entity) error
redisRepositoryBase: +FetchByID(id) (Entity, error)
redisRepositoryBase: +Update(entity) error
redisRepositoryBase: +DeleteByID(id) error
Redis client
As a developer the Redis client can be accessed directly from the RedisRepository
due to has an aggregation with redisRepositoryBase
.
Data Mapper Object (DMO)
DMOs are the selected objects to map entity data into a secondary adapter or storage adapter. This objects are responsible to encrypt or decrypt field values at save/update or fetch operations. Each time that a repository is created the encryption key must be provided.
AES key
The key argument should be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
Provider
The Redis repository has been tested with Go Redis lib
Each entity needs to create their own repository instance and this happens into the entity dependency
provider.
Before to bind
a Redis instance as part of your entity provider, a *redis.Client
provider must be created.
Repository provider
dependency/redis.go | RedisProvider
Entity provider
Following the example of the section Extending Entity with custom fields
we will need to bind a redis
repository to the entity service like the example below:
dependency/sensor.go | SensorProvider
- The redis instance is bound to the default instance provided by RedisProvider