From ddf34c115283db8e419d575225529a61fe4a6ebd Mon Sep 17 00:00:00 2001 From: James Earl Douglas Date: Mon, 21 Mar 2022 11:26:15 -0700 Subject: [PATCH] Update ZIO from 2.0.0-RC2 to 2.0.0-RC3 (#594) * Update ZIO from 2.0.0-RC2 to 2.0.0-RC3 This updates ZIO to 2.0.0-RC3, and replaces `ZManaged` with `Scope`. For reference, see: * Don't leak `Scope` in `ZStream`'s `R` `s/ZStream\[Scope/ZStream[Any/g` * Wrap `.use` -> `.flatMap` updates in `ZIO.scoped` This ensures that open resources are closed when the functions return. --- build.sbt | 2 +- .../zio/JsonPackagePlatformSpecific.scala | 4 +-- .../json/JsonDecoderPlatformSpecific.scala | 33 +++++++++++-------- .../json/JsonEncoderPlatformSpecific.scala | 10 +++--- .../json/DecoderPlatformSpecificSpec.scala | 18 +++++----- .../json/EncoderPlatformSpecificSpec.scala | 7 ++-- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/build.sbt b/build.sbt index 0e53ae559..ae5961d1e 100644 --- a/build.sbt +++ b/build.sbt @@ -35,7 +35,7 @@ addCommandAlias( addCommandAlias("testJS", "zioJsonJS/test") -val zioVersion = "2.0.0-RC2" +val zioVersion = "2.0.0-RC3" lazy val root = project .in(file(".")) diff --git a/zio-json/jvm/src/main/scala/zio/JsonPackagePlatformSpecific.scala b/zio-json/jvm/src/main/scala/zio/JsonPackagePlatformSpecific.scala index db42968a3..403b02e6d 100644 --- a/zio-json/jvm/src/main/scala/zio/JsonPackagePlatformSpecific.scala +++ b/zio-json/jvm/src/main/scala/zio/JsonPackagePlatformSpecific.scala @@ -37,12 +37,12 @@ trait JsonPackagePlatformSpecific { readJsonLinesAs(Paths.get(path)) def readJsonLinesAs[A: JsonDecoder](url: URL): ZStream[Any, Throwable, A] = { - val managed = ZManaged + val scoped = ZIO .fromAutoCloseable(ZIO.attempt(url.openStream())) .refineToOrDie[IOException] ZStream - .fromInputStreamManaged(managed) + .fromInputStreamScoped(scoped) .via( ZPipeline.utf8Decode >>> stringToChars >>> diff --git a/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala b/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala index 31bf1b2e9..bfa6163aa 100644 --- a/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala +++ b/zio-json/jvm/src/main/scala/zio/json/JsonDecoderPlatformSpecific.scala @@ -30,10 +30,15 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => final def decodeJsonStreamInput[R]( stream: ZStream[R, Throwable, Byte], charset: Charset = StandardCharsets.UTF_8 - ): ZIO[R, Throwable, A] = - stream.toInputStream - .flatMap(is => ZManaged.fromAutoCloseable(UIO(new java.io.InputStreamReader(is, charset)))) - .use(readAll) + ): ZIO[R with Scope, Throwable, A] = + ZIO.scoped[R] { + stream.toInputStream + .flatMap(is => + ZIO + .fromAutoCloseable(ZIO.succeed(new java.io.InputStreamReader(is, charset))) + .flatMap(readAll) + ) + } /** * Attempts to decode a stream of characters into a single value of type `A`, but may fail with @@ -43,8 +48,8 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => * * @see also [[decodeJsonStreamInput]] */ - final def decodeJsonStream[R](stream: ZStream[R, Throwable, Char]): ZIO[R, Throwable, A] = - stream.toReader.use(readAll) + final def decodeJsonStream[R](stream: ZStream[R, Throwable, Char]): ZIO[R with Scope, Throwable, A] = + ZIO.scoped[R](stream.toReader.flatMap(readAll)) final def decodeJsonPipeline( delimiter: JsonStreamDelimiter = JsonStreamDelimiter.Array @@ -52,12 +57,12 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => ZPipeline.fromPush { for { // format: off - runtime <- ZManaged.runtime[Any] - inQueue <- Queue.unbounded[Take[Nothing, Char]].toManaged - outQueue <- Queue.unbounded[Take[Throwable, A]].toManaged - ended <- Ref.makeManaged(false) - reader <- ZManaged.fromAutoCloseable { - UIO { + runtime <- ZIO.runtime[Any] + inQueue <- Queue.unbounded[Take[Nothing, Char]] + outQueue <- Queue.unbounded[Take[Throwable, A]] + ended <- Ref.make(false) + reader <- ZIO.fromAutoCloseable { + ZIO.succeed { def readPull: Iterator[Chunk[Char]] = runtime.unsafeRun(inQueue.take) .fold( @@ -69,7 +74,7 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => new zio.stream.internal.ZReader(Iterator.empty ++ readPull) } } - jsonReader <- ZManaged.fromAutoCloseable(UIO(new WithRetractReader(reader))) + jsonReader <- ZIO.fromAutoCloseable(ZIO.succeed(new WithRetractReader(reader))) process <- ZIO.attemptBlockingInterrupt { // Exceptions fall through and are pushed into the queue @tailrec def loop(atBeginning: Boolean): Unit = { @@ -131,7 +136,7 @@ trait JsonDecoderPlatformSpecific[A] { self: JsonDecoder[A] => outQueue.offer(Take.fail(t)) } .interruptible - .forkManaged + .forkScoped push = { (is: Option[Chunk[Char]]) => val pollElements: IO[Throwable, Chunk[A]] = outQueue diff --git a/zio-json/jvm/src/main/scala/zio/json/JsonEncoderPlatformSpecific.scala b/zio-json/jvm/src/main/scala/zio/json/JsonEncoderPlatformSpecific.scala index 406d381b7..953c3fb34 100644 --- a/zio-json/jvm/src/main/scala/zio/json/JsonEncoderPlatformSpecific.scala +++ b/zio-json/jvm/src/main/scala/zio/json/JsonEncoderPlatformSpecific.scala @@ -2,7 +2,7 @@ package zio.json import zio.json.internal.WriteWriter import zio.stream._ -import zio.{ Chunk, Ref, ZIO, ZManaged } +import zio.{ Chunk, Ref, ZIO } trait JsonEncoderPlatformSpecific[A] { self: JsonEncoder[A] => @@ -19,9 +19,9 @@ trait JsonEncoderPlatformSpecific[A] { self: JsonEncoder[A] => ): ZPipeline[Any, Throwable, A, Char] = ZPipeline.fromPush { for { - runtime <- ZIO.runtime[Any].toManaged - chunkBuffer <- Ref.makeManaged(Chunk.fromIterable(startWith.toList)) - writer <- ZManaged.fromAutoCloseable { + runtime <- ZIO.runtime[Any] + chunkBuffer <- Ref.make(Chunk.fromIterable(startWith.toList)) + writer <- ZIO.fromAutoCloseable { ZIO.succeed { new java.io.BufferedWriter( new java.io.Writer { @@ -40,7 +40,7 @@ trait JsonEncoderPlatformSpecific[A] { self: JsonEncoder[A] => ) } } - writeWriter <- ZManaged.succeed(new WriteWriter(writer)) + writeWriter <- ZIO.succeed(new WriteWriter(writer)) push = { (is: Option[Chunk[A]]) => val pushChars = chunkBuffer.getAndUpdate(c => if (c.isEmpty) c else Chunk()) diff --git a/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala b/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala index 1527b0d0b..c34574a88 100644 --- a/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala +++ b/zio-json/jvm/src/test/scala-2/zio/json/DecoderPlatformSpecificSpec.scala @@ -16,9 +16,9 @@ import zio.test._ import java.nio.charset.StandardCharsets import java.nio.file.Paths -object DecoderPlatformSpecificSpec extends DefaultRunnableSpec { +object DecoderPlatformSpecificSpec extends ZIOSpecDefault { - def spec: Spec[TestEnvironment, TestFailure[Any], TestSuccess] = + def spec: Spec[TestEnvironment with Scope, TestFailure[Any], TestSuccess] = suite("Decoder")( test("excessively nested structures") { // JVM specific: getResourceAsString not yet supported @@ -91,12 +91,14 @@ object DecoderPlatformSpecificSpec extends DefaultRunnableSpec { // impl is covered by the tests getResourceAsStringM("che-2.geo.json").flatMap { str => - ZManaged.fromAutoCloseable(Task(getResourceAsReader("che-2.geo.json"))).use { reader => - for { - circe <- ZIO.fromEither(circe.parser.decode[GeoJSON](str)) - got <- ZIO.attemptBlocking(JsonDecoder[GeoJSON].unsafeDecode(Nil, reader)) - } yield { - assert(got)(equalTo(circe)) + ZIO.scoped[TestEnvironment] { + ZIO.fromAutoCloseable(ZIO.attempt(getResourceAsReader("che-2.geo.json"))).flatMap { reader => + for { + circe <- ZIO.fromEither(circe.parser.decode[GeoJSON](str)) + got <- ZIO.attemptBlocking(JsonDecoder[GeoJSON].unsafeDecode(Nil, reader)) + } yield { + assert(got)(equalTo(circe)) + } } } } diff --git a/zio-json/jvm/src/test/scala-2/zio/json/EncoderPlatformSpecificSpec.scala b/zio-json/jvm/src/test/scala-2/zio/json/EncoderPlatformSpecificSpec.scala index 3b8bf0761..123bca173 100644 --- a/zio-json/jvm/src/test/scala-2/zio/json/EncoderPlatformSpecificSpec.scala +++ b/zio-json/jvm/src/test/scala-2/zio/json/EncoderPlatformSpecificSpec.scala @@ -6,18 +6,19 @@ import testzio.json.data.geojson.generated._ import testzio.json.data.googlemaps._ import testzio.json.data.twitter._ import zio.Chunk +import zio.Scope import zio.json.ast.Json import zio.stream.ZStream import zio.test.Assertion._ -import zio.test.{ DefaultRunnableSpec, TestEnvironment, assert, _ } +import zio.test.{ ZIOSpecDefault, TestEnvironment, assert, _ } import java.io.IOException import java.nio.file.Files -object EncoderPlatformSpecificSpec extends DefaultRunnableSpec { +object EncoderPlatformSpecificSpec extends ZIOSpecDefault { import testzio.json.DecoderSpec.logEvent._ - def spec: Spec[TestEnvironment, TestFailure[Any], TestSuccess] = + def spec: Spec[TestEnvironment with Scope, TestFailure[Any], TestSuccess] = suite("Encoder")( suite("roundtrip")( testRoundTrip[DistanceMatrix]("google_maps_api_response"),