Search code examples
scalascala-catscats-effectdoobie

Is it okay to use "unsafeRunSync()" in Cats-Effects?


I am using Doobie and in the examples that I found, it uses unsafeRunSync, like:

sql"select name from country"
  .query[String]    // Query0[String]
  .to[List]         // ConnectionIO[List[String]]
  .transact(xa)     // IO[List[String]]
  .unsafeRunSync    // List[String]
  .take(5)          // List[String]
  .foreach(println)

Under the hood, this function is implemented as follows:

final def unsafeRunSync(): A = unsafeRunTimed(Duration.Inf).get

In the docs, I found that "Please note that this function is intended for testing; it should never appear in your mainline production code!". I wonder if it is okay then to use unsafeRunSync in production if it uses this function under the hood?

Also, how do I put a timeout on the execution if not with unsafeRunTimed?


Solution

  • Well, it depends on what exactly you mean by “OK”. I am not aware of any laws restricting the use of the unsafeRunSync method. I also don't think any major religion considers it a sin (though some minor ones certainly might).

    That said, calling unsafeRunSync is not referentially transparent and has all the downsides that come with that. Namely, equational reasoning goes out of the window. It also blocks the calling thread if asynchronous processing is involved at any point (and in ScalaJS it won't work at all in such cases). To me, these are sufficient reasons to avoid using it in production code whenever possible. That said, there are situations where it's not possible. For instance, you sometimes need to implement interfaces that expect side effects to be performed, such as java.io.OutputStream. There's not much you can do in that situation, those signatures are the way they are.

    It is however not necessary to call unsafeRunTimed to perform an action with a timeout. Just use the race method and a Timer.