Created
May 31, 2020 18:21
-
-
Save iamanandkris/87deef653ba51582a7de2a06d19fc1af to your computer and use it in GitHub Desktop.
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
import zio.{Has, Layer, Ref, Task, ZIO, ZLayer} | |
import zio._ | |
import zio.console._ | |
object ZIOInsteadOfFreeRewrite extends App { | |
type UserID = String | |
case class UserProfile(name: String) | |
//Base trait for all the operations that are to be recorded when running test | |
trait Operation | |
//The TestState | |
final case class ExecutedInstructions(ops: List[Operation]) | |
type DatabaseService = Has[Database.Service] | |
type LoggerService = Has[Logger.Service] | |
object Database { | |
//Service | |
trait Service { | |
def lookup(id: UserID): Task[UserProfile] | |
def update(id: UserID, profile: UserProfile): Task[Unit] | |
} | |
def testService(ref: Ref[ExecutedInstructions]): Layer[Nothing, DatabaseService] = ZLayer.succeed(DatabaseTestService(ref)) | |
//def live(ref: Ref[ExecutedInstructions]): Layer[Nothing, DatabaseService] = ZLayer.succeed(DatabaseTestService(ref)) | |
} | |
object Logger { | |
trait Service { | |
def info(id: String): Task[Unit] | |
} | |
def testService(ref: Ref[ExecutedInstructions]): Layer[Nothing, LoggerService] = ZLayer.succeed(LoggerTestService(ref)) | |
//def live(ref: Ref[ExecutedInstructions]): Layer[Nothing, LoggerService] = ZLayer.succeed(LoggerTestService(ref)) | |
} | |
// A concurrent-safe test logger service, which uses a `Ref` to keep track | |
// of changes to the instruction set: | |
case class LoggerTestService(ref: Ref[ExecutedInstructions]) extends Logger.Service { | |
def info(line: String): Task[Unit] = | |
ref.update(x => x.copy(ops = x.ops :+ LoggerTestService.MessageLogged(line))).map(x => ()) | |
} | |
object LoggerTestService { | |
trait LoggerOperation extends Operation | |
case class MessageLogged(message: String) extends LoggerOperation | |
} | |
//Test Service Implementation | |
case class DatabaseTestService(ref: Ref[ExecutedInstructions]) extends Database.Service{ | |
private var map: Map[UserID, UserProfile] = Map("abc" -> UserProfile("testName")) | |
def lookup(id: UserID): Task[UserProfile] = | |
ref.update(x => x.copy(ops = x.ops :+ DatabaseTestService.UserLookedUp(id))).map(x => map(id)) | |
def update(id: UserID, profile: UserProfile): Task[Unit] = | |
ref.update(x => x.copy(ops = x.ops :+ DatabaseTestService.UserUpdated(id, profile))).map(x => map = map + (id -> profile)) | |
} | |
object DatabaseTestService { | |
// database operations performed against the database: | |
trait DatabaseOperation extends Operation | |
case class UserUpdated(id: UserID, profile: UserProfile) extends DatabaseOperation | |
case class UserLookedUp(id: UserID) extends DatabaseOperation | |
} | |
val function = for { | |
profile <- database.lookup("abc") | |
_ <- logger.info(profile.name) | |
} yield profile | |
override def run(args: List[String]): ZIO[zio.ZEnv, Nothing, ExitCode] = { | |
(for { | |
instructionRef <- Ref.make(ExecutedInstructions(Nil)) | |
res <- function.provideCustomLayer(Database.testService(instructionRef) ++ Logger.testService(instructionRef)) | |
_ <- putStrLn(res.toString) | |
}yield res).map(x => ExitCode.success).orDie | |
} | |
} | |
import ZIOInsteadOfFreeRewrite._ | |
package object database { | |
def lookup(id: UserID) = ZIO.accessM[DatabaseService](_.get.lookup(id)) | |
def update(id: UserID, profile: UserProfile) = | |
ZIO.accessM[DatabaseService](_.get.update(id, profile)) | |
} | |
package object logger { | |
def info(message: String) = ZIO.accessM[LoggerService](_.get.info(message)) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment