Trouble extending the Future[T] trait in Scala - scala

Please excuse my poor understanding of Scala. I'm just a Java developer that wants to get something working in the Play Framework. I even attempted to implement a trait using Java code, but I got even more obscure errors. I have the following Scala code:
package models
import scala.concurrent.Future
class SettableFuture[T](name: String) extends Future[T] {
var assignedValue: T
def set(newValue: T) =
assignedValue = newValue
//override abstract methods in Future[T]
def ready(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): models.SettableFuture[T] =
this
def result(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): T =
assignedValue
def isCompleted: Boolean =
false
def onComplete[U](func: scala.util.Try[T] => U)(implicit executor: scala.concurrent.ExecutionContext): Unit =
null
def value: Option[scala.util.Try[T]] =
null
}
And here's my error:
overriding method ready in trait Awaitable of type (atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait)SettableFuture.this.type; method ready has incompatible type
Ignore the return values of the methods for now, they're nonsensical because I'm just trying to fix all the compile errors.
I simply copied the method stubs from the compile time exception when extending a trait without overriding its abstract methods and pasted them into my source file. I don't understand why I'm still getting errors. I took a look at the signature for ready() in Awaitable and it looks like the return type should in fact be the class.
EDIT: the reason why I want to implement this is because in the Promise/Future Scala API, I can only find things that let me asynchronously execute long-running, blocking tasks. What I'm after is something that lets execution of a request be suspended until something of interest sets a value in the SettableFuture instance, which completes a Promise to send a response. In this way, it's somewhat like a continuation. Anyway, here is the working code that I ended up with:
package models
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import scala.concurrent.CanAwait
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import scala.util.Try
class SettableFuture[T]() extends Future[T] {
private final val ValueNotSet = 0
private final val ValueBeingSet = 1
private final val ValueSet = 2
private val valueStatus: AtomicInteger = new AtomicInteger(ValueNotSet)
private val onCompleteWaitHandle: CountDownLatch = new CountDownLatch(1)
private var onComplete: Try[T] => _ = _
private var assignedValue: T = _
/** Set a value and complete this Future.
*
* Returns false if the value has already been set by a past call to this method.
* Otherwise, marks this Future as complete, executes the function passed to
* onComplete, and finally returns true.
*/
def set(newValue: T): Boolean = {
//set value and trigger onComplete only once
if (valueStatus.compareAndSet(ValueNotSet, ValueBeingSet)) {
assignedValue = newValue
valueStatus.set(ValueSet)
onCompleteWaitHandle.countDown()
if (onComplete != null)
onComplete(Try(assignedValue))
true
}
false
}
//override abstract methods in the Future[T] trait
def ready(atMost: Duration)(implicit permit: CanAwait): this.type = {
onCompleteWaitHandle.await(atMost.length, atMost.unit)
this
}
def result(atMost: Duration)(implicit permit: CanAwait): T = {
ready(atMost)
assignedValue
}
def isCompleted: Boolean = (valueStatus.get() == ValueSet)
def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit =
onComplete = func
def value: Option[Try[T]] = {
if (!isCompleted)
None
Some(Try(assignedValue))
}
}

In terms of the specific error you are getting, the ready method you are overriding has a return type of Awaitable.this.type - ie. the specific type of this instance of Awaitable (the super type of Future, so that in Future, this method is seen to have return type Future.this.type). For your SettableFuture class, this means the return type for the ready method needs to be models.SettableFuture.this.type.
Other minor problems you can expect to hit: the onComplete method's implementation should be {}, not null, as the latter is a return of type Null.type, not Unit, and the var assignedValue needs to be initialised in a non-abstract class, which can be done by adding = _ to the line defining the variable (although you really want to make it at least protected, and provide an accessor which will check if it has been set - maybe by changing the variable to an Option[T] initialised to None, or else maintaining a Boolean flag that can be checked in the accessor, and which is set to true by the set method).
In terms of what it looks like you are trying to achieve, however, you might just want to check out scala.concurrent.Promise, which represents a "promise of a future result". It has a method future that returns a Future, and various complete, completeWith, and similar methods that can be used to set the Promise's value, which in turn will cause the associated Future to become ready/completed.

The SettableFuture class unnecessarily mixes the two concerns that the Future and Promise traits were designed to separate:
asynchronous provision of a value (Promise), and
waiting for and reacting to that provision (Future)
Rather than thinking of a Future as an asynchronous, long-running, blocking computation, it may help to think of it simply as a value that may be provided at some future time. You can react to provision of that value in a number of ways, including registering a callback or mapping it to some other value. For example, in Play one will often suspend processing of a request with a pattern like this (in Scala):
def handleRequest = Action {
Async {
gimmeAFuture().map(value => Ok(value))
}
}
def gimmeAFuture(): Future[JsValue] = // ...
The gimmeAFuture method returns a Future, but the request handling code doesn't care about how the value is computed. It could be
computed immediately with Future.successful,
computed asynchronously with Future.apply, or
supplied by the completion of a Promise
As an example of the latter, the gimmeAFuture method might be implemented as follows:
def gimmeAFuture: Future[JsValue] = {
val p = Promise.apply[JsValue]()
// asynchronously complete the promise 30 seconds from now
scheduler.scheduleOnce(30.seconds)(p.complete(Success(someJsObject)))
// return the future immediately
p.future
}
Of course, you could implement that method however you want. The key is that something will need to hold on to that Promise object and complete it with a value in order to resume handling of the request. The request handler itself does not get a reference to the Promise object, since it only cares about the value that will be computed (i.e., the Promise's Future).

I revisited this question after finding this link and I realized why there was so much confusion.
I was planning on using the SettableFuture class because I couldn't find anything like it that already existed in the Play Java API. I wanted something equivalent to a TaskCompletionSource in .NET, and Aaron's answer made it really clear that Scala had exactly what I needed. Unfortunately, I couldn't find the equivalent in Play's Java API.
That link cleared up exactly why I was having so much difficulty over something that should have been so simple. Thanks all for answering my question!

Related

Instantiate a top level lazy value based on value we get in a method scala

Is there a way to instantiate a top level lazy value based on value we get in a method
trait Props {
val env: String
}
object Exc extends App {
Foo.getInput("dev")
}
object Foo extends Props {
lazy val env: String = ???
def getInput(e: String): Unit = {
//How do I instantiate env with e here
env = e //this doesn't work
}
def exampleMethod() = println(env)
}
object Foo has to extend trait Props, so I need to figure out a way how to instantiate the variable env , based on what's passed in the method
The closest thing to what you want may well be a Future, which is the other notable case in the language and standard library where evaluation can be delayed and a result be write-once.
So something like the following
import scala.concurrent.{ Await, Future, Promise }
import scala.concurrent.duration.Duration
object Foo extends Props {
private val envPromise = Promise[String]()
lazy val env: String = Await.result(envPromise.future, Duration.Inf)
def getInput(e: String): Unit = {
envPromise.success(e)
}
}
If env is accessed before getInput is called, it will block the accessing thread for arbitrarily long until some other thread calls getInput (if no other thread does, it's effectively an infinite loop). Alternatively one can put a finite duration (e.g. 3.minutes) on the Await, which will throw an exception if getInput hasn't been called in that time. The exception in the lazy initializer will propagate to the accessing thread (which may be a bit of a surprise: someone given a Props would reasonably expect that accessing the env (a val) would not blow up), but a subsequent access after getInput was called will have the value.
Multiple calls to getInput will throw exceptions because a Promise can be completed at most one time.
My honest opinion is that it may be worth revisiting the decisions which led up to this. I would specifically consider some alternative like:
object Foo {
private val propsPromise = Promise[Props]()
val propsFuture: Future[Props] = propsPromise.future
def getInput(e: String): Unit =
propsPromise.success(new Props { val env: String = e })
}
Where you are delaying construction of a valid Props instance but can statically provide a reference to that instance for if/when it exists.
In this case env should be var:
var env: String = ???
lazy here is not needed

Setting an immutable field for later use

I'm in a situation where I need to set a certain field in a singleton object so it can be used later.
def register(importantField: String): Unit = {
Factory.setField(importantField)
}
where Factory is:
object Factory {
var field: Option[String] = None
def setField(importantField: String): Unit = {
field = Option(importantField)
}
def functionThatWillBeCalledLater: Unit = {
// do something with member "field"
}
}
but I really want to avoid using var. Is there some kind of idiomatic way to do this?
Don't do this. Global factories, besides being racy and breaking referential transparency, are also a nightmare for unit testing. You should really think about designing your code in a way, where you can keep all the "important fields" where you need them.
The trick is that instead of something like
class Foo {
def doFoo() = Factory.bar
}
Factory.register(param)
new Foo().doFoo()
You would have to write
class Foo {
def doFoo(factory: Factory) = factory.bar
}
new Foo().doFoo(new Factory(param)
Or maybe
class Foo(factory: Factory) {
def doFoo() = factory.bar
}
new Foo(new Factory(param)).doFoo
It may seem a bit tedious compared, to just throwing all the stuff into a global state object, and accessing it from everywhere ... but that's only as long as all of the uses of that function everywhere always use the same value of the parameter (in which case, it is better off just being a constant in the first place) or (perhaps, more importantly) until you start thinking about writing unit tests to test places that use your Factory. You cannot mock an object ... so, what will you do?
Singleton objects have to be thread safe - since the object is static, there's no guarantee that only one thread will access it, so your call not to use a var is totally reasonable. All vals are final and guaranteed to be thread safe, but we can't say the same about vars (and, well, if we're talking about idiomatic, mutable state is generally frowned upon).
You could implement your own getter and setter (using proper synchronization) for a private var, or use a scala.concurrent.Promise for this purpose - a Promise can only be completed once, and is guaranteed to be thread safe.
import scala.concurrent.Promise
object Factory {
private val _field: Promise[String] = Promise()
// the notation below allows you to set it via `Factory.field = "a"`
def field_=(value: String): Boolean = _field.trySuccess(value)
def field: Option[String] = _field.future.value.flatMap(_.toOption)
}
That said, the most idiomatic Scala way to approach factories with variable baseline conditions would be to create one with all the variables set to the values you need. An object is essentially just a val, so instead of an actual singleton object you could instantiate the Factory with all the parameters you need once they're available - and then just use that everywhere.

Return type with generic with bounds

I have the following code
import scala.concurrent.Future
class RequestType
class Read extends RequestType
class Write extends RequestType
object Main {
def main(args: Array[String]): Unit = {
}
def dbrequest[T <: RequestType](t: T): Future[T] = {
val dBRequest = new DBRequest
t match {
case r: Read => dBRequest.read(r)
case w: Write => dBRequest.write(w)
}
}
}
class DBRequest {
def read(r: Read): Future[Read] = {
Future(r)
}
def write(w: Write): Future[Write] = {
Future(w)
}
}
read and write method return a Future of type RequestType. If T is bounded and Future is covariant, then why is the compiler failing to conform type of Future[Read] or Future[Write] to Future[T]
Your code will compile with one small change.
def dbrequest[T <: RequestType](t: T): Future[RequestType] = {
So why is it that returning Future[RequestType] works and returning Future[T] doesn't, especially since T is bounded the way it is?
Think of it this way: T is resolved at compile time. With every invocation of dbrequest() the compiler turns T into either Read or Write. The match statement, on the other hand, is resolved at run time. So from the compiler's perspective the match statement returns both Read and Write.
As has been pointed out, you don't really need a type parameter in this code, as presented. The following simplification is equivalent.
def dbrequest(t: RequestType): Future[RequestType] = {
If T is bounded and Future is covariant, then why is the compiler failing to conform type of Future[Read] or Future[Write] to Future[T]
Your code would make sense if T was guaranteed to be Read or Write.
But it could Read with SomeTrait. Or a singleton type (so even making RequestType, Read and Write sealed wouldn't help). Etc. See my answer to Returning subclass of parameterized type in Scala for a solution (just replace Output in that question with Future).

idiomatic way to block async operations

I was looking at some open source scala project. and I saw that some are doing something like :
abstract class Foo{
def create(implicit ex: ExecutionContextExecutor): Seq[ResultSet] = {
Await.result(createAsync(), timeout)
}
def createAsync()(implicit ex: ExecutionContextExecutor): Future[Seq[ResultSet]] = //implementation
... more like those
}
is there any advantage/disadvantage for calling each method with
(implicit ex: ExecutionContextExecutor) parameter rather than passing the ExecutionContextExecutor in the class constructor:
abstract class Foo(implicit ex: ExecutionContextExecutor){
def create(timeout: FiniteDuration): Seq[ResultSet] = {
Await.result(createAsync(), timeout)
}
def createAsync(): Future[Seq[ResultSet]] = //implementation
... more like those
}
is there preferred option ?
The former approach gives you more flexibility as to where the execution of createAsync will be scheduled, since each time you can make a decision as to which ExecutionContext you want to pass in. Question is, do you need that flexibility? I find that most of the times a single ExecutionContext is sufficient, but it is really a matter of case by case analysis.
In general, the first snippet is horrible IMO. Exposing a synchronous wrapper which blocks around an asynchronous operation is usually a sign of a code smell, and code like that doesn't scale well.

How to chain Futures for async database I/O handling?

I recently started developing an Application in Play Scala. Although I have used Play Java for several applications already, I am also new to Scala and Play Scala.
I use DAO pattern to abstract the database interaction. The DAO contains methods for insert, update delete. After reading async and thread-pool related documentation, I figured that making database interaction async was highly important, unless you tweak the Play default thread pool to have many threads.
To ensure that all database calls are handled asynchronously, I made all the call to return a Future instead of a value directly. I have created a separate execution context for the database interactions.
trait Dao[K, V] {
def findById(id: K): Future[Option[V]]
def update(v: V): Future[Boolean]
[...]
}
This has lead to very complex and deeply nested code in actions.
trait UserDao extends Dao[Long, User] {
def existsWithEmail(email: String): Future[Boolean]
def insert(u: User) Future[Boolean]
}
object UserController extends Controller {
def register = Action {
[...]
userDao.existsWithEmail(email).flatMap { exists =>
exits match {
case true =>
userDao.insert(new User("foo", "bar")).map { created =>
created match {
case true => Ok("Created!")
case false => BadRequest("Failed creation")
}
}
case false =>
Future(BadRequest("User exists with same email"))
}
}
}
}
Above is a sample of simplest of actions. Level of nesting gets deeper as I have more database calls involved. Although I figured that some of the nesting can be reduced with the use of for comprehension, I am doubting if my approach itself is fundamentally wrong?
Consider a case where I need to create a user,
a. If none exists already with same email address.
b. If none exists already with same mobile number.
I can create two futures,
f(a) checking if user exists with email.
f(b) checking if user exists with mobile.
I cannot go and insert a new user unless I verify that both conditions evaluate false. I can actually have f(a) and f(b) running in parallel. The parallel execution maybe undesirable in case f(a) evaluates to true, and may work in favor otherwise. Step 3 of creating user depends on both these futures, so I wonder if following is equally good?
trait UserDao extends Dao[Long, User] {
def existsWithEmail(email: String): Boolean
def existsWithMobile(mobile: String): Boolean
def insert(u: User): Unit
}
def register = Action {
implicit val dbExecutionContext = myconcurrent.Context.dbExceutionContext
Future {
if (!userDao.existsWithEmail(email) && !userDao.existsWithMobile(mobile) {
userDao.insert(new User("foo", "bar")
Ok("Created!")
} else {
BadRequest("Already exists!")
}
}
}
Which one is a better approach? Does the approach of using a single Future with multiple calls to database have any downside?
You are correct when you say that a for comprehension can make for less nesting.
To solve the dual-future problem, consider:
existsWithEmail(email).zip(existsWithMobile(mobile)) map {
case (false, false) => // create user
case _ => // already exists
}
If you have a lot of these, you can use Future.sequence( Seq(future1, future2, ...) ) to turn a sequence of futures into a future sequence.
You may want to take a look at more functional idioms for DB access than DAO, e.g., Slick or Anorm. Usually those will compose better and end up being more flexible than DAO.
A side note: it is more efficient to use if/else for a simple true/false test than it is to use match/case, and is the preferred style.
I solved this problem using for comprehension in scala. I added a few implicit type converters to help with error handling.
Initially I did something like,
def someAction = Action.async {
val result =
for {
student <- studentDao.findById(studentId)
if (student.isDefined)
parent <- parentDao.findById(student.get.parentId)
if (parent.isDefined)
address <- addressDao.findById(parent.get.addressId)
if (address.isDefined)
} yield {
// business logic
}
result fallbackTo Future.successful(BadRequest("Something went wrong"))
}
This is how the code was initially structured to counter the dependency between futures. Note that each subsequent future depends on the previous future. Also, each findById is returning a Future[Option[T]] so if within for comprehension is required to handle cases where the methods return None. I used fallbackTo method on the Future to fallback to a BadRequest result if any of the futures evaluated to None (In event of any if condition failing within for comprehension, it returns a failed future) Another issue with above approach was that it would suppress any kind of exception encountered (even exceptions as trivial as NPE) and simply fallback to BadRequest instead, which was very bad.
Above method was able to counter future of options and handle the failed cases, although it was not helpful to figure out exactly which of the futures in the for comprehension had failed. To overcome this limitation, I used implicit type converters.
object FutureUtils {
class FutureProcessingException(msg: String) extends Exception(msg)
class MissingOptionValueException(msg: String) extends FutureProcessingException(msg)
protected final class OptionFutureToOptionValueFuture[T](f: Future[Option[T]]) {
def whenUndefined(error: String)(implicit context: ExecutionContext): Future[T] = {
f.map { value =>
if (value.isDefined) value.get else throw new MissingOptionValueException(error)
}
}
}
import scala.language.implicitConversions
implicit def optionFutureToValueFutureConverter[T](f: Future[Option[T]]) = new OptionFutureToOptionValueFuture(f)
}
The above implicit conversions allowed me to write readable for comprehensions chaining multiple futures.
import FutureUtils._
def someAction = Action.async {
val result =
for {
student <- studentDao.findById(studentId) whenUndefined "Invalid student id"
parent <- parentDao.findById(student.get.parentId) whenUndefined "Invalid parent id"
address <- addressDao.findById(parent.get.addressId) whenUndefined "Invalid address id"
} yield {
// business logic
}
result.recover {
case fpe: FutureProcessingException => BadRequest(fpe.getMessage)
case t: Throwable => InternalServerError
}
}
The above approach ensured that all exceptions caused by missing Option value are handled as a BadRequest with specific message about what exactly failed. All other failures are treated as InternalServerError. You can log the exact exception with stack trace in order to help debug.