Understanding ZLayer: A powerful tool from ZIO

zio
Reading Time: 3 minutes

What is ZIO?

ZIO is a Scala zero-dependency library for asynchronous and concurrent programming. It enables you to create applications that are scalable, resilient and responsive to your business’s demands.

ZIO is built around the ZIO data type. These data types have three parameters and are referred to as ZIO[R, E, A].

R stands for environment type and the effect requires an R-type environment. When this type parameter is set to Any then the effect has no limitations because it can be run with any value or with Unit.

E stands for failure kind with a value of type E then the effect may fail.  This effect can be used with  Throwable or Nothing and Nothing means the effect cannot fail.

A stands for success and the effect will succeed with the type A. If this type is set to Unit then the effect will yield no relevant information. If it is set to Nothing then the effect will run indefinitely or until failure.

You can click here to read more about ZIO and ZIO Datatypes.

ZLayer

A ZLayer[-RIn, +E, +ROut]represents an application layer; each layer in an application can require some services as input RIn and produces some services as output ROut.
Like everything else, ZIO treats services as an effect. As any service may require dependency [RIn] and produces an effect[ROut].
For sake of better understanding we will look into a small application that will help us understand ZLayer.

Understanding ZLayer with Example

The application is simple as it counts the number of words present in the given list of URLs. We will divide the application into two services->

  • This first service is named SourceReader. The service opens the source then reads the content of a file and closes the sources.
  • WordCounter service takes the content of the file and produces a map with words which has the total occurrence of the word.

Here the SourceReader service does not require any resources therefore construction of the service layer is simple. We just need to wrap the constructor of service inside ZLayer.succeed(). ZLayer.succeed() converts instantiation of service to functional effect which return SourceReaderEnv.

WordCounter is different from SourceReader Service as it is dependent on it. Therefore SourceReader availability is important for the construction of WordCounter service. To help us in this we will require ZLayer.fromService(). ZLayer.fromService[SourceReader.Service, WordCounter.Service] makes sure SourceReader is available for the construction of WordCounter.

To build a single service which requires numerous services. We use ZLayer.fromServices() which is similar to ZLayer.fromService().

ZIO.accessM() makes sure to get the instance of service and make methods of services available.

Now the only thing left to make is layers of SourceReader and WordCounter compose each other. Which will return an instance of the WordCounter service with ZIO.live method we created earlier. The construction of wordCounterLayer is also known as vertical composition in ZIO.

ZIO.provideLayer() helps in providing the required layer. It is similar to dependency injection but instead of providing an instance of service. ZLayer wraps the instance and provides the effect of the instance which is lazy and immutable.

You can click here to follow the official documentation for more information on ZIO and ZLayer.

You can also click here for demo application on ZLayer.

Written by 

Mohd Alimuddin is a Software Consultant at Knoldus. He has knowledge of languages like Scala, Python, C#, HTML, CSS, and MySQL. His hobbies include watching anime, movies, having excellent food, and traveling.