Last active
February 3, 2026 20:26
-
-
Save dacr/f293a05776307e94a2084b3c3915d796 to your computer and use it in GitHub Desktop.
ZIO learning - structured services - vertical composition / published by https://github.com/dacr/code-examples-manager #73bc55eb-d065-4fcc-81c0-db0ead534f96/67c613e406230c38bdc8739a1dd58fd9a3456c42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // summary : ZIO learning - structured services - vertical composition | |
| // keywords : scala, zio, learning, services, pure-functional, @testable | |
| // publish : gist | |
| // authors : Rock the JVM | |
| // license : Apache License Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) | |
| // id : 73bc55eb-d065-4fcc-81c0-db0ead534f96 | |
| // created-on : 2021-05-03T18:43:49+02:00 | |
| // managed-by : https://github.com/dacr/code-examples-manager | |
| // run-with : scala-cli $file | |
| // Highly inspired from Structuring Services in Scala with ZIO and ZLayer : https://www.youtube.com/watch?v=PaogLRrYo64 | |
| // And lately updated or Scala3 & ZIO2 | |
| // --------------------- | |
| //> using scala "3.4.2" | |
| //> using dep "dev.zio::zio:2.0.13" | |
| // --------------------- | |
| import zio.* | |
| // ---------------------------------------------------------------------------------------- | |
| case class User(name: String, email: String) | |
| // ---------------------------------------------------------------------------------------- | |
| // This is the classical service pattern used within ZIO, with the standard naming scheme | |
| // Service definition | |
| trait UserEmailer: | |
| def notify(user: User, message: String): Task[Unit] | |
| object UserEmailer: | |
| class UserEmailerImpl() extends UserEmailer: | |
| override def notify(user: User, message: String): Task[Unit] = | |
| ZIO.attempt(println(s"[User emailer] Sending '$message' to ${user.email}'")) | |
| val live: URLayer[Any, UserEmailer] = ZLayer.succeed(UserEmailerImpl()) | |
| // Front-facing API - helper function | |
| def notify(user: User, message: String): RIO[UserEmailer, Unit] = | |
| ZIO.serviceWithZIO(_.notify(user, message)) | |
| // ---------------------------------------------------------------------------------------- | |
| trait UserDb: | |
| def insert(user: User): Task[Unit] | |
| object UserDb: | |
| class UserDbImpl extends UserDb: | |
| override def insert(user: User) = ZIO.attempt( | |
| println(s"[Database] insert into public.user value ('${user.email}')") | |
| ) | |
| val live = ZLayer.succeed(UserDbImpl()) | |
| def insert(user: User): RIO[UserDb, Unit] = | |
| ZIO.serviceWithZIO(_.insert(user)) | |
| // ---------------------------------------------------------------------------------------- | |
| class UserSubscription(notifier: UserEmailer, userDb: UserDb): | |
| def subscribe(user: User): Task[User] = | |
| for | |
| _ <- userDb.insert(user) | |
| _ <- notifier.notify(user, s"Welcome to this site, ${user.email}") | |
| yield user | |
| object UserSubscription: | |
| val live: URLayer[UserEmailer & UserDb, UserSubscription] = ZLayer( | |
| for | |
| userEmailer <- ZIO.service[UserEmailer] | |
| userDb <- ZIO.service[UserDb] | |
| yield UserSubscription(userEmailer, userDb) | |
| ) | |
| // front-facing API | |
| def subscribe(user: User): RIO[UserSubscription, User] = | |
| ZIO.serviceWithZIO(_.subscribe(user)) | |
| // ---------------------------------------------------------------------------------------- | |
| object Encapsulated extends ZIOAppDefault: | |
| val david = User("david", "[email protected]") | |
| val layers = ZLayer.make[UserDb & UserEmailer & UserSubscription]( | |
| UserDb.live, | |
| UserEmailer.live, | |
| UserSubscription.live | |
| ) | |
| val logic = | |
| UserSubscription | |
| .subscribe(david) | |
| .provideLayer(layers) | |
| override def run = logic | |
| Encapsulated.main(Array.empty) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment