Skip to content

Instantly share code, notes, and snippets.

@matfournier
Last active October 6, 2022 08:36
Show Gist options
  • Save matfournier/f115039ab0dcfbed98fd3b63f4424602 to your computer and use it in GitHub Desktop.
Save matfournier/f115039ab0dcfbed98fd3b63f4424602 to your computer and use it in GitHub Desktop.
forever repeating an action cats-effect question
/** An effect for infinitely repeating an action, use with care
* as there is no way to kill the process w/o shutting down the
* server in this implementation */
trait RepeatEval[F[_]] {
def repeat[A](fa: F[A], duration: FiniteDuration): F[Unit]
}
object RepeatEval {
def apply[F[_]](implicit ev: RepeatEval[F]): RepeatEval[F] = ev
implicit def concurrentBackground[F[_]: Concurrent: Timer]: RepeatEval[F] =
new RepeatEval[F] {
def repeat[A](fa: F[A], duration: FiniteDuration): F[Unit] =
(fa >> Timer[F].sleep(duration) >> repeat(fa, duration)).start.void
}
}
// in use somewhere else
def resource[F[_]: Concurrent: RepeatEval: ContextShift](
config: DarkLaunchConfig
): Resource[F, DarkLaunch[F]] = {
val path = Paths.get(config.fileLocation + config.fileName)
val refreshInterval: FiniteDuration = config.refreshInterval.getOrElse(5.seconds)
for {
ref <- Resource.liftF(Ref.of[F, Map[String, DarkLaunchRecord]](Map()))
service = new LiveDarkLaunchServiceEffect[F](ref)
loader = new ConfigDarkLaunchCodeLoader[F](ref, path)
_ <- RepeatEval[F].repeat(loader.load, refreshInterval).background
} yield service
}
// after comment: https://gitter.im/typelevel/cats-effect?at=5f3c9c208b8d4f633efeda1e
trait RepeatEval[F[_]] {
def repeat[A](fa: F[A], duration: FiniteDuration): Resource[F, F[Nothing]]
}
object RepeatEval {
def apply[F[_]](implicit ev: RepeatEval[F]): RepeatEval[F] = ev
implicit def concurrentBackground[F[_]: Concurrent: Timer]: RepeatEval[F] =
new RepeatEval[F] {
def repeat[A](fa: F[A], duration: FiniteDuration): Resource[F, F[Nothing]] =
(fa *> Timer[F].sleep(duration)).foreverM.background
}
}
// and used
def resource[F[_]: Concurrent: RepeatEval: ContextShift](
config: DarkLaunchConfig
): Resource[F, DarkLaunch[F]] = {
val path = Paths.get(config.fileLocation + config.fileName)
val refreshInterval: FiniteDuration = config.refreshInterval.getOrElse(5.seconds)
for {
ref <- Resource.liftF(Ref.of[F, Map[String, DarkLaunchRecord]](Map()))
service = new LiveDarkLaunchServiceEffect[F](ref)
loader = new ConfigDarkLaunchCodeLoader[F](ref, path)
_ <- RepeatEval[F].repeat(loader.load, refreshInterval)
} yield service
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment