Safe persistenceId encoder for complex primary key

51 Views Asked by At

What is the best way to generate persistenceId from complex key (String, String) and every part of this key is not controlled (may contain any symbol)?

  1. If decoding is required
  2. If decoding is not required (original key stored in actor)
1

There are 1 best solutions below

5
On

One possibility is to encode the length of the first string of the key as the first characters of the persistenceId. An example in Scala:

import scala.util.Try

type ComplexKey = (String, String)

def persistenceIdFor(key: ComplexKey): String = {
  val (first, second) = key
  val firstLen = first.length
  s"${firstLen};${first},${second}"
}

val PersistenceIdRegex = """^(\d+);(.*)$""".r

// You might not necessarily ever need to get a key for a given persistenceId, but to show the above is invertible
def keyForPersistenceId(persistenceId: String): Option[ComplexKey] =
  persistenceId match {
    case PersistenceIdRegex(firstLenStr, content) =>
      val firstLenTry = Try(firstLenStr.toInt)

      firstLenTry
        .filter(_ <= content.length)
        .toOption
        .map(firstLen => content.splitAt(firstLen))

    case _ => None
  }

Another would be to use escaping, but that can have a lot of subtleties, despite its initially apparent simplicity.

The specific Akka Persistence backend in use may enforce restrictions on the persistenceId (e.g. length of IDs).