From 1ddcdeabf34abb69e4d034c8250e6c5e5fd848e9 Mon Sep 17 00:00:00 2001 From: kyri-petrou <67301607+kyri-petrou@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:47:41 +1100 Subject: [PATCH] Update prelude & minor validator optimizations (#2113) --- build.sbt | 2 +- .../scala/caliban/validation/Validator.scala | 20 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 4d908098ac..90363e3ba6 100644 --- a/build.sbt +++ b/build.sbt @@ -32,7 +32,7 @@ val zqueryVersion = "0.6.0" val zioJsonVersion = "0.6.2" val zioHttpVersion = "3.0.0-RC4" val zioOpenTelemetryVersion = "3.0.0-RC21" -val zioPreludeVersion = "1.0.0-RC22" +val zioPreludeVersion = "1.0.0-RC23" Global / onChangedBuildSource := ReloadOnSourceChanges diff --git a/core/src/main/scala/caliban/validation/Validator.scala b/core/src/main/scala/caliban/validation/Validator.scala index 21006c376b..a12a50fece 100644 --- a/core/src/main/scala/caliban/validation/Validator.scala +++ b/core/src/main/scala/caliban/validation/Validator.scala @@ -270,16 +270,15 @@ object Validator { checkDirectivesUniqueness(op.directives, directiveDefinitions).as(op.operationType match { case OperationType.Query => op.directives.map((_, __DirectiveLocation.QUERY)) case OperationType.Mutation => op.directives.map((_, __DirectiveLocation.MUTATION)) - case OperationType.Subscription => - op.directives.map((_, __DirectiveLocation.SUBSCRIPTION)) + case OperationType.Subscription => op.directives.map((_, __DirectiveLocation.SUBSCRIPTION)) }) ) - fragmentDirectives <- ZPure.foreach(context.fragments.values)(fragment => + fragmentDirectives <- ZPure.foreach(context.fragments.values.toList)(fragment => checkDirectivesUniqueness(fragment.directives, directiveDefinitions) .as(fragment.directives.map((_, __DirectiveLocation.FRAGMENT_DEFINITION))) ) selectionDirectives <- collectDirectives(context.selectionSets, directiveDefinitions) - } yield opDirectives.flatten ++ fragmentDirectives.flatten ++ selectionDirectives + } yield opDirectives.flatten ::: fragmentDirectives.flatten ::: selectionDirectives private def collectDirectives( selectionSet: List[Selection], @@ -368,7 +367,7 @@ object Validator { lazy val validateVariables: QueryValidation = ZPure.serviceWithPure { context => - ZPure.foreachDiscard(context.operations)(op => + validateAll(context.operations)(op => validateAll(op.variableDefinitions.groupBy(_.name)) { case (name, variables) => ZPure.when(variables.length > 1)( failValidation( @@ -1210,10 +1209,15 @@ object Validator { } } - // Pure's implementation doesn't check if the Iterable is empty, and this is causing some performance degradation + /** + * Wrapper around `ZPure.foreachDiscard` optimized for cases where the input is empty or has only one element. + */ private def validateAll[R, A, B]( in: Iterable[A] )(f: A => EReader[R, ValidationError, B]): EReader[R, ValidationError, Unit] = - if (in.isEmpty) zunit - else ZPure.foreachDiscard(in)(f) + in.sizeCompare(1) match { + case -1 => zunit + case 0 => f(in.head).unit + case _ => ZPure.foreachDiscard(in)(f) + } }