What can i use to write this scala code better? - scala

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

Related

Propagate errors through a chain of Scala futures

Considering a sequence of futures each returning Either[Status, Resp].
How would you propagate error status codes through a for comprehension which is using Future and not Either?
The code bellow does not work, since the parsing exception is not caught by .recover of the last future
The use case is Scala Play ActionRefiners which returns Future[Either[Status, TRequest[A]]].
def parseId(id: String):Future[Int] = {
Future.successful(Integer.parseInt(id))
}
def getItem(id: Int)(implicit ec: ExecutionContext): Future[Either[Status, String]] =
Future(Some("dummy res from db " + id)).transformWith {
case Success(opt) => opt match {
case Some(item) => Future.successful(Right(item))
case _ => Future.successful(Left(NotFound))
}
case Failure(_) => Future.successful(Left(InternalServerError))
}
(for {
id <- parseId("bad request")
resp <- getItem(id)
} yield resp).recover {
case _:NumberFormatException => Left(BadRequest)
}
I could move the .recover to parseId, but this makes the for comprehension very ugly - having to treat the Either[Status, id] in the middle
def parseId(id: String):Future[Either[Status, Int]] = {
Future.successful(Right(Integer.parseInt(id))).recover {
case _:NumberFormatException => Left(BadRequest)
}
}
Your exception is not caught because you are not throwing it inside the Future: Future.successful is immediately satisfied with the result of the expression you give it, if it throws an exception, it is executed on the current thread.
Try removing the .successful: Future(id.toInt) will do what you want.
Also, I would recommend to get rid of all the Eithers: these are highly overrated/overused, especially in the context of Future (that already wrap their result into Try anyhow), and just make the code more complicated and less readable without offering much benefit.
case class FailureReason(status: Status)
extends Exception(status.toString)
def notFound() = throw FailureReason(NotFound)
def internalError() = throw FailureReason(InternalError)
def badRequest() = throw FailureReason(BadRequest)
def parseId(id: String):Future[Int] = Future(id.toInt)
def getItem(id: Int): Future[String] = Future(Some("dummy"))
.map { _.getOrElse(notFound) }
.recover { _ => internalError }
// this is the same as your for-comprehension, just looking less ugly imo :)
parseId("foo").flatMap(getItem).recover {
case _: NumberFormatException => badRequest()
}
// if you still want `Either` in the end for some reason:
.map(Right.apply[Status, String])
.recover {
case _: NumberFormatException => Left(BadRequest) // no need for the first recover above if you do this
case FailureReason(status) => Left(status)
}

How to put error logs in code when using pattern matching?

I have a function convert date time to epoch, and I want to put some logs where it failed. Such as case _ => and .getOrElse(JNothing) , how can I do that?
def time_to_epoch(params: List[JValue]): JValue = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
***
}.getOrElse(JNothing) // for saying something similar to can't convert time to epoch
case _ =>
JNothing // Add a (ErrorMessage(xxxxxxx)) for saying number of parameters are invalid and what are expected inline function forma
}
def time_to_epoch(params: List[JValue]): JValue = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
//***
}.getOrElse {
log.error("Cant ...")
JNothing
}
case _ =>
log.error("Number ...")
JNothing
}
For functional programming solution, there's treelog you can use, but it's really not necessary in your case, unless you need the function to be strictly pure.
If time_to_epoch can fail then it is better to return a Try rather than a special failure value like JNothing.
case class MyException(msg: String) extends Exception
def time_to_epoch(params: List[JValue]): Try[JValue] = params match {
case JString(timestamp) :: JString(pattern) :: JString(timezone) :: Nil =>
Try {
???
}
case _ =>
Failure(MyException("Invalid parameters"))
}
You can print the error information using match:
time_to_epoch(???) match {
case Failure(e) =>
println(s"Operation failed: $e")
case _ =>
}
The advantage of this is that it is easy to chain multiple Try operations without having to test for failure at each step. It allows the code to focus on the main code path while still handling errors correctly.

Testing exceptions in Scala

