Skip to content

Instantly share code, notes, and snippets.

@guidoschmidt17
Last active November 11, 2022 15:12
Show Gist options
  • Select an option

  • Save guidoschmidt17/83dcf4b536e404ef9ce38459f3a36743 to your computer and use it in GitHub Desktop.

Select an option

Save guidoschmidt17/83dcf4b536e404ef9ce38459f3a36743 to your computer and use it in GitHub Desktop.
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