Last active
November 11, 2022 15:12
-
-
Save guidoschmidt17/83dcf4b536e404ef9ce38459f3a36743 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
| package cqrs | |
| package domain | |
| package fx | |
| package mastermanagement | |
| import zio.prelude.* | |
| import zio.prelude.fx.* | |
| import eventstore.* | |
| import eventstore.Event.* | |
| import domain.mastermanagement.* | |
| case class SimpleMaster(id: Uuid, name: String, description: String) | |
| trait ItemInstance: | |
| val master: SimpleMaster | |
| val items: Int | |
| def changeName(name: String): ItemInstance | |
| case class ItemInstanceImpl(master: SimpleMaster, items: Int = 0) extends ItemInstance: | |
| def changeName(name: String) = | |
| copy(master = master.copy(name = name)) | |
| object Dsl: | |
| type Program[+A] = ZPure[Evt, S, S, Env, Err, A] | |
| type Env = MasterEnv | |
| case class MasterEnv(maxItems: Int, config: Option[String] = None) | |
| type S = ItemInstance | |
| type Evt = Event | |
| type Err = EventstoreError | |
| inline def pure[A](a: A): Program[A] = | |
| ZPure.succeed(a) | |
| inline def raiseError[E <: Err](t: => E): Program[Nothing] = | |
| ZPure.fail(t) | |
| inline def assertThat[E <: Err](cond: => Boolean, t: => E): Program[Unit] = | |
| if cond then ZPure.unit else raiseError(t) | |
| inline def extractOption[A, E <: EventstoreError](a: Option[A], t: => E): Program[A] = | |
| a match | |
| case Some(value) => pure(value) | |
| case None => raiseError(t) | |
| inline def get: Program[S] = | |
| ZPure.get[S] | |
| @Deprecated("use update instead") | |
| inline def set(s: S): Program[Unit] = | |
| EState.set(s) | |
| inline def update(f: S => S) = | |
| EState.update[S, S](f) | |
| inline def inspect[A](f: S => A): Program[A] = | |
| get.map(f(_)) | |
| inline def inquire[A](f: Env => A): Program[A] = | |
| ZPure.service[S, Env].map(f(_)) | |
| inline def liftEvent(evt: Evt)(using t: Transition[S]): Program[Unit] = | |
| t.run(evt) *> ZPure.log(evt) | |
| trait Transition[S2]: | |
| def run(evt: Evt): Program[Unit] | |
| given ItemInstanceT: Transition[S] with | |
| def run(evt: Evt) = | |
| evt match | |
| case AggregateCreated(_, _) => update(_.changeName(s"aggregated")) | |
| case RemovedProperty(_, property) => update(_.changeName(s"removed $property")) | |
| case Deleted(id) => update(_.changeName(s"deleted $id")) | |
| case Master.ChangedName(_, name) => update(_.changeName(name)) | |
| case _ => raiseError(RegistrationError(s"not handled ${evt.getClass}")) | |
| def inquireMaxItems: Program[Int] = | |
| inquire(_.maxItems) | |
| def inquireConfig: Program[String] = | |
| inquire(_.config).flatMap(extractOption(_, RegistrationError("No config found"))) | |
| var pureCounter = 0 | |
| var homeCounter = 0 | |
| lazy val testDsl: Program[Unit] = | |
| for | |
| _ <- liftEvent(AggregateCreated(Identified.empty, Identified.empty)) | |
| _ <- liftEvent(RemovedProperty(Identified.empty, "field1")) | |
| _ <- liftEvent(Deleted(Identified.empty)) | |
| yield pureCounter += 1 | |
| lazy val testAllDsl: Program[Unit] = | |
| for | |
| config <- inquireConfig | |
| maxItems <- inquireMaxItems | |
| items <- inspect(_.items) | |
| _ <- assertThat(items < maxItems, RegistrationError(s"maxItems reached : $items >= $maxItems")) | |
| _ <- liftEvent(AggregateCreated(Identified.empty, Identified.empty)) | |
| _ <- liftEvent(RemovedProperty(Identified.empty, "field1")) | |
| _ <- liftEvent(Deleted(Identified.empty)) | |
| master <- inspect(_.master) | |
| name <- inspect(_.master.name) | |
| yield | |
| println(s"inquire $config $maxItems") | |
| println(s"inspect $master name $name") | |
| end Dsl | |
| import Dsl.* | |
| import zio.* | |
| object TestZPure extends ZIOAppDefault: | |
| val repeatsingletests = 9999999 | |
| val repeatalltests = 9 | |
| val monitoring = true | |
| val run = for | |
| _ <- ZIO.sleep(15.seconds).when(monitoring) | |
| env = ZEnvironment(MasterEnv(20, Some("this is my config"))) | |
| _ <- ZIO.debug(s"testAllDsl") | |
| result <- ZIO.succeed { | |
| val s1 = ItemInstanceImpl(SimpleMaster(Uuid.randomUuid, "name", "description"), 21) | |
| testAllDsl.provideEnvironment(env).runAll(s1) // will fail with 'maxItems reached' | |
| } | |
| _ <- ZIO.debug(s"result testAllDsl $result") | |
| _ <- (for | |
| _ <- ZIO.debug(s"testing ZPure") | |
| result <- ZIO | |
| .succeed { | |
| val test = testDsl.provideEnvironment(env) | |
| val s1 = ItemInstanceImpl(SimpleMaster(Uuid.randomUuid, "name", "description")) | |
| test.runAll(s1) | |
| } | |
| .repeatN(repeatsingletests) | |
| .measured("with ZPure ") | |
| _ <- ZIO.debug(s"result ZPure : $pureCounter $result") | |
| _ <- ZIO.debug(s"testing homegrown Dsl") | |
| (ii, _) <- Master("name", "description") | |
| result <- (for | |
| (ii, _) <- ii.master.changeName("this is a new name") | |
| (ii, _) <- ii.master.changeName("this is a new description") | |
| (ii, e) <- ii.master.changeName("deleted") | |
| yield | |
| homeCounter += 1 | |
| e | |
| ) | |
| .repeatN(repeatsingletests) | |
| .measured("with homegrown ") | |
| _ <- ZIO.debug(s"result homegrown : $homeCounter $result") | |
| yield ()) | |
| .repeatN(repeatalltests) | |
| .measured("all tests") | |
| _ <- ZIO.sleep(2.minutes).when(monitoring) | |
| yield () |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment