Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling timeouts in immutable classes

I want a thread-safe (immutable) Scala class for a long working task. For some corner cases the tasks takes very long so I want to implement a time-out. What's the best way to implement this in an immutable class?

My first attempt was to use an implicit parameter like this:

class Worker(val input: String) {

  def start: String = {
    implicit val startTimeStamp = new TimeStamp
    doSomething1 + doSomething2
  }

  def doSomething1()(implicit startTimeStamp: TimeStamp): String = { ... }

  def doSomething2()(implicit startTimeStamp: TimeStamp): String = {
    ... 
    checkTimeout 
    ...
   }
}

class TimeStamp { val start = System.currentTimeMillis }

This should work, but there is still a lot of boiler-plate code with the implicit parameters. (In the real code I have hundreds deeply nested doSomething-functions in the worker class.) Is there a more beautiful way to do this in Scala?

like image 483
Sonson123 Avatar asked Feb 04 '13 16:02

Sonson123


2 Answers

Sounds like you are looking for futures. In scala 2.9.x I would suggest you to use the akka library for that, from 2.10.0 on there is the scala.concurrent.Future trait.

example for 2.10:

import concurrent._
import concurrent.duration._
import ExecutionContext.Implicits.global

val f = future {
  blocking {
    // long running task
  }
}

try {
  val res = Await.result(f, 100 millis)
} catch {
  case e: java.util.concurrent.TimeoutException =>
    // handle timeout
}

edit: added blocking call as suggested by Viktor Klang.

like image 128
drexin Avatar answered Nov 12 '22 23:11

drexin


Use Hystrix. It is a Java library which does exactly what you are asking for. Plays nice with Scala and got great documentation.

Example:

class LongOperation(...) extends HystrixCommand[Result](
  HystrixCommandProperties.Setter()
    .withExecutionIsolationThreadTimeoutInMilliseconds(60 * 1000))
{
  override protected def run: Result = {
    // your code
  }
}

How to execute synchronously:

val result = new LongOperation(...).execute()
like image 26
Jakozaur Avatar answered Nov 12 '22 22:11

Jakozaur