choosing your effect
Longevity will wrap the results of all your persistence operations in an “effect”. The effect describes how you would like longevity to handle the blocking nature of database operations. You can choose to use Scala futures, a more functional, IO monad kind of approach, where all side-effects are pushed to the edges of your program, or an entirely synchronous and blocking approach.
We already saw how to use futures in the previous section:
import longevity.context.LongevityContext import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future val context = LongevityContext[Future, DomainModel]()
You need to provide an execution context when creating a
LongevityContext with a
The easiest way to do this is to include
at the top of your file.
For a more functional approach, you can use the cats-effect IO monad:
import cats.effect.IO import longevity.context.LongevityContext import longevity.effect.cats.ioEffect import scala.concurrent.ExecutionContext.Implicits.global val context = LongevityContext[IO, DomainModel]()
IO as an effect also requires an implicit execution context. This execution context is used
for synchronous operations. Blocking operations use a separate execution context, where blocking
threads are spun up as needed to handle the asynchony. In the code example above, we choose a
suitable default execution context for blocking operations. If you wish to explore using your own
blocking execution context, take a look at the API for
longevity.effect.cats.ioEffect. For an explanation
of the reason for using two execution contexts here, please see the “Thread Shifting” section in
this IO monad for cats blog post.
If you want a synchronous persistence API, use
import longevity.context.LongevityContext import longevity.effect.Blocking val context = LongevityContext[Blocking, DomainModel]()
Blocking[A] is equivalent to
A, similar to an
Id monad like
cats.Id. Because of
this, the results of persistence operations are unwrapped.
Many more effects are possible, and we intend to provide support for some of the more common
Task-like classes in the near future. But you can always provide your own. Simply create your own
Effect class by implementing this API, and make your
effect implicitly available when constructing your
Some of the examples in this user manual may assume a
Future effect, but you can always intuit how
things would look with other effects. For instance, if you see a code example like this:
val createResult: Future[PState[User]] = repo.create(user)
You can assume that it would look like this with the
val createResult: IO[PState[User]] = repo.create(user)
Or like this with the
val createResult: PState[User] = repo.create(user)
The longevity demo project has multiple examples using different effects.