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

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

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

import cats.Applicative
import cats.effect.kernel.syntax.spawn.*
import cats.effect.kernel.{Fiber, Ref, Temporal}
import cats.syntax.applicative.*
import cats.syntax.flatMap.*
import cats.syntax.functor.*
import endless.transaction.Transaction.Status

import scala.concurrent.duration.FiniteDuration

private[transaction] trait TimeoutSideEffect[F[_]] {
  def scheduleTimeoutAccordingTo[R](status: Status[R]): F[Unit]
}

private[transaction] object TimeoutSideEffect {
  private type UnitFiber[F[_]] = Fiber[F, Throwable, Unit]

  def apply[F[_]: Temporal](
      timeout: Option[FiniteDuration],
      triggerTimeout: F[Unit]
  ): F[TimeoutSideEffect[F]] =
    for {
      neverTimeout <- Temporal[F].never[Unit].start
      timeoutFiberRef <- Ref.of(neverTimeout)
      timeoutSideEffect <- new FiberBasedTimeoutSideEffect[F](
        timeoutFiberRef,
        timeout,
        triggerTimeout
      )
        .pure[F]
    } yield timeoutSideEffect

  private class FiberBasedTimeoutSideEffect[F[_]](
      timeoutFiberRef: Ref[F, UnitFiber[F]],
      timeout: Option[FiniteDuration],
      triggerTimeout: F[Unit]
  )(implicit temporal: Temporal[F])
      extends TimeoutSideEffect[F] {
    import temporal.*

    def scheduleTimeoutAccordingTo[R](status: Status[R]): F[Unit] = timeout match {
      case Some(duration) =>
        status match {
          case Status.Preparing =>
            (timeoutFiberRef.access >>= { case (fiber, set) =>
              fiber.cancel >> sleepThenTrigger(duration).start >>= set
            }).void
          case _ =>
            (timeoutFiberRef.access >>= { case (fiber, set) =>
              fiber.cancel >> never[Unit].start >>= set
            }).void
        }
      case None => Applicative[F].unit
    }

    private def sleepThenTrigger(duration: FiniteDuration) = sleep(duration) >> triggerTimeout
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy