How to avoid try with Future fromTry - scala

I need to write a future that flushes a stream and closes it. Here is what I tried:
def close(ous: OutputStream) = Future.fromTry(Try {
try {
ous.flush()
} finally {
ous.close()
}
})
Looks ugly. try{}finally{} inside the Try. But I need finally block in order to avoid resource leak. Is there a way to rewrite the code in not so ugly way?

Future already captures exceptions returning a Future.failed, there's no need to do fromTry and block, so you can do:
Future { out.flush() }.andThen( _=> out.close )
( Future { out.flush() } will asynchronously flush the stream and andThen will get called wether it finishes or fails.

This could be an option i think.
def close(ous: OutputStream) = Future.fromTry(Try(ous.flush())) andThen {
case Success(_) => println("do something here")
case Failure(_) => ous.close()
}

It's not clear to me whether this is actually cleaner:
def close(ous: OutputStream) = Future.fromTry(
val flushed = Try { ous.flush() }
val closed = Try { ous.close() }
if (closed.isFailure) closed else flushed // bubble up the correct error
)
Note: This is nearly an equivalent of this answer but not quite. Mainly since the .close can fail, and this must be encapsulated in the Try.

since you are already using Try use pattern match on result to Try{ stream.flush } and apply Try{ stream.close() }
example,
import java.io.{ByteArrayOutputStream, OutputStream}
import java.util.Date
import java.io.ObjectOutputStream
import scala.concurrent.Future
import scala.util.Try
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
def doSomeOperation: OutputStream => Future[String] = (outputStream: OutputStream) =>
withCleanup(outputStream) {
Future {
//1/0
outputStream.toString
}
}
def withCleanup(outputStream: OutputStream)(fn: Future[String]): Future[String] = {
val execution = fn
execution onComplete {
case Success(_) => cleanup(outputStream)
case Failure(_) => cleanup(outputStream)
}
execution
}
def cleanup(outputStream: OutputStream): Try[Unit] = Try {
outputStream.flush()
println("flushed")
} match {
case _ => Try {
outputStream.close()
println("closed")
}
}
Then call the function, which will flush and close your stream as well.
val stream = new ObjectOutputStream(new ByteArrayOutputStream())
stream.writeObject(new Date())
scala> doSomeOperation(stream)
res18: scala.concurrent.Future[String] = Future(<not completed>)
flushed
closed

Related

Scala Future not printing results

I am learning Scala Future with the following code:
object DangerousAndSlowService {
def queryNextNumber: Long = {
50
}
}
val number1F = Future { DangerousAndSlowService.queryNextNumber }
number1F.onComplete({
case Success(value) => {
println(s"Got the callback, meaning = $value")
}
case Failure(exception) => {
exception.printStackTrace
}
})
However, the "50" is never printed.
Already spent several hours but still cannot figure it out.
Thanks.
The main thread exits without letting the future finish its job, therefore the output is non-deterministic: sometimes it does print something, sometimes it doesn't. If you don't mind blocking the main thread, you can use Await:
import scala.concurrent.Future
import scala.util.{Success, Failure}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
object DangerousAndSlowService {
def queryNextNumber: Long = {
50
}
}
val number1F = Future { DangerousAndSlowService.queryNextNumber }
number1F.onComplete({
case Success(value) => {
println(s"Got the callback, meaning = $value")
}
case Failure(exception) => {
exception.printStackTrace
}
})
Await.result(number1F, 1.second)
While Await is necessary here to produce the output, it's also good to note you should use it with caution. It blocks the current thread, which is typically not what you want when you work with asynchronous computations and futures.

How to spawn an unknown amount of Futures and combine the result even if one or more failed?

I want to turn the following sequential code into concurrent code with Futures and need advice on how to structure it.
sequential:
import java.net.URL
val providers = List(
new URL("http://www.cnn.com"),
new URL("http://www.bbc.co.uk"),
new URL("http://www.othersite.com")
)
def download(urls: URL*) = urls.flatMap(url => io.Source.fromURL(url).getLines).distinct
val res = download(providers:_*)
I want to download all sources that are coming in via the varargs of the download method and combine the results into one Seq/List/Set, whatever, together. When one Future failed, let's say because the server is unreachable, it should take all others and move on and return the result nonetheless. firstCompletedOf won't work because I need the results of all, except one failed due to error. I thought about using Future.sequence like below but I can't get it to work. Here is what I tried...
def download(urls: URL*) = Future.sequence {
urls.map { url =>
Future {
io.Source.fromURL(url).getLines
}
}
}
This produces a Seq[Future[Iterator[String]]] which is not compatible with M_[Future[A_]].
A Future[Iterator[String]] is what I want. (I thought I return an Iterator because I need to reuse it later on with reset method on Iterator.)
You can use parallel collections:
import java.net.URL
val providers = List(
new URL("http://www.cnn.com"),
new URL("http://www.bbc.co.uk"),
new URL("http://www.othersite.com")
)
def download(urls: URL*) = urls.par.flatMap(url => {
Try {
io.Source.fromURL(url).getLines
} match {
case Success(e) => e
case Failure(_) => Seq()
}
}).toSeq
val res: Seq[String] = download(providers:_*)
Or if you want the non blocking version with a Future:
def download(urls: URL*) = Future {
blocking {
urls.par.flatMap(url => {
Try {
io.Source.fromURL(url).getLines
} match {
case Success(e) => e
case Failure(_) => Seq()
}
})
}
}
val res: Future[Seq[String]] = download(providers:_*)

Executing a code block even after catching an exception in Scala

In my current method, I am trying to make a series of calls and if any of them fail, I want to be able to continue running the remainder (while capturing the Exception that was thrown). I am having a hard time figuring this out in Scala.
So in this example, I want to kick off each of these calls - RunA, RunB and RunC but if RunB throws an exception, I want to print that and continue kicking off RunC after that.
var result = Try {
new RunA()
new RunB()
new RunC()
} catch {
case e: Throwable => e.printStackTrace()
false
}
Outside of having them all individually wrapped in a Try/Catch, I am sure there are better ways to do this which is why I am hoping someone can help with this.
I looked at the 'Ignoring' exception but it appears to completely ignore the exception which I want to atleast log.
Thanks!
First, don't mix try { ... } catch { ... } up with scala.util.Try{ ... }.
You can
import scala.util._
val runA = Try{ new RunA }
val runB = Try{ new RunB }
val runC = Try{ new RunC }
and then deal with the exceptions as you see fit. For instance, if you want to print and continue, you could deal with the try statements right there:
def getOrPrint[A](f: => A): Option[A] = Try{ f } match {
case Success(x) => Some(x)
case Failure(e) => e.printStackTrace; None
}
getOrPrint{ new RunA }
...
There can be more elegant ways for such things with scalaz (e.g. read an article here for some inspiration: http://johnkurkowski.com/posts/accumulating-multiple-failures-in-a-ValidationNEL/), but with "only" Scala you can do something like this:
import scala.reflect.ClassTag
import scala.util.{Try, Success, Failure}
def tryAndLog[T: ClassTag] = Try {
implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T] // new instance
} match {
case Success(_) => true
case Failure(ex) => ex.printStackTrace ; false
}
def tryRunAll = {
val A = tryAndLog[RunA]
val B = tryAndLog[RunB]
val C = tryAndLog[RunC]
A && B && C // returns true if all invocations succeeded, false otherwise
}
You are mixing scala.util.Try with try {} catch {} which are different concepts. Try wraps function into Success(result) or Failure(error) class, and try-catch is like Java try-catch. I suggest you something like this:
class RunA
class RunB
class RunC
class Result(a: RunA, b: RunB, c: RunC)
implicit class LogFailure[T](t: Try[T]) {
def logFailure: Try[T] = t match {
case scala.util.Failure(err) => err.printStackTrace(); t
case _ => t
}
}
val tryA= Try(new RunA())
val tryB= Try(new RunB())
val tryC = Try(new RunC())
val result: Try[Result] = for {
a <- tryA.logFailure
b <- tryB.logFailure
c <- tryC.logFailure
} yield {
// do smth with a, b, c
new Result(a, b, c)
}
If A, B, C will be successful you'll get Success(Result) if one of them failure you'll get Failure with first exception, however all of them will be logged (printed stack trace)

Why does Future's recover not catch exceptions?

I'm using Scala, Play Framework 2.1.x, and reactivemongo driver.
I have an api call :
def getStuff(userId: String) = Action(implicit request => {
Async {
UserDao().getStuffOf(userId = userId).toList() map {
stuffLst => Ok(stuffLst)
}
}
})
It works fine 99% of the time but it may fail sometimes (doesn't matter why, that's not the issue).
I wanted to recover in a case of an error so i added:
recover { case _ => BadRequest("")}
But this does not recover me from errors.
I tried the same concept on the scala console and it worked:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
var f = future { throw new Exception("") } map {_ => 2} recover { case _ => 1}
Await.result(f, 1 nanos)
This returns 1 as expected.
I currently wrapped the Async with:
try{
Async {...}
} catch {
case _ => BadRequest("")
}
And this catches the errors.
I went over some Scala's Future docs on the net and I'm baffled why recover did not work for me.
Does anyone know why? What do I miss to sort it out?
Why it fails actually matters 100%. If we spread the code over a number of lines of code, you'll understand why:
def getStuff(userId: String) = Action(implicit request => {
Async {
val future = UserDao().getStuffOf(userId = userId).toList()
val mappedFuture = future.map {
stuffLst => Ok(stuffLst)
}
mappedFuture.recover { case _ => BadRequest("")}
}
})
So, UserDao().getStuffOf(userId = userId).toList() returns you a future. A future represents something that may not have happened yet. If that thing throws an exception, you can handle that exception in recover. However, in your case, the error is happening before the future is even being created, the UserDao().getStuffOf(userId = userId).toList() call is throwing an exception, not returning a future. So the call to recover the future will never be executed. It's equivalent to doing this in the Scala repl:
import scala.concurrent._
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
var f = { throw new Exception(""); future { "foo" } map {_ => 2} recover { case _ => 1} }
Await.result(f, 1 nanos) }
Obviously that doesn't work, since you never created the future in the first place beacuse the exception was thrown before the code to create the future happened.
So the solution is to either wrap your call to UserDao().getStuffOf(userId = userId).toList() in a try catch block, or find out why it's failing in whatever method you're calling, and catch the exception there, and return a failed future.
If you have a later version of Play eg 2.2.x, you can do this:
def urlTest() = Action.async {
val holder: WSRequestHolder = WS.url("www.idontexist.io")
holder.get.map {
response =>
println("Yay, I worked")
Ok
}.recover {
case _ =>
Log.error("Oops, not gonna happen")
InternalServerError("Failure")
}
}

Is there a standard Scala function for running a block with a timeout?

I need to call into a service that may or not return timely results. I'd like to be able to write
val result = runWithTimeout(5000, valReturnedOnTimeout) { service.fetch }
Is there a standard function that will do the job - like Ruby's timeout?
With credit to the other answers - in the absence of any standard library function, I've gone down the Futures route.
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
Some(Await.result(Future(f), timeoutMs milliseconds))
}
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeout(timeoutMs)(f).getOrElse(default)
}
So that
#Test def test {
runWithTimeout(50) { "result" } should equal (Some("result"))
runWithTimeout(50) { Thread.sleep(100); "result" } should equal (None)
runWithTimeout(50, "no result") { "result" } should equal ("result")
runWithTimeout(50, "no result") { Thread.sleep(100); "result" } should equal("no result")
}
I'd be grateful for any feedback as to whether this is a good Scala style!
You could use a future
import scala.actors.Futures._
val myfuture =
future {
Thread.sleep(5000)
println("<future>")
"future "
}
awaitAll(300,myfuture ) foreach println _
But also have a look at Circuit Breaker for Scala which is a implementation of the
Circuit Breaker Pattern. Basically it lets you control the timeout and what should happen if a failure occurs accessing an external resource
Usage looks like this in Scala (from the readme) :
. . .
addCircuitBreaker("test", CircuitBreakerConfiguration(timeout=100,failureThreshold=10))
. . .
class Test extends UsingCircuitBreaker {
def myMethodWorkingFine = {
withCircuitBreaker("test") {
. . .
}
}
def myMethodDoingWrong = {
withCircuitBreaker("test") {
require(false,"FUBAR!!!")
}
}
}
Might Futures and its alarm do the trick?
Something that hasn't been mentioned yet is awaitEither, a method on the actors package's Futures object. awaitEither returns the result from the first of a pair of futures to complete, so for example something like this could be used:
awaitEither(future{task}, alarm(timeoutPeriod))
and then dressed up in a method as suggested:
def runWithTimeout[T](timeoutPeriod: Int, timeoutValue: T)(task: => T) = {
awaitEither(future{task}, alarm(timeoutPeriod)) match {case () => timeoutValue case x => x}
}
alarm returns Unit which is assignable to a val of type Any so awaitEither returns something that can be pattern matched against.
You can start it in a new Thread and then wait for it to finish with Thread.join. If you pass a parameter to join, it waits at most that many milliseconds.
val t = new Thread {
override def run() {
//...
}
}
t.start()
t.join(5000)
The post above
import scala.concurrent.ExecutionContext.Implicits.global import
scala.concurrent._ import scala.concurrent.duration._
def runWithTimeout[T](timeoutMs: Long)(f: => T) : Option[T] = {
Await.result(Future(f), timeoutMs milliseconds).asInstanceOf[Option[T]] }
def runWithTimeout[T](timeoutMs: Long, default: T)(f: => T) : T = {
runWithTimeout(timeoutMs)(f).getOrElse(default) }
didn't work for me on Scala 2.11.
Following modified version works for me:
def runWithTimeout[T](timeout: Long)(f: => T): Option[T] = {
Option.apply(Await.result(Future(f), timeout seconds))
}