Some Name
Some Name

Reputation: 9540

Completing future with TimeoutException or Awaiting?

I have the following trait:

trait Tr{
     /**
      * Returns future of the number of bytes written
      */
     def write(bytes: Array[Byte]): Future[Long]
}

So I can await the result like this:

I.

val bts: Array[Byte] = //...
val to: Long = //...
val tr: Tr = //...
Await.result(tr.write(bts), to)

But I also can design the Tr in a bit different way:

trait Tr{
     /**
      * Returns future of the number of bytes written
      */
     def write(bytes: Array[Byte], timeout: Long): Future[Long]
}

II.

val bts: Array[Byte] = //...
val to: Long = //...
val tr: Tr = //...
Await.result(tr.write(bts, to), Duration.Inf)

What is the better way? I think the II case has its use in case where the actual writing-IO is not interruptible or performed by a caller thread. So for flexibility I would design the thread in the II way.

The thing is writing forever in II looks a bit wierd.

Is it correct to do so? Or I'm abuse the Future?

Upd: Consider the following possible implementation of the Tr:

class SameThreadExecutionContext extends ExecutionContext{
  override def execute(runnable: Runnable): Unit = runnable.run()
  override def reportFailure(cause: Throwable): Unit = ???
}

clas DummyTrImpl extends Tr{
    private final implicit val ec = new SameThreadExecutionContext
    override def write(bytes: Array[Byte]): Future[Long] = {
         Thread.sleep(10000)
         throw new RuntimeException("failed")
    }
}

Now if I write this:

val bts: Array[Byte] = //...
val to: Long = 1000
val tr: Tr = new DummyTrImpl
Await.result(tr.write(bts), to) //Waiting 10 secs instead of 1 
                                //and throwing RuntimeException instead of timeout

Upvotes: 0

Views: 122

Answers (2)

Tim
Tim

Reputation: 27421

The two traits have different behaviours, so it depends a little on what you are trying to achieve.

Trait I. says

Write some data and take as long as necessary. Complete the Future when the write completes or fails.

Trait II. says

Try to write some data but give up if it takes too long. Complete the Future when the write completes, or fails, or times out

The second option is preferred because it is guaranteed to progress, and because the write is not left hanging if the Await.result times out.

Upvotes: 2

Rich
Rich

Reputation: 15464

Option II is generally preferred (or globally set timeouts), because Futures are not generally "awaited", but tend to be chained instead.

It is unusual to write code like:

Await.result(tr.write(bts, to))

and more common to write code like:

tr.write(bts, to).then(written => ... /* write succeeded, do next action */ ..)

Upvotes: 4

Related Questions