Reputation: 1518
I am using scanamo to query a dynamodb and all i want to do is check that the db actually exists. I'm not really concerned with the record I get back, just that there were no errors. For the query part I'm using this:
trait DynamoTestTrait extends AbstractDynamoConfig { def test(): Future[List[Either[DynamoReadError, T]]] = ScanamoAsync.exec(client)table.consistently.limit(1).scan())}
that returns the Future List. I want to evaluate the first? item in the list and just return true if it is not a read error.
I thought this would work but it doesn't:
val result = test() match {
case r: DynamoReadError => Future.successful(false)
case r: Registration => Future.successful(true)
}
I'm new to scala so struggling with return types and things. This is a Play api call so i need to evaluate that boolen future at some point. With something like this:
def health = Action {
val isHealthy = h.testDynamo()
val b: Boolean = Await.result(isHealthy, scala.concurrent.duration.Duration(5, "seconds"))
Ok(Json.toJson(TestResponse(b.toString)))
}
I think this is probably wrong also as i don't want to use Await but i can't get async to work either. Sorry, i'm kind of lost.
When i try to evaluate result i only get a message about the Future:
{
"status": 500,
"message": "Future(<not completed>) (of class scala.concurrent.impl.Promise$DefaultPromise)"
}
Upvotes: 0
Views: 395
Reputation: 27356
The result is a Future
so you can't test the result without doing something like Await.result
(as you do later). What you can do is modify the result returned by the Future
to be the result you need.
In your case you can do this:
test().map(_.headOption.forall(_.isRight))
This will return Future[Boolean]
which you can then use in your Await.result
call.
Here is how it works:
map
calls a function on the result of the Future
, which is type List[Either[DynamoReadError, T]]
and returns a new Future
that gives the result of that function call.
_.headOption
takes the head of the list and returns an Option[Either[DynamoReadError, T]]
. This is Some(...)
if there are one or more elements in the list, or None
if the list is empty.
forall
checks the contents of the Option
and returns the result of the test on that option. If the Option
is None
then it returns true
.
_.isRight
tests the value Either[...]
and returns true
if the value is Right[...]
and false
if it is Left[...]
.
This does what you specified, but perhaps it would be better to check if any of the results failed, rather than just the first one? If so, it is actually a bit simpler:
test().map(_.forall(_.isRight))
This checks that all the entries in the List
are Right
, and fails as soon as a Left
is found.
The problem with returning this from Play
is a separate issue and should probably be in a separate question.
Upvotes: 2