All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.laserdisc.mysql.binlog.compaction.package.scala Maven / Gradle / Ivy

package io.laserdisc.mysql.binlog

import cats.data.Kleisli
import cats.implicits._
import io.circe.Json
import io.laserdisc.mysql.binlog.event.EventMessage
import io.laserdisc.mysql.json

import scala.collection.mutable

package object compaction {
  def compact(transaction: Seq[EventMessage]): Seq[EventMessage] =
    transaction
      .foldLeft(mutable.LinkedHashMap.empty[String, EventMessage]) { case (acc, evt) =>
        val emId = calcIdentity(evt)
        acc
          .get(emId)
          .fold(acc.put(emId, evt)) { latest =>
            mkNewEvent(evt)
              .andThen(finalizeNewEvent)
              .run(latest) match {
              case Some(ne) =>
                acc.remove(emId);
                acc.put(emId, ne)
              case None => acc.remove(emId)
            }
          }
        acc
      }
      .values
      .toSeq

  def mkNewEvent(current: EventMessage): Kleisli[Option, EventMessage, EventMessage] =
    Kleisli(latest =>
      latest.row.hcursor
        .downField("after")
        .set(current.row.hcursor.downField("after").focus.getOrElse(Json.Null))
        .top
        .map(newJson =>
          latest
            .copy(
              timestamp = current.timestamp,
              fileName = current.fileName,
              offset = current.offset,
              row = newJson
            )
        )
    )

  val finalizeNewEvent: Kleisli[Option, EventMessage, EventMessage] = Kleisli(value =>
    (value.row.hcursor.downField("before").focus, value.row.hcursor.downField("after").focus)
      .mapN[Option[EventMessage]] {
        case (Json.Null, Json.Null) => None
        case (Json.Null, _)         => Some(value.copy(action = "create"))
        case (_, Json.Null)         => Some(value.copy(action = "delete"))
        case (_, _)                 => Some(value.copy(action = "update"))
      }
      .flatten
  )

  def calcIdentity(em: EventMessage): String =
    (em.table +: json.flatSort(em.pk)).mkString("|")
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy