Understanding Spray's detach directive - scala

I'm trying to understand Spray's detach directive and whether there's any difference between using detach and using the onComplete directive. What I want to achieve is "one thread per request" where by thread I mean JVM thread ( which should be an OS thread).
So, what the difference between A and B ?
Method A:
// assume controller.divide(a,b) returns Future[Int]
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(controller.divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete(InternalServerError, s"An error occurred: ${ex.getMessage}")
}
}
Method B:
// assume controller.divide(a,b) returns Int
val route = {
path("divide" / IntNumber / IntNumber) { (a,b) =>
detach(global) {
Try { controller.divide(a,b) } match {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete(InternalServerError, s"An error occurred: ${ex.getMessage}")
}
}
} }
Cheers !

The point of detach is that you don't need your method to return a Future - that's really it.
The idea is to run items you know won't throw exceptions compactly, but without needing to block the handler thread. You should rewrite Method B as:
detach(global) {
complete(s"The result was ${controller.divide(a, b)}")
}
In the spray-routing world, the Failure case would be handled by an outer handleExceptions directive.

See Spray's `detach` Directive where the accepted answer explains very well, what
detach does and
how it uncouples from the route executing actor.

Related

How to implement a retry logic in pattern match?

This is my function that used to call another api, I want to do a retry when I got some specific exception(TimeoutException, etc) for 3 times, how can do that? Thanks for help!
determinationService.getTax(getRequest, runID) match {
case Success(getResponse) =>
LOGGER.info("Following response received from determination service:")
LOGGER.info(getTaxResponse.toString)
...
case Failure(exception) =>
LOGGER.error(
"AppName:{} RunID:{} Grpc error when calling Determination service: {}",
Array(LoggingConstant.APP_NAME, runID, exception): _*
)
//do retry here
}
unit test
val determinationServiceMock = mock[DeterminationService]
doReturn(Failure(new TimeOutException())).when(determinationServiceMock).getTax(any(), any())
Assuming a result type of Unit you could do:
#tailrec
def someDef(retry: Int = 0): Unit = {
determinationService.getTax(getRequest, runID) match {
case Success(getResponse) =>
LOGGER.info("Following response received from determination service:")
LOGGER.info(getTaxResponse.toString)
// ...
case Failure(exception) =>
LOGGER.error(
"AppName:{} RunID:{} Grpc error when calling Determination service: {}",
Array(LoggingConstant.APP_NAME, runID, exception): _*
)
exception match {
case _: TimeoutException if retry < 3 => someDef(retry + 1)
case _ => // ...
}
}
}
Note: your actual code might not be tail-recursive, just this snippet is.

What can i use to write this scala code better?

functionThatReturnsATry[Boolean]() match {
case Success(value) =>
value match {
case true => somethingThatReturnsFuture[Unit]
case false =>
Failure(new SomeException("This failed here"))
}
case Failure(exception) => Failure(exception)
}
The code will return Future[Unit] when functionThatReturnsATry finishes succesfully and returns true.
If functionThatReturnsATry fails, i want to pass that failure up the chain.
If functionThatReturnsATry returns false, i want to pass a new sepecific failure up the chain
One improvement would be to use guard expressions on the match to separate the three different cases. You should also return Future.failed rather than Failure so that the result is Future[Unit] not Any:
functionThatReturnsATry[Boolean]() match {
case Success(value) if value =>
somethingThatReturnsFuture[Unit]
case Success(_) =>
Future.failed(new SomeException("This failed here"))
case Failure(exception) =>
Future.failed(exception)
}
I like the existing answer, but as an alternative, if you don't care about controlling the precise exception of the first step, you can wrap your Try in a Future and use a for-comprehension:
def attempt(): Try[Boolean] = Success(true)
def soon(): Future[Unit] = Future.failed(new RuntimeException("uh"))
for {
success <- Future.fromTry(attempt()) if success
result <- soon()
} yield result
The code is available here on Scastie.
I'd be tempted to fold() over the Try.
functionThatReturnsATryBool()
.fold(Future.failed
,if (_) somethingThatReturnsFutureUnit()
else Future.failed(new SomeException("This failed here"))
)
The result is type Future[Unit] with either type of failure returned as Future(Failure(java.lang.Exception(...))). No loss of error message.
functionThatReturnsATry[Boolean]() match {
case Success(true) => somethingThatReturnsFuture[Unit]
case Success(false) => Future.failed(new SomeException("This failed here"))
case Failure(exception) => Future.failed(exception)
}
https://scalafiddle.io/sf/DSaGvul/0

