Last active
May 25, 2024 10:18
-
-
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/481b49f97bd074e208a7139520c52b299a8d0839
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 NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2) | |
// 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