Hallo. Am Vorabend des Starts des Kurses "Scala-Entwickler" haben wir eine nützliche Übersetzung für Sie vorbereitet.
2020 (I, II) , ZIO. 9 . ZIO 1.0, ZIO ZLayer.
, ZIO — . , /, , .
ZIO . 5 , , ZIO. : ZIO assert- TestClock.
1. ,
ZIO , JVM , . , .
(pollLoop
) . , , . , - .
def pollLoop(running: Ref[Boolean],
consumer: Consumer
): UIO[Unit] =
running.get.flatMap {
case true => for {
_ <- pollAndHandle(consumer)
result <- pollLoop(running, consumer)
} yield result
case false => ZIO.unit
}
, for-, , . For- flatMap
, map
. , for- . , — map
— .
def pollLoop(running: Ref[Boolean],
consumer: Consumer
): UIO[Unit] =
running.get.flatMap {
case true =>
pollAndHandle(consumer)
.flatMap(_ => pollLoop(running, consumer))
.map(result => result)
case false => ZIO.unit
}
Greyhound ZIO doWhile
, , . , (pollOnce
), doWhile
:
pollOnce(running, consumer).doWhile(_ == true).forkDaemon
, pollOnce
UIO[boolean]
, , :
def pollOnce(running: Ref[Boolean],
consumer: Consumer
): UIO[Unit] =
running.get.flatMap {
case true => for {
_ <- pollAndHandle(consumer)
} yield true
case false => UIO(false)
}
, - , .
2.
«» «» (. 2 2), , . :
def repeatedlyPublishQuote(stock: Stock) = {
publishQuote(stock).repeat(Schedule.fixed(1.second))
}
def publishQuote(stock: Stock) = {
println(s"getLatestQuote for $stock")
for {
quote <- grpcClient.getLatestQuote(stock)
_ <- sendToWebsocket(quote)
} yield ()
}
ZIO, publishQuote
, repeat repeatedlyPublishQuote
. repeat .
— , ZIO. , - , .
, , , , console.putStrLn
, for-, :
def publishQuote(stock: Stock) = {
val sendQuote = for {
_ <- console.putStrLn(s"getLatestQuote for $stock")
quote <- grpcClient.getLatestQuote(stock)
_ <- sendToWebsocket(quote)
} yield ()
sendQuote.catchAll(_ => UIO.unit)
}
, catchAll for-, . .
3. TestClock assert-
, « », , . consumer
, 1 , , .
- messageHandler
, (assert), . , , .
. specs2, ScalaTest.
TestClock
, ZIO, . TestClock
, .
eventuallyZ
:
def eventuallyZ[T](f: UIO[T])(predicate: T => Boolean): ZIO[Clock, Throwable, Unit] = {
f.repeat(Schedule.spaced(100.milliseconds) && Schedule.doUntil(predicate))
.timeoutFail(new RuntimeException)(4.seconds)
.unit
}
Schedule
ZIO 100 , - 4 .
. eventuallyZ
Clock
, , . Live Clock, , TestClock
, eventuallyZ
TestClock
, , , TestClock.adjust
.
ZIO provideSomeLayer
:
def eventuallyZ[T](f: UIO[T])(predicate: T => Boolean): ZIO[Clock, Throwable, Unit] = {
f.repeat(Schedule.spaced(100.milliseconds) && Schedule.doUntil(predicate))
.timeoutFail(new RuntimeException)(4.seconds)
.provideSomeLayer(Clock.live)
.unit
}
ZIO, eventuallyZ
, Live Clock 100 . , TestClock
.
4. assert- ZIO Test
: ZIO Test. : , :
object NumbersTest extends DefaultRunnableSpec {
override def spec =
testM("positive and even") {
checkAll(Gen.fromIterable(Seq(0, 2, 4, 6))) { number =>
assert(number)(isPositive)
assert(number % 2 == 0)(Assertion.isTrue)
}
}
}
, , , , (, : Gen.anyInt.filter(_ > 0)
). . isEven, assert . , , 0 .
+ positive and even after additionRan 1 test in 660 ms: 1 succeeded, 0 ignored, 0 failed
, assert- &&
:
assert(number)(isPositive) && assert(number % 2 == 0 (Assertion.isTrue)
:
Ran 1 test in 685 ms: 0 succeeded, 0 ignored, 1 failed
- positive and even after addition
Test failed after 1 iteration with input: 0
0 did not satisfy isGreaterThan(0)
5. , Managed#Acquire
(fibers) ZIO — , / , ZIO.
, foreachPar
.
. fork
forkDaemon
( ). , ( ).
, ! ZManaged
acquire
release
( , ), , uninterruptible
:
criticalEffect.uninterruptible
Managed.acquire
, «heart-beat» . Managed.release
( ).
object Server extends zio.ManagedApp {
def sendHeartBeat(): URIO[Console with Clock, Unit] =
console.putStrLn("heart-beat").repeat(Schedule.fixed(1.second)).ignore
override def run(args: List[String]): ZManaged[zio.ZEnv, Nothing, ExitCode] =
Managed
.make(sendHeartBeat().fork)(_.interrupt)
.map(_ => ExitCode(0))
}
, fork , !
, ZIO, :
Managed.make(sendHeartBeat().fork.interruptible)(.interrupt)
:
sendHeartBeat().toManaged.fork
toManaged_
, Managed.make
.
!
:
ZIO, Twitter Medium. - , .