Scala: Chaining futures, returning the first

I have a scenario where I have a Future[Something]: a which when successful needs to trigger a second Future[Unit]: b. I want to chain a and b together but I only care that a succeeds. if b fails I can just log an error and leave it at that:
So far I have:
def updateSomething(something: Something): Future[Something] = {
val eventual: Future[Something] = repository.update(something)
eventual.onSuccess({
case updated =>
repository.audit(updated.id, "Update successful")
.onFailure({
case throwable: Throwable => Logger.error("Audit failed", throwable)
})
Logger.info("Update Complete")
})
eventual
}
But this does not link the lifecyles of the update and the audit together. e.g when I Await.result(service.updateSomething(...), duration) there is no guarantee the repository.audit future has completed.
flatMap is your friend. You can just use a for-comprehension + recover:
for {
a <- executeA()
_ <- executeB(b).recover{case e => println(e); Future.unit } // awaits B to complete
} yield a
Also you can use more friendly form:
execudeA().flatMap(a =>
executeB().recover { case e => println(e); () }.map(_ => a)
)
also, you can just use a val
val = a <- executeA()
a.andThen{ case _ => executeB(b).recover{case e => println(e)} }
a //and return a

Scala map over a Future

In the following example, what is the expected behaviour?
import scala.concurrent.ExecutionContext.Implicits.global
val someFuture = Future { 1+1 }.map(elem => {
println("mapping immediately")
elem.toString
})
someFuture.onComplete {
case scala.util.Success(value) => println(s"Got the callback = $value")
case Failure(e) => e.printStackTrace()
}
Is the following output always guaranteed?
mapping immediately
Got the callback = 2
It depends.
val someFuture = Future { 1+1 }.map(elem => {
println("mapping immediately")
elem.toString
})
someFuture will be executed eagerly and the println will be executed.
someFuture.onComplete {
case scala.util.Success(value) => println(s"Got the callback = $value")
case Failure(e) => e.printStackTrace()
}
onComplete is an event listener for a Future. This is called only when this future is completed, either through an exception, or a value, to apply the provided function.
Therefore, it will always execute after the execution of the someFuture.
Assuming that the someFuture is not going to fail, the order
`mapping immediately
Got the callback = 2`
is guaranteed.
For what ever reason, if there's an exception thrown, then the result would change. In that case Got the callback = 2 will not be printed and mapping immediately may or may not be printed.
Hope this helps.

In scala how to wrap a PartialFunction?

In scala, Futures have a sort of rescue function that takes a PartialFunction. This code is skipped if the Future resolved with a response but is called if a failure occurs.
I want to simple wrap the partial function in a proxy that always executes code that writes to a stat counter. At first I was thinking I would just create another PartialFunction but soon realized that does not work very well with the isDefined, then apply as I really want this to be called every time.
How do I go about proxying the PartialFunction such that my code is always called when the Future has an exception?
To summarize the comments: You can use the onFailure callback to execute some side-effecting code (logging) when a Future fails.
val future = Future(1 / 0)
future.onFailure {
case _ => println("I have seen the Future, and it doesn't look good.")
}
As #cmbaxter notes, you could also use andThen on the Future, which accepts a PartialFunction[Try[A], B] and returns the original Future. So you could apply the side-effecting function using andThen, and than recover afterwards. You could even chain them multiple times.
Future(1 / 0)
.andThen { case Failure(_) => println("Future failed.") }
.recover { case e: ArithmeticException => 0 }
.andThen { case Failure(_) => println("Tried to recover, and still failed.") }
Or a helper that always includes it:
object FutureLogger {
def apply[A](a: => A): Future[A] = Future(a).andThen {
case Failure(_) => println("FAILURE")
}
}