Reputation: 9540
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
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
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