I want to test (in Intellij Idea testing framework) the following code:
def eval(t: Term): Term = t match {
case t if isVal(t) => t
case If(t1,t2,t3) if True == eval(t1) => eval(t2)
case If(t1,t2,t3) if False == eval(t1) => eval(t3)
case Succ(t) if isNum(eval(t)) => Succ(eval(t))
case Pred(t) => eval(t) match {
case Zero => Zero
case Succ(v) if isNum(v) => v
case _ => throw TermIsStuck(Pred(eval(t)))
}
case IsZero(t) => eval(t) match {
case Zero => True
case Succ(v) if isNum(v) =>False
case _ => throw TermIsStuck(IsZero(eval(t)))
}
case _ => throw TermIsStuck(t)
}
For a reference you can see this repository. So I wrote the following test:
test("testEval") {
Arithmetic.term(new Arithmetic.lexical.Scanner("if iszero pred pred 2 then if iszero 0 then true else false else false")) match {
case Arithmetic.Success(res,next) => assert(eval(res) == True)
case Arithmetic.Failure(msg,next) => assert(false)
}
Arithmetic.term(new Arithmetic.lexical.Scanner("pred succ succ succ false")) match {
case Arithmetic.Success(res,next) => assert(Arithmetic.eval(res) == TermIsStuck(Succ(False)))
case Arithmetic.Failure(msg,next) => assert(false)
}
}
Getting the error:
Succ(False)
fos.Arithmetic$TermIsStuck: Succ(False) ...
How can I test this catching the error? Indeed this test should be passed...
You are in Scala you are not supposed to throw exception around, but in scalatest you can do something like this:
a[yourException.type] should be thrownBy yourFunction()
You can do a better version of that,
case class Error(exception: Exception){
throw exception
???
}
Or something like
case object Error
And then you check it like:
Error shouldBe yourFunction()
Looks like you're not using any widespread testing framework for scala (such as scalatest or specs2) - an obvious recommendation would be to use some.
However, if you'd like to stick with "no-framework" approach, one option would be to use good old try .. catch:
val term = Arithmetic.term(
new Arithmetic.lexical.Scanner("pred succ succ succ false")
)
try {
val evaluated = term match {
case Arithmetic.Success(res,next) => Arithmetic.eval(res)
case Arithmetic.Failure(msg,next) => assert(false)
}
} catch {
case TermIsStuck(Succ(False)) => // do nothing, or explicitly mark test as successful
case _ => assert(false) // any other exception should fail the test
}
However, I think the implementation is partially broken - it never returns Arithmetic.Failure, but throws exception. I think the intent of Arithmetic.Failure was exactly to capture such cases. If that's the case, then better implementation would be to replace throw TermIsStuck with Arithmetic.Failure(TermIsStuck(...)).

Process Future[Try[Option]] in scala

I have a method that returns Future[Try[Option[Int]]]. I want to extract value of Int for further computation. Any idea how to process it??
future.map(_.map(_.map(i => doSomethingWith(i))))
If you want use cats you can do fun (for certain definitions of fun) things like:
import scala.concurrent._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global
import cats.Functor
import cats.instances.option._
import cats.implicits._
val x = Future { Try { Some(1) } } // your type
Functor[Future].compose[Try].compose[Option].map(x)(_ + 2)
This is suggested ONLY if you're already familiar with cats or scalaz.
Otherwise, you're great to go with any of the other valid answers here (I especially like the map-map-map one).
Just map the future and use match case to handle the different cases:
val result: Future[Try[Option[Int]]] = ???
result.map {
case Success(Some(r)) =>
println(s"Success. Result: $r")
//Further computation here
case Success(None) => //Success with None
case Failure(ex) => //Failed Try
}
Converting Future[Try[Option[Int]]] to Future[Int]
One hacky way is to convert the unfavourable results into failed future and flatMapping over.
Convert try failures to Future failures preserving the information that exception originated from Try and convert None to NoneFound exception.
val f: Future[Try[Option[Int]]] = ???
case class TryException(ex: Throwable) extends Exception(ex.getMessage)
case object NoneFound extends Exception("None found")
val result: Future[Int] = f.flatMap {
case Success(Some(value)) => Future.successful(value)
case Success(None) => Future.failed(NoneFound)
case Failure(th) => Future.failed(TryException(th))
}
result.map { extractedValue =>
processTheExtractedValue(extractedValue)
}.recover {
case NoneFound => "None case"
case TryException(th) => "try failures"
case th => "future failures"
}
Now in every case you know from where the exception has originated. In case of NoneFound exception you know Future and Try are successful but option is none. This way information is not lost and nested structure is flattened to Future[Int].
Now result type would be Future[Int]. Just use map, flatMap, recover and recoverWith to compose further actions.
If you really concerned about extraction see this, else go through the answer by #pamu to see how you actually use your Future.
Suppose your Future value is result.
Await.ready(result, 10.seconds).value.get.map { i => i.get}.get
Obviously this wont get through your failure and None cases and would throw exceptions and Await is not recommended.
So if you want to handle Failure and None case ->
val extractedValue = Await.ready(f, 10.seconds).value.get match {
case Success(i) => i match {
case Some(value) => value
case None => println("Handling None here")
}
case Failure(i) => println("Handling Failure here")
}

Understanding Spray's detach directive

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.