How I can make my custom data class as StatefulRedisConnection value type?
Asked Answered
D

1

7

Lettuce Core API has RedisClient class that contains these methods:

public StatefulRedisConnection<String, String> connect() {
      return this.connect(this.newStringStringCodec());
}

public <K, V> StatefulRedisConnection<K, V> connect(RedisCodec<K, V> codec) {
      this.checkForRedisURI();
      return (StatefulRedisConnection)this.getConnection(this.connectStandaloneAsync(codec, this.redisURI, this.timeout));
}

I want to call method connect(RedisCodec<K, V> codec), but I don't know how to config my codec object that I should pass as a parameter to this method.

My current code:

val redisClient = RedisClient.create("redis://password@localhost:6379/0");
val connection = redisClient.connect();
// in this case type of connection is StatefulRedisConnection<String, String>
val redisCommands = connection.sync()

I also has my custom data class.

data class MyCustomDataClassName {
  val id: UUID,
  val something: String,
  val foo: String,
  val bar: String
}

I want to write this code:

val redisClient = RedisClient.create("redis://password@localhost:6379/0");
val codec = /* should be something that returns object of type StatefulRedisConnection<String, MyCustomDataClassName>*/
val connection = redisClient.connect(codec);
val redisCommands = connection.sync()
Devoirs answered 5/11, 2019 at 9:10 Comment(0)
P
0

This is an excerpt of Kotlin with Lettuce + Redis. I tested this with the framework Ktor.

  1. Operating directly with custom classes requires setting up a serializer in combination with RedisCodec.
  2. Please note the custom ModelCodec being passed to the connection.
  3. This is a very specific example, you might keep it more generic or add mutliple RedisCodecs for other types as well.
@Serializable
data class MyCustomDataClassName(
    val id: UUID,
    val something: String,
    val foo: String,
    val bar: String
)

object RedisCache {  

    private val client: RedisClient
    private val connection: StatefulRedisConnection<String, MyCustomDataClassName>
    private val commands: RedisCommands<String, MyCustomDataClassName>

    val redisKey = "key:1"

    init {
        val redisUri = RedisURI.Builder.redis("localhost", 6379).build()
        client = RedisClient.create(redisUri)
        connection = client.connect(ModelCodec())
        commands = connection.sync()
        // Established connection to Redis
    }

    fun set(key: String, value: MyCustomDataClassName) {
        val result = commands.set(key, value)
    }

    fun get(key: String): MyCustomDataClassName {
        return commands.get(key)
    }

}


internal class ModelCodec : RedisCodec<String, MyCustomDataClassName> {
   private val charset: Charset = Charset.forName("UTF-8")

   override fun decodeKey(bytes: ByteBuffer): String {
       return charset.decode(bytes).toString()
   }

   override fun decodeValue(bytes: ByteBuffer): MyCustomDataClassName? {
       try {
           val jsonString = charset.decode(bytes).toString()
           return Json.decodeFromString(jsonString)
       } catch (e: Exception) {
           return null
       }
   }

   override fun encodeKey(key: String): ByteBuffer {
       return charset.encode(key)
   }

   override fun encodeValue(value: MyCustomDataClassName): ByteBuffer? {
       try {

           val jsonString = Json.encodeToString(MyCustomDataClassName.serializer(), value)
           return ByteBuffer.wrap(jsonString.toByteArray(charset))
       } catch (e: IOException) {
           e.printStackTrace()
           return null
       }
   }
}

Piranesi answered 26/2 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.