diff --git a/src/main/scala/com.snowplowanalytics.iglu/client/ClientError.scala b/src/main/scala/com.snowplowanalytics.iglu/client/ClientError.scala index a9466151..60f32aa4 100644 --- a/src/main/scala/com.snowplowanalytics.iglu/client/ClientError.scala +++ b/src/main/scala/com.snowplowanalytics.iglu/client/ClientError.scala @@ -17,14 +17,14 @@ import java.time.Instant import cats.Show import cats.syntax.show._ import cats.syntax.either._ - import io.circe.{Decoder, DecodingFailure, Encoder, Json} import io.circe.syntax._ - import validator.ValidatorError import resolver.LookupHistory import resolver.registries.RegistryError +import scala.collection.immutable.SortedMap + /** Common type for Resolver's and Validator's errors */ sealed trait ClientError extends Product with Serializable { def getMessage: String = @@ -34,7 +34,7 @@ sealed trait ClientError extends Product with Serializable { object ClientError { /** Error happened during schema resolution step */ - final case class ResolutionError(value: Map[String, LookupHistory]) extends ClientError { + final case class ResolutionError(value: SortedMap[String, LookupHistory]) extends ClientError { def isNotFound: Boolean = value.values.flatMap(_.errors).forall(_ == RegistryError.NotFound) } @@ -67,7 +67,7 @@ object ClientError { .downField("lookupHistory") .as[List[RepoLookupHistory]] .map { history => - ResolutionError(history.map(_.toField).toMap) + ResolutionError(SortedMap[String, LookupHistory]() ++ history.map(_.toField).toMap) } case "ValidationError" => cursor diff --git a/src/main/scala/com.snowplowanalytics.iglu/client/resolver/Resolver.scala b/src/main/scala/com.snowplowanalytics.iglu/client/resolver/Resolver.scala index f7cd69b1..946e898e 100644 --- a/src/main/scala/com.snowplowanalytics.iglu/client/resolver/Resolver.scala +++ b/src/main/scala/com.snowplowanalytics.iglu/client/resolver/Resolver.scala @@ -17,13 +17,10 @@ import cats.{Applicative, Id, Monad} import java.time.Instant import scala.concurrent.duration.MILLISECONDS - import cats.data._ import cats.effect.Clock import cats.implicits._ - import io.circe.{Decoder, DecodingFailure, HCursor, Json} - import com.snowplowanalytics.iglu.core.{ SchemaCriterion, SchemaKey, @@ -34,7 +31,6 @@ import com.snowplowanalytics.iglu.core.{ SelfDescribingSchema } import com.snowplowanalytics.iglu.core.circe.CirceIgluCodecs._ - import com.snowplowanalytics.iglu.client.ClientError.ResolutionError import com.snowplowanalytics.iglu.client.resolver.registries.{ Registry, @@ -43,6 +39,8 @@ import com.snowplowanalytics.iglu.client.resolver.registries.{ } import com.snowplowanalytics.iglu.client.resolver.registries.Registry.Get +import scala.collection.immutable.SortedMap + /** Resolves schemas from one or more Iglu schema registries */ final case class Resolver[F[_]](repos: List[Registry], cache: Option[ResolverCache[F]]) { import Resolver._ @@ -295,7 +293,9 @@ object Resolver { private def postProcess[F[_], A](result: Either[LookupFailureMap, A]) = result.leftMap { failure => - ResolutionError(failure.map { case (key, value) => (key.config.name, value) }) + ResolutionError(SortedMap[String, LookupHistory]() ++ failure.map { + case (key, value) => (key.config.name, value) + }) } private def matchConfig[F[_]: Applicative](datum: SelfDescribingData[Json]) = { diff --git a/src/test/scala/com.snowplowanalytics.iglu.client/ClientErrorSpec.scala b/src/test/scala/com.snowplowanalytics.iglu.client/ClientErrorSpec.scala index 5d2c626d..0fac976a 100644 --- a/src/test/scala/com.snowplowanalytics.iglu.client/ClientErrorSpec.scala +++ b/src/test/scala/com.snowplowanalytics.iglu.client/ClientErrorSpec.scala @@ -13,16 +13,15 @@ package com.snowplowanalytics.iglu.client import cats.data.NonEmptyList - import io.circe.syntax._ import io.circe.literal._ - import com.snowplowanalytics.iglu.client.resolver.LookupHistory import com.snowplowanalytics.iglu.client.resolver.registries.RegistryError import com.snowplowanalytics.iglu.client.validator.{ValidatorError, ValidatorReport} - import org.specs2.Specification +import scala.collection.immutable.SortedMap + class ClientErrorSpec extends Specification { def is = s2""" @@ -32,7 +31,7 @@ class ClientErrorSpec extends Specification { def e1 = { val error: ClientError = ClientError.ResolutionError( - Map( + SortedMap( "First repo" -> LookupHistory( Set(RegistryError.NotFound, RegistryError.RepoFailure("Server outage")), 1, diff --git a/src/test/scala/com.snowplowanalytics.iglu.client/resolver/ResolverSpec.scala b/src/test/scala/com.snowplowanalytics.iglu.client/resolver/ResolverSpec.scala index 00f593ad..48f9cc3c 100644 --- a/src/test/scala/com.snowplowanalytics.iglu.client/resolver/ResolverSpec.scala +++ b/src/test/scala/com.snowplowanalytics.iglu.client/resolver/ResolverSpec.scala @@ -15,6 +15,8 @@ package com.snowplowanalytics.iglu.client.resolver import java.time.Instant import java.net.URI +import scala.collection.immutable.SortedMap + // Cats import cats.Id import cats.effect.IO @@ -132,7 +134,7 @@ class ResolverSpec extends Specification with DataTables with ValidatedMatchers val schemaKey = SchemaKey("com.acme.icarus", "wing", "jsonschema", SchemaVer.Full(1, 0, 0)) val expected = ResolutionError( - Map( + SortedMap( "Iglu Client Embedded" -> LookupHistory(Set(RegistryError.NotFound), 1, SpecHelpers.now), "Iglu Test Embedded" -> LookupHistory(Set(RegistryError.NotFound), 1, SpecHelpers.now) )) @@ -151,7 +153,7 @@ class ResolverSpec extends Specification with DataTables with ValidatedMatchers "jsonschema", SchemaVer.Full(1, 0, 0)) val expected = ResolutionError( - Map( + SortedMap( "Iglu Client Embedded" -> LookupHistory(Set(RegistryError.NotFound), 1, SpecHelpers.now), "Iglu Test Embedded" -> LookupHistory( Set(RegistryError.RepoFailure("ParsingFailure: exhausted input")), @@ -312,7 +314,7 @@ class ResolverSpec extends Specification with DataTables with ValidatedMatchers Nil) val expected = ResolutionError( - Map( + SortedMap( "Mock Repo 1" -> LookupHistory(Set(error1, error2), 2, Instant.ofEpochMilli(2008L)), "Mock Repo 2" -> LookupHistory(Set(error3, error4), 2, Instant.ofEpochMilli(2009L)), "Iglu Client Embedded" -> LookupHistory(