0

I have a service that makes use of the Scala Async library. I'm using this library primarily to time my database calls. The method that I want to test contains multiple calls to the database using the async await mechanism. A pseudo code of what I have is as below:

def myDbMethod() = async {
  val firstCall = await(call the db and get the result)

  val secondCall = await(all the db and get the result)

  val thirdCall = await(all the db and get the result)
  ...
}

In my Scala test unit test, I have

Await.result(myDbMethod(), 10.seconds)

I was just trying to debug myMethod by running my unit test which would return with a test success even before getting into the secondCall. I mean I had breakpoints in all the 3 calls to the database, but the IntelliJ debugger would just exit out as soon as it finishes the first call to the database. Why is this? How can I test this behaviour using IntelliJ debugger?

joesan
  • 13,963
  • 27
  • 95
  • 232

2 Answers2

2

I'm not sure that my answer would suffice your expectations, but it's a known issue. The problem is that async/await is quite a complicated macro, which does heavy transformations on the trees (you can check the output by enabling -Xprint:<phase_name_after_typer> flag). Unfortunately neither of existing IDEs (I'm working with Intellij and Ensime) can debug it, but I'm not familiar with their internals to explain why they can't in details.

From my experience I couldn't find any neat pros over the native for-comprehension, so you can stick with th native syntax or explicit flatmap calls, which is nicely debuggable.

4lex1v
  • 21,367
  • 6
  • 52
  • 86
  • Did I shoot myself in my leg trying to use the async / await library? Damn. I need to find some way to test it! – joesan Sep 25 '15 at 11:23
  • @sparkr you can test them in a usual way with `Await` or with scalatest `whenReady` calls, but not debug. Also note, that in your snippet futures won't run in parallel, read the last example [here](https://github.com/scala/async#what-is-async) – 4lex1v Sep 25 '15 at 11:26
  • Each of those calls returns a Future. Why do you think that it will not run in parallel? – joesan Sep 25 '15 at 11:54
  • @sparkr it's the same as if you would write it with for-comprehension. Please check [this](http://stackoverflow.com/questions/19045936/scalas-for-comprehension-with-futures/19046133#19046133) and [this](https://github.com/dosht/scala-async-experiment). In order to run it in parallel you need to have a future in your variable and await on the result. – 4lex1v Sep 25 '15 at 11:59
0

This construct could be used for depdendant asynchronous calls. async / await adds some sugar to make that easier, but to formalate that by hand you can do it like this:

def dbMethodDependant : Future[T] = for {
  res1 <- firstCall
  res2 <- secondCall(res2)
  res3 <- thirdCall(res3)
} yield res3

Await.result(dbMethodDependant, forever)
Andreas Neumann
  • 10,734
  • 1
  • 32
  • 52