Search code examples
scalazio

ZIO: apply ZLayers to a Runtime manually (without a bootstrap method)


If I have an instance of a ZIO Runtime, how do I apply ZLayers (such as the new enableAutoBlockingExecutor in ZIO 2.1) to it to get a modified Runtime?

I see that Runtime has a withEnvironment method, but I am not sure how to create a ZEnvironment from ZLayers.

(My application doesn't extend ZIOAppDefault, so I don't have a bootstrap method, or use ZLayers anywhere else. In parts of the system that use ZIO, effects are run manually where needed using runtime.unsafe.run from the Runtime I am attempting to construct.)

private val layerIWantToApply: ZLayer[Any, Nothing, Unit] = Runtime.enableAutoBlockingExecutor

private val runtime: Runtime[ZEnv] = Runtime.default
  .withEnvironment(DefaultServices.live)
  // what to do here?

Solution

  • I didn't test it but I think what you want is Runtime.unsafe.fromLayer:

    val layerIWantToApply: ZLayer[Any, Nothing, Unit] = Runtime.enableAutoBlockingExecutor
        
    val defaultServiesLayer: ZLayer[Any, Nothing, ...] = 
      ZLayer.fromZIOEnvironment(ZIO.succeed(DefaultServices.live))
    
    val allLayers: ZLayer[Any, Nothing, ... with Unit] =
      defaultServiesLayer ++ layerIWantToApply
        
    val runtime: Runtime.Scoped[... with Unit] =
      zio.Unsafe.unsafe { implicit unsafe => Runtime.unsafe.fromLayer(allLayers) }
    

    From the documentation:

    Unsafely creates a Runtime from a ZLayer whose resources will be allocated immediately, and not released until the Runtime is shut down or the end of the application.

    This method is useful for small applications and integrating ZIO with legacy code, but other applications should investigate using ZIO.provide directly in their application entry points.