Search code examples
scalaoption-typeslickscala-catsscala-option

Cats OptionT future not completing


I'm having an issue where my future (wrapped with OptionT) doesn't complete.

When I explicitly await the result withoutn OptionT, I can see the correct output (See logs below Some(2,2)). But in my for comprehension, we never see the "Ids: " logs. and in the Await OptionT println, we never see the output.

Obviously without the Duration.Inf, the futures timeout.

The functionality here is that if the Brand and Country for the Ids provided do not exist, we should fail. If they exist, we can continue to create the link between them.

  def save(brandId: Int, countryId: Int): Future[Option[Int]] = {
    val now = DateTime.now(DateTimeZone.UTC)
    println(s"Await: ${Await.result(getIds(brandId, countryId), Duration.Inf)}")
    println(s"Await OptionT: ${Await.result(OptionT(getIds(brandId, countryId)).map(identity).value, Duration.Inf)}")
    for {
      ids <- OptionT(getIds(brandId, countryId))
      _ = logger.info(s"Ids: $ids")
      brand = BrandCountry(None, ids._2, ids._1, now, "admin", now, "admin")
      _ = logger.info(s"Brand: $brand")
      insertStmt = BrandCountrys.returning(BrandCountrys.map(_.id)) += brand
      _ = logger.info(s"Executing SQL:\n${insertStmt.statements.mkString(";\n")}")
      result <- OptionT.liftF(db.run(insertStmt))
    } yield result
  }.value

  private def getIds(brandId: Int, countryId: Int) = {
    val ids = for {
      bId <- Brands.filter(_.id === brandId).map(_.id)
      cId <- Countries.filter(_.id === countryId).map(_.id)
    } yield (bId, cId)
    logger.info(s"Executing SQL:\n${ids.result.statements.mkString(";\n")}")
    db.run(ids.result.headOption)
  }

The log output here is

[error] c.d.d.v.d.BrandCountrysDao - Executing SQL:
select x2."id", x3."id" from "configurations_v2"."brands" x2, "configurations_v2"."countries" x3 where (x2."id" = 2) and (x3."id" = 2)
Await: Some((2,2))
[error] c.d.d.v.d.BrandCountrysDao - Executing SQL:
select x2."id", x3."id" from "configurations_v2"."brands" x2, "configurations_v2"."countries" x3 where (x2."id" = 2) and (x3."id" = 2)

then it waits forever (Duration.Inf)


Solution

  • The issue here was not related to Cats or OptionT, but rather to the default ExecutionContext provided by scalatest, which was executing the code.