0

I am just starting to use monix, in part for scheduling repeated work in a long running app. I will manage exceptions but I would like that monix continue calling the given function even if I let pass some of them.

Now, from a simple test, once a repeated call is scheduled, it won't continue calling it once an exception arise :

// will print "Hi" repeatedly
scheduler.scheduleAtFixedRate(5.milliseconds, 2.milliseconds) {
  println("Hi")
}

// will print "Hi" only once
scheduler.scheduleAtFixedRate(5.milliseconds, 2.milliseconds) {
  println("Hi")
  throw new RuntimeException("oups, forgot to catch that one")
}

Note: I create the scheduler to log exceptions and errors

EDIT:

I realize that it's a poor design to simply repeat that task upon failure. Instead I should actually setup a proper exception management system, with delayed restart.

Now, I don't see any functionalities in Monix to do that. So I'll have to do it my-self. I let the question in case someone has the same issue, and in case someone knows of a monix tooling that can be useful.

Juh_
  • 14,628
  • 8
  • 59
  • 92

2 Answers2

3

An alternative is to use Observable, which makes things easier to compose. It also comes in with a lot of built in features, so you don't need to handroll your own function.

val myTask: Task[Unit] = Task.delay(println("Execute Task")

// Note that the period will tick after you've completed the task
// So, if you have a long running task, just make sure you are aware of that
Observable
  .intervalAtFixedRate(1.seconds, 1.seconds)
  .mapEval(_ => myTask.onErrorRestart(maxRetries = 5))
  .completedL
  .startAndForget // Optional, will run in a separate fiber, so it doesn't block main thread
  .runToFuture
atl
  • 326
  • 1
  • 9
2

You can always leverage scala.util.Try for that or simple try-catch blocks. On any failure case, you just log and move on. You can even have failure retry strategy as below.

import scala.util._

def taskExceptionProne() = ???

var failures = 0
val maxRetries = 10

scheduler.scheduleAtFixedRate(5.milliseconds, 2.milliseconds) {
    Try(taskExceptionProne) match {
        Success(result) =>
            //do something with the result
            failures = 0
            println("Task executed.")
        Failure(throwable) =>
            if (failures>=maxRetries) throw throwable else {
                failures = failures + 1
                //log failure
                println(throwable.getMessage)
            }
    }
}
lprakashv
  • 1,121
  • 10
  • 19