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

endless.transaction.impl.logic.ShardedCoordinator.scala Maven / Gradle / Ivy

The newest version!
package endless.transaction.impl.logic

import cats.data.NonEmptyList
import cats.effect.kernel.Resource
import cats.syntax.applicative.*
import cats.syntax.applicativeError.*
import cats.syntax.flatMap.*
import cats.syntax.show.*
import cats.{MonadError, Show}
import endless.core.entity.Sharding
import endless.core.protocol.EntityIDCodec
import endless.transaction.impl.algebra.TransactionAlg
import endless.transaction.{Coordinator, Transaction}
import org.typelevel.log4cats.Logger

private[transaction] final class ShardedCoordinator[F[_]: Logger, TID, BID, Q, R](
    sharding: Sharding[F, TID, ({ type T[G[_]] = TransactionAlg[G, TID, BID, Q, R] })#T]
)(implicit entityIDCodec: EntityIDCodec[TID], monadError: MonadError[F, Throwable])
    extends Coordinator[F, TID, BID, Q, R] {
  private implicit val entityIDShow: Show[TID] = Show.show(entityIDCodec.encode)

  def get(id: TID): Resource[F, Transaction[F, BID, Q, R]] =
    Resource.make(sharding.entityFor(id).pure[F])(release =
      transaction =>
        (transaction.status >>= {
          case Right(_: Transaction.Status.Final[R]) => ().pure
          case Right(_: Transaction.Status.Pending[R]) =>
            Logger[F].debug(show"Aborting transaction $id") >> transaction.abort() >>= {
              case Right(_) => Logger[F].debug(show"Transaction $id aborted")
              case Left(_)  => Logger[F].warn(show"Failed to abort transaction $id")
            }
          case Left(_) => Logger[F].debug(show"Transaction $id not yet created")
        }).handleErrorWith(throwable =>
          Logger[F].warn(throwable)(show"Failed to abort transaction $id")
        )
    )

  def create(
      id: TID,
      query: Q,
      branch: BID,
      otherBranches: BID*
  ): Resource[F, Transaction[F, BID, Q, R]] =
    Resource
      .eval(
        Logger[F].debug(show"Creating transaction $id") >>
          sharding
            .entityFor(id)
            .create(id, query, NonEmptyList.of[BID](branch, otherBranches*))
      )
      .flatMap {
        case Right(_) =>
          Resource.eval(
            Logger[F].debug(show"Transaction transaction $id successfully created")
          ) >> get(id)
        case Left(_) =>
          Resource.eval(Logger[F].warn(show"Transaction $id already exists")) >> Resource
            .raiseError[F, Transaction[F, BID, Q, R], Throwable](
              Coordinator.TransactionAlreadyExists
            )
      }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy