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.

4

2 回答 2

2

另一种方法是使用Observable,它使事情更容易编写。它还具有许多内置功能,因此您无需手动处理自己的功能。

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
于 2019-11-18T08:54:34.490 回答
1

您始终可以利用 scala.util.Try 或简单的 try-catch 块。在任何失败的情况下,您只需登录并继续前进。您甚至可以有如下失败重试策略。

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)
            }
    }
}
于 2018-09-12T10:23:51.670 回答