Skip to content

Instantly share code, notes, and snippets.

@err0r500
Last active February 24, 2023 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save err0r500/caed5c5c4b6103936dfc1c34c67c3d77 to your computer and use it in GitHub Desktop.
Save err0r500/caed5c5c4b6103936dfc1c34c67c3d77 to your computer and use it in GitHub Desktop.
import zio.*
import scala.collection.mutable
// TYPES
case class Metadata(
title: String,
description: String,
language: String,
format: String
)
case class Doc(
metadata: Metadata,
content: Array[Byte]
)
//
// metadata repo
//
trait MetadataRepo:
def get: MetadataRepo.Get
def put: MetadataRepo.Put
object MetadataRepo:
type Get = (id: String) => ZIO[Any, Nothing, Option[Metadata]]
type Put = (id: String, metadata: Metadata) => ZIO[Any, Nothing, Unit]
def put(id: String, metadata: Metadata): ZIO[MetadataRepo, Nothing, Unit] =
ZIO.serviceWithZIO[MetadataRepo](_.put(id, metadata))
class MetadataRepoInMem() extends MetadataRepo:
private var metadatas: mutable.Map[String, Metadata] = mutable.Map.empty
def get: MetadataRepo.Get = (id) => ZIO.succeed(metadatas.get(id))
def put: MetadataRepo.Put = (id, metadata) =>
ZIO.succeed(metadatas.put(id, metadata))
object MetadataRepoInMem:
val layer: ZLayer[Any, Nothing, MetadataRepoInMem] =
ZLayer.succeed(new MetadataRepoInMem())
//
// blob storage repo
//
trait BlobStorage:
def get: BlobStorage.Get
def put: BlobStorage.Put
object BlobStorage:
type Get = (id: String) => ZIO[Any, Nothing, Option[Array[Byte]]]
type Put = (id: String, content: Array[Byte]) => ZIO[Any, Nothing, Unit]
class BlobStorageInMem() extends BlobStorage:
var blobs: mutable.Map[String, Array[Byte]] = mutable.Map.empty
def get: BlobStorage.Get = (id) => ZIO.succeed(blobs.get(id))
def put: BlobStorage.Put = (id, content) =>
ZIO.succeed(blobs.put(id, content))
object BlobStorageInMem:
val layer = ZLayer.succeed(new BlobStorageInMem())
//
// doc repo
//
trait DocRepo:
def save: DocRepo.Save
def get: DocRepo.Get
object DocRepo:
type Save = (doc: Doc, id: String) => ZIO[Any, Nothing, Unit]
type Get = (id: String) => ZIO[Any, Nothing, Option[Doc]]
def save(doc: Doc, id: String): ZIO[DocRepo, Nothing, Unit] =
ZIO.serviceWithZIO[DocRepo](_.save(doc, id))
def get(id: String): ZIO[DocRepo, Nothing, Option[Doc]] =
ZIO.serviceWithZIO[DocRepo](_.get(id))
//
// doc repo live
//
sealed trait DocRepoLiveErr extends Exception
case class MetaNotFound(id: String) extends DocRepoLiveErr
case class BlobNotFound(id: String) extends DocRepoLiveErr
case class DocRepoLive(MR: MetadataRepo, BSR: BlobStorage) extends DocRepo:
def save: DocRepo.Save = (doc, id) =>
for
_ <- MR.put(
id,
Metadata(
doc.metadata.title,
doc.metadata.description,
doc.metadata.language,
doc.metadata.format
)
)
_ <- BSR.put(id, doc.content)
yield ()
def get: DocRepo.Get = (id) =>
(for
metadata <- MR
.get(id)
.flatMap(_ match
case Some(m) => ZIO.succeed(m)
case None => ZIO.fail(MetaNotFound(id))
)
blob <- BSR
.get(id)
.flatMap(_ match
case Some(m) => ZIO.succeed(m)
case None => ZIO.fail(BlobNotFound(id))
)
yield Some(Doc(metadata, blob)))
.catchAll(e =>
for _ <- Console.printLine(s"Error $e").catchAll(_ => ZIO.unit)
yield None
)
object DocRepoLive:
val layer: ZLayer[MetadataRepo with BlobStorage, Nothing, DocRepo] =
ZLayer {
for
metadataRepo <- ZIO.service[MetadataRepo]
blobStorage <- ZIO.service[BlobStorage]
yield DocRepoLive(metadataRepo, blobStorage)
}
//
// main
//
object MainApp extends ZIOAppDefault {
val app = for
_ <- DocRepo.save(
Doc(
Metadata("title", "description", "language", "format"),
"content".getBytes()
),
"id"
)
_ <- DocRepo.get("id").flatMap(doc => Console.printLine(doc.toString))
_ <- DocRepo.get("id2")
_ <- MetadataRepo.put(
"id3",
Metadata("title3", "description3", "language3", "format3")
)
_ <- DocRepo.get("id3")
yield ()
def run =
app.provide(
DocRepoLive.layer,
MetadataRepoInMem.layer,
BlobStorageInMem.layer
)
}
// result (console output) :
//
// Some(Doc(Metadata(title,description,language,format),[B@57bb2b43))
// Error MetaNotFound
// Error BlobNotFound
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment