scalascala-catscats-effectfs2

How to make cancellable timeout callback?


I want that user can run a timer with callback and able to cancel it. Something like this:

def main: F[Unit] =
  for
    cancel       <- runTimer(callback, 5.seconds)
    shouldCancel <- askUser
    _            <- cancel.whenA(shouldCancel)
  yield ()

How can I do it in terms of Cats of FS2?


Solution

  • The code that you need is actually pretty simple thanks to cats-effect being very powerful at solving concurrency problems:

    def runTimer(
      callback: IO[Unit],
      delay: Duration,
      cancel: IO[Unit]
    ): IO[Unit] =
      IO.race(
        IO.sleep(delay) >> callback.uncancelable,
        cancel
      ).void
    

    The key aspects are as follows:

    You could improve this to ensure that cancel can't cancel the callback, but allow an upper cancellation to cancel the whole race.


    You can see a demo of the code running here: https://scastie.scala-lang.org/BalmungSan/UP6N6wMBTQGLHPjOmXS9mw/1