From 7982289590775f843360ec14d38a80787acc18c0 Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Sat, 6 May 2023 13:33:47 +0200 Subject: [PATCH 1/7] Bulk request now returns BulkResponse iinstead of Unit --- .../zio/elasticsearch/HttpExecutorSpec.scala | 8 +- .../zio/elasticsearch/ElasticRequest.scala | 5 +- .../elasticsearch/executor/HttpExecutor.scala | 10 +- .../executor/response/BulkResponse.scala | 174 ++++++++++++++++++ .../HttpElasticExecutorSpec.scala | 21 ++- 5 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala diff --git a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala index 29bc3a673..cc8e70abb 100644 --- a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala +++ b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala @@ -1436,11 +1436,15 @@ object HttpExecutorSpec extends IntegrationSpec { firstDocumentId, Script("ctx._source.intField = params['factor']").withParams("factor" -> 100) ) - res <- Executor.execute(ElasticRequest.bulk(req1, req2, req3, req4, req5, req6).refreshTrue) + req7 = ElasticRequest.update[TestDocument](index, DocumentId("invalid-document-id"), document.copy(intField = 100)) + res <- Executor.execute(ElasticRequest.bulk(req1, req2, req3, req4, req5, req6, req7).refreshTrue) doc1 <- Executor.execute(ElasticRequest.getById(index, firstDocumentId)).documentAs[TestDocument] doc2 <- Executor.execute(ElasticRequest.getById(index, secondDocumentId)).documentAs[TestDocument] doc3 <- Executor.execute(ElasticRequest.getById(index, thirdDocumentId)).documentAs[TestDocument] - } yield assert(res)(isUnit) && assert(doc3)(isSome(equalTo(document.copy(intField = 100)))) && + } yield assert(res.items.size)(equalTo(7)) && + assert(res.items.map(_.error.isDefined))(equalTo(List(false, false, false, false, false, false, true))) && + assert(res.items(6).error.map(_. `type`))(equalTo(Some("document_missing_exception"))) && + assert(doc3)(isSome(equalTo(document.copy(intField = 100)))) && assert(doc2)(isNone) && assert(doc1)( isSome(equalTo(document.copy(doubleField = 3000, intField = 100))) ) diff --git a/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala b/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala index 4b1083eba..34730c870 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala @@ -35,6 +35,7 @@ import zio.elasticsearch.script.Script import zio.json.ast.Json import zio.json.ast.Json.{Arr, Obj} import zio.schema.Schema +import zio.elasticsearch.executor.response.BulkResponse sealed trait BulkableRequest[A] extends ElasticRequest[A] @@ -361,8 +362,8 @@ object ElasticRequest { private[elasticsearch] final case class Aggregate(index: IndexName, aggregation: ElasticAggregation) extends AggregateRequest - sealed trait BulkRequest extends ElasticRequest[Unit] with HasRefresh[BulkRequest] with HasRouting[BulkRequest] - + sealed trait BulkRequest extends ElasticRequest[BulkResponse] with HasRefresh[BulkRequest] with HasRouting[BulkRequest] + private[elasticsearch] final case class Bulk( requests: List[BulkableRequest[_]], index: Option[IndexName], diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index bf52b548b..9d4e948bd 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -33,6 +33,7 @@ import zio.ZIO.logDebug import zio.elasticsearch.ElasticRequest._ import zio.elasticsearch._ import zio.elasticsearch.executor.response.{ + BulkResponse, CountResponse, CreateResponse, DocumentWithHighlightsAndSort, @@ -42,6 +43,7 @@ import zio.elasticsearch.executor.response.{ } import zio.elasticsearch.request.{CreationOutcome, DeletionOutcome, UpdateOutcome} import zio.elasticsearch.result._ +import zio.json._ import zio.json.ast.Json import zio.json.ast.Json.{Arr, Obj, Str} import zio.json.{DeriveJsonDecoder, JsonDecoder} @@ -126,7 +128,7 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig } } - private def executeBulk(r: Bulk): Task[Unit] = { + private def executeBulk[A](r: Bulk): Task[BulkResponse] = { val uri = (r.index match { case Some(index) => uri"${esConfig.uri}/$index/$Bulk" case None => uri"${esConfig.uri}/$Bulk" @@ -136,12 +138,16 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig baseRequest.post(uri).contentType(ApplicationJson).body(r.body) ).flatMap { response => response.code match { - case HttpOk => ZIO.unit + case HttpOk => ZIO.fromEither(response.body) + .map(body => body.replaceAll(" = ", ":").fromJson[BulkResponse]) + .right.mapError(x => new Exception(s"Error: ${x.toString} with body='${response.body.getOrElse("")}'")) + case _ => ZIO.fail(handleFailures(response)) } } } + private def executeCount(r: Count): Task[Int] = { val req = baseRequest .get(uri"${esConfig.uri}/${r.index}/$Count".withParams(getQueryParams(List(("routing", r.routing))))) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala new file mode 100644 index 000000000..ee2aea6fb --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala @@ -0,0 +1,174 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.executor.response + +import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField} +import zio.json.jsonHint + +// Bulk response format: +// https://www.elastic.co/guide/en/elasticsearch/reference/8.7/docs-bulk.html + +private[elasticsearch] final case class Error( + `type`: String, + reason: String, + @jsonField("index_uuid") + indexUuid: String, + shard: String, + index: String +) + +private[elasticsearch] object Error { + implicit val decoder: JsonDecoder[Error] = DeriveJsonDecoder.gen[Error] +} + +private[elasticsearch] final case class Status( + status: Int, + error: Error +) + +private[elasticsearch] object Status { + implicit val decoder: JsonDecoder[Status] = DeriveJsonDecoder.gen[Status] +} + +private[elasticsearch] final case class ShardsResponse( + total: Int, + successful: Int, + failed: Int +) + +private[elasticsearch] object ShardsResponse { + implicit val decoder: JsonDecoder[ShardsResponse] = DeriveJsonDecoder.gen[ShardsResponse] +} + +private[elasticsearch] sealed trait Item { + def index: String + def id: String + def version: Option[Int] + def result: Option[String] + def shards: Option[ShardsResponse] + def seqNo: Option[Int] + def primaryTerm: Option[Int] + def status: Option[Int] + def error: Option[Error] +} + +@jsonHint("create") +private[elasticsearch] final case class Create( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + @jsonField("_seq_no") + seqNo: Option[Int], + @jsonField("_primary_term") + primaryTerm: Option[Int], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Create { + implicit val decoder: JsonDecoder[Create] = DeriveJsonDecoder.gen[Create] +} + +@jsonHint("delete") +private[elasticsearch] final case class Delete( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + @jsonField("_seq_no") + seqNo: Option[Int], + @jsonField("_primary_term") + primaryTerm: Option[Int], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Delete { + implicit val decoder: JsonDecoder[Delete] = DeriveJsonDecoder.gen[Delete] +} + +@jsonHint("index") +private[elasticsearch] final case class Index( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + @jsonField("_seq_no") + seqNo: Option[Int], + @jsonField("_primary_term") + primaryTerm: Option[Int], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Index { + implicit val decoder: JsonDecoder[Index] = DeriveJsonDecoder.gen[Index] +} + +@jsonHint("update") +private[elasticsearch] final case class Update( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + @jsonField("_seq_no") + seqNo: Option[Int], + @jsonField("_primary_term") + primaryTerm: Option[Int], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Update { + implicit val decoder: JsonDecoder[Update] = DeriveJsonDecoder.gen[Update] +} + +private[elasticsearch] object Item { + implicit val decoder: JsonDecoder[Item] = DeriveJsonDecoder.gen[Item] +} + +private[elasticsearch] final case class BulkResponse( + took: Int, + errors: Boolean, + items: List[Item] +) + +private[elasticsearch] object BulkResponse { + implicit val decoder: JsonDecoder[BulkResponse] = DeriveJsonDecoder.gen[BulkResponse] +} + diff --git a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala index 8c6e4073e..3eb253b61 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala @@ -20,7 +20,7 @@ import zio.elasticsearch.ElasticAggregation.termsAggregation import zio.elasticsearch.ElasticQuery.{matchAll, term} import zio.elasticsearch.domain.TestDocument import zio.elasticsearch.executor.Executor -import zio.elasticsearch.executor.response.{TermsAggregationBucket, TermsAggregationResponse} +import zio.elasticsearch.executor.response.{BulkResponse, Create, ShardsResponse, TermsAggregationBucket, TermsAggregationResponse} import zio.elasticsearch.request.CreationOutcome.Created import zio.elasticsearch.request.DeletionOutcome.Deleted import zio.elasticsearch.request.UpdateConflicts.Proceed @@ -48,7 +48,24 @@ object HttpElasticExecutorSpec extends SttpBackendStubSpec { assertZIO( Executor.execute(ElasticRequest.bulk(ElasticRequest.create(index, doc)).refreshTrue) )( - isUnit + equalTo(BulkResponse( + took = 3, + errors = false, + items = List(Create( + index = "repositories", + id = "123", + version = Some(1), + result = Some("created"), + shards = Some(ShardsResponse( + total = 1, + successful = 1, + failed = 0 + )), + seqNo = Some(0), + primaryTerm = Some(1), + status = Some(201), + error = None + )))) ) }, test("count request") { From 9fc0b1be8c097393b7f0813a520972e4017c171a Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Sat, 6 May 2023 13:51:35 +0200 Subject: [PATCH 2/7] Clarify bulk response error code --- .../zio/elasticsearch/executor/HttpExecutor.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index 9d4e948bd..8751a26ea 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -138,10 +138,13 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig baseRequest.post(uri).contentType(ApplicationJson).body(r.body) ).flatMap { response => response.code match { - case HttpOk => ZIO.fromEither(response.body) - .map(body => body.replaceAll(" = ", ":").fromJson[BulkResponse]) - .right.mapError(x => new Exception(s"Error: ${x.toString} with body='${response.body.getOrElse("")}'")) - + case HttpOk => response.body match { + case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body empty: ${error}")) + case Right(body) => body.replaceAll(" = ", ":").fromJson[BulkResponse] match { + case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body invalid: ${error}")) + case Right(response) => ZIO.succeed(response) + } + } case _ => ZIO.fail(handleFailures(response)) } } From fcb8649640c1312d464b23d4e4509a2c64dd7c3d Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Sat, 6 May 2023 16:57:30 +0200 Subject: [PATCH 3/7] apply scalafmt --- .../zio/elasticsearch/HttpExecutorSpec.scala | 10 ++-- .../zio/elasticsearch/ElasticRequest.scala | 9 ++-- .../elasticsearch/executor/HttpExecutor.scala | 20 ++++---- .../executor/response/BulkResponse.scala | 4 +- .../HttpElasticExecutorSpec.scala | 51 ++++++++++++------- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala index cc8e70abb..71b55dab1 100644 --- a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala +++ b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala @@ -1436,14 +1436,18 @@ object HttpExecutorSpec extends IntegrationSpec { firstDocumentId, Script("ctx._source.intField = params['factor']").withParams("factor" -> 100) ) - req7 = ElasticRequest.update[TestDocument](index, DocumentId("invalid-document-id"), document.copy(intField = 100)) + req7 = + ElasticRequest + .update[TestDocument](index, DocumentId("invalid-document-id"), document.copy(intField = 100)) res <- Executor.execute(ElasticRequest.bulk(req1, req2, req3, req4, req5, req6, req7).refreshTrue) doc1 <- Executor.execute(ElasticRequest.getById(index, firstDocumentId)).documentAs[TestDocument] doc2 <- Executor.execute(ElasticRequest.getById(index, secondDocumentId)).documentAs[TestDocument] doc3 <- Executor.execute(ElasticRequest.getById(index, thirdDocumentId)).documentAs[TestDocument] } yield assert(res.items.size)(equalTo(7)) && - assert(res.items.map(_.error.isDefined))(equalTo(List(false, false, false, false, false, false, true))) && - assert(res.items(6).error.map(_. `type`))(equalTo(Some("document_missing_exception"))) && + assert(res.items.map(_.error.isDefined))( + equalTo(List(false, false, false, false, false, false, true)) + ) && + assert(res.items(6).error.map(_.`type`))(equalTo(Some("document_missing_exception"))) && assert(doc3)(isSome(equalTo(document.copy(intField = 100)))) && assert(doc2)(isNone) && assert(doc1)( isSome(equalTo(document.copy(doubleField = 3000, intField = 100))) diff --git a/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala b/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala index 34730c870..1f8832a8d 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/ElasticRequest.scala @@ -19,6 +19,7 @@ package zio.elasticsearch import zio.Chunk import zio.elasticsearch.ElasticPrimitive.ElasticPrimitiveOps import zio.elasticsearch.aggregation.ElasticAggregation +import zio.elasticsearch.executor.response.BulkResponse import zio.elasticsearch.highlights.Highlights import zio.elasticsearch.query.ElasticQuery import zio.elasticsearch.query.sort.Sort @@ -35,7 +36,6 @@ import zio.elasticsearch.script.Script import zio.json.ast.Json import zio.json.ast.Json.{Arr, Obj} import zio.schema.Schema -import zio.elasticsearch.executor.response.BulkResponse sealed trait BulkableRequest[A] extends ElasticRequest[A] @@ -362,8 +362,11 @@ object ElasticRequest { private[elasticsearch] final case class Aggregate(index: IndexName, aggregation: ElasticAggregation) extends AggregateRequest - sealed trait BulkRequest extends ElasticRequest[BulkResponse] with HasRefresh[BulkRequest] with HasRouting[BulkRequest] - + sealed trait BulkRequest + extends ElasticRequest[BulkResponse] + with HasRefresh[BulkRequest] + with HasRouting[BulkRequest] + private[elasticsearch] final case class Bulk( requests: List[BulkableRequest[_]], index: Option[IndexName], diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index 8751a26ea..110802bd8 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -43,10 +43,9 @@ import zio.elasticsearch.executor.response.{ } import zio.elasticsearch.request.{CreationOutcome, DeletionOutcome, UpdateOutcome} import zio.elasticsearch.result._ -import zio.json._ import zio.json.ast.Json import zio.json.ast.Json.{Arr, Obj, Str} -import zio.json.{DeriveJsonDecoder, JsonDecoder} +import zio.json.{DeriveJsonDecoder, JsonDecoder, _} import zio.schema.Schema import zio.stream.{Stream, ZStream} import zio.{Chunk, Task, ZIO} @@ -138,19 +137,20 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig baseRequest.post(uri).contentType(ApplicationJson).body(r.body) ).flatMap { response => response.code match { - case HttpOk => response.body match { - case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body empty: ${error}")) - case Right(body) => body.replaceAll(" = ", ":").fromJson[BulkResponse] match { - case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body invalid: ${error}")) - case Right(response) => ZIO.succeed(response) + case HttpOk => + response.body match { + case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body empty: ${error}")) + case Right(body) => + body.replaceAll(" = ", ":").fromJson[BulkResponse] match { + case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body invalid: ${error}")) + case Right(response) => ZIO.succeed(response) + } } - } - case _ => ZIO.fail(handleFailures(response)) + case _ => ZIO.fail(handleFailures(response)) } } } - private def executeCount(r: Count): Task[Int] = { val req = baseRequest .get(uri"${esConfig.uri}/${r.index}/$Count".withParams(getQueryParams(List(("routing", r.routing))))) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala index ee2aea6fb..ad724cc9c 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala @@ -16,8 +16,7 @@ package zio.elasticsearch.executor.response -import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField} -import zio.json.jsonHint +import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField, jsonHint} // Bulk response format: // https://www.elastic.co/guide/en/elasticsearch/reference/8.7/docs-bulk.html @@ -171,4 +170,3 @@ private[elasticsearch] final case class BulkResponse( private[elasticsearch] object BulkResponse { implicit val decoder: JsonDecoder[BulkResponse] = DeriveJsonDecoder.gen[BulkResponse] } - diff --git a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala index 3eb253b61..4adc1df22 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala @@ -20,7 +20,13 @@ import zio.elasticsearch.ElasticAggregation.termsAggregation import zio.elasticsearch.ElasticQuery.{matchAll, term} import zio.elasticsearch.domain.TestDocument import zio.elasticsearch.executor.Executor -import zio.elasticsearch.executor.response.{BulkResponse, Create, ShardsResponse, TermsAggregationBucket, TermsAggregationResponse} +import zio.elasticsearch.executor.response.{ + BulkResponse, + Create, + ShardsResponse, + TermsAggregationBucket, + TermsAggregationResponse +} import zio.elasticsearch.request.CreationOutcome.Created import zio.elasticsearch.request.DeletionOutcome.Deleted import zio.elasticsearch.request.UpdateConflicts.Proceed @@ -48,24 +54,31 @@ object HttpElasticExecutorSpec extends SttpBackendStubSpec { assertZIO( Executor.execute(ElasticRequest.bulk(ElasticRequest.create(index, doc)).refreshTrue) )( - equalTo(BulkResponse( - took = 3, - errors = false, - items = List(Create( - index = "repositories", - id = "123", - version = Some(1), - result = Some("created"), - shards = Some(ShardsResponse( - total = 1, - successful = 1, - failed = 0 - )), - seqNo = Some(0), - primaryTerm = Some(1), - status = Some(201), - error = None - )))) + equalTo( + BulkResponse( + took = 3, + errors = false, + items = List( + Create( + index = "repositories", + id = "123", + version = Some(1), + result = Some("created"), + shards = Some( + ShardsResponse( + total = 1, + successful = 1, + failed = 0 + ) + ), + seqNo = Some(0), + primaryTerm = Some(1), + status = Some(201), + error = None + ) + ) + ) + ) ) }, test("count request") { From a50333eb1b756b21a3486b0b73de35dba74f1b94 Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Mon, 8 May 2023 01:57:04 +0200 Subject: [PATCH 4/7] Fix remaining issues --- .../elasticsearch/executor/HttpExecutor.scala | 25 ++++++------ .../executor/response/BulkResponse.scala | 39 +++++-------------- .../HttpElasticExecutorSpec.scala | 2 - .../elasticsearch/SttpBackendStubSpec.scala | 6 +-- 4 files changed, 23 insertions(+), 49 deletions(-) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index 110802bd8..3a18df668 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -45,7 +45,7 @@ import zio.elasticsearch.request.{CreationOutcome, DeletionOutcome, UpdateOutcom import zio.elasticsearch.result._ import zio.json.ast.Json import zio.json.ast.Json.{Arr, Obj, Str} -import zio.json.{DeriveJsonDecoder, JsonDecoder, _} +import zio.json.{DeriveJsonDecoder, JsonDecoder} import zio.schema.Schema import zio.stream.{Stream, ZStream} import zio.{Chunk, Task, ZIO} @@ -133,24 +133,21 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig case None => uri"${esConfig.uri}/$Bulk" }).withParams(getQueryParams(List(("refresh", r.refresh), ("routing", r.routing)))) - sendRequest( - baseRequest.post(uri).contentType(ApplicationJson).body(r.body) + sendRequestWithCustomResponse( + baseRequest.post(uri).contentType(ApplicationJson) + .body(r.body).response(asJson[BulkResponse]) ).flatMap { response => response.code match { case HttpOk => - response.body match { - case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body empty: ${error}")) - case Right(body) => - body.replaceAll(" = ", ":").fromJson[BulkResponse] match { - case Left(error) => ZIO.fail(new ElasticException(s"Bulk response body invalid: ${error}")) - case Right(response) => ZIO.succeed(response) - } - } - case _ => ZIO.fail(handleFailures(response)) + response.body.fold( + e => ZIO.fail(new ElasticException(s"Exception occurred: ${e.getMessage}")), + value => ZIO.succeed(value) + ) + case _ => ZIO.fail(handleFailuresFromCustomResponse(response)) } } } - + private def executeCount(r: Count): Task[Int] = { val req = baseRequest .get(uri"${esConfig.uri}/${r.index}/$Count".withParams(getQueryParams(List(("routing", r.routing))))) @@ -643,6 +640,6 @@ private[elasticsearch] object HttpExecutor { DeriveJsonDecoder.gen[PointInTimeResponse] } - def apply(esConfig: ElasticConfig, client: SttpBackend[Task, Any]) = + def apply(esConfig: ElasticConfig, client: SttpBackend[Task, Any]) = new HttpExecutor(esConfig, client) } diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala index ad724cc9c..07c4c6819 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala @@ -18,10 +18,7 @@ package zio.elasticsearch.executor.response import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField, jsonHint} -// Bulk response format: -// https://www.elastic.co/guide/en/elasticsearch/reference/8.7/docs-bulk.html - -private[elasticsearch] final case class Error( +final case class Error private[elasticsearch]( `type`: String, reason: String, @jsonField("index_uuid") @@ -34,7 +31,7 @@ private[elasticsearch] object Error { implicit val decoder: JsonDecoder[Error] = DeriveJsonDecoder.gen[Error] } -private[elasticsearch] final case class Status( +final case class Status private[elasticsearch]( status: Int, error: Error ) @@ -43,7 +40,7 @@ private[elasticsearch] object Status { implicit val decoder: JsonDecoder[Status] = DeriveJsonDecoder.gen[Status] } -private[elasticsearch] final case class ShardsResponse( +final case class ShardsResponse private[elasticsearch] ( total: Int, successful: Int, failed: Int @@ -53,20 +50,18 @@ private[elasticsearch] object ShardsResponse { implicit val decoder: JsonDecoder[ShardsResponse] = DeriveJsonDecoder.gen[ShardsResponse] } -private[elasticsearch] sealed trait Item { +sealed trait Item { def index: String def id: String def version: Option[Int] def result: Option[String] def shards: Option[ShardsResponse] - def seqNo: Option[Int] - def primaryTerm: Option[Int] def status: Option[Int] def error: Option[Error] } @jsonHint("create") -private[elasticsearch] final case class Create( +final case class Create private[elasticsearch]( @jsonField("_index") index: String, @jsonField("_id") @@ -76,10 +71,6 @@ private[elasticsearch] final case class Create( result: Option[String], @jsonField("_shards") shards: Option[ShardsResponse], - @jsonField("_seq_no") - seqNo: Option[Int], - @jsonField("_primary_term") - primaryTerm: Option[Int], status: Option[Int], error: Option[Error] ) extends Item @@ -89,7 +80,7 @@ private[elasticsearch] object Create { } @jsonHint("delete") -private[elasticsearch] final case class Delete( +final case class Delete private[elasticsearch]( @jsonField("_index") index: String, @jsonField("_id") @@ -99,10 +90,6 @@ private[elasticsearch] final case class Delete( result: Option[String], @jsonField("_shards") shards: Option[ShardsResponse], - @jsonField("_seq_no") - seqNo: Option[Int], - @jsonField("_primary_term") - primaryTerm: Option[Int], status: Option[Int], error: Option[Error] ) extends Item @@ -112,7 +99,7 @@ private[elasticsearch] object Delete { } @jsonHint("index") -private[elasticsearch] final case class Index( +final case class Index private[elasticsearch]( @jsonField("_index") index: String, @jsonField("_id") @@ -122,10 +109,6 @@ private[elasticsearch] final case class Index( result: Option[String], @jsonField("_shards") shards: Option[ShardsResponse], - @jsonField("_seq_no") - seqNo: Option[Int], - @jsonField("_primary_term") - primaryTerm: Option[Int], status: Option[Int], error: Option[Error] ) extends Item @@ -135,7 +118,7 @@ private[elasticsearch] object Index { } @jsonHint("update") -private[elasticsearch] final case class Update( +final case class Update private[elasticsearch] ( @jsonField("_index") index: String, @jsonField("_id") @@ -145,10 +128,6 @@ private[elasticsearch] final case class Update( result: Option[String], @jsonField("_shards") shards: Option[ShardsResponse], - @jsonField("_seq_no") - seqNo: Option[Int], - @jsonField("_primary_term") - primaryTerm: Option[Int], status: Option[Int], error: Option[Error] ) extends Item @@ -161,7 +140,7 @@ private[elasticsearch] object Item { implicit val decoder: JsonDecoder[Item] = DeriveJsonDecoder.gen[Item] } -private[elasticsearch] final case class BulkResponse( +final case class BulkResponse private[elasticsearch] ( took: Int, errors: Boolean, items: List[Item] diff --git a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala index 4adc1df22..89b816c89 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala @@ -71,8 +71,6 @@ object HttpElasticExecutorSpec extends SttpBackendStubSpec { failed = 0 ) ), - seqNo = Some(0), - primaryTerm = Some(1), status = Some(201), error = None ) diff --git a/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala index 185963169..052523de5 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/SttpBackendStubSpec.scala @@ -61,9 +61,9 @@ trait SttpBackendStubSpec extends ZIOSpecDefault { response = Response( """ |{ - | "took" = 3, - | "errors" = false, - | "items" = [ + | "took" : 3, + | "errors" : false, + | "items" : [ | { | "create": { | "_index": "repositories", From 4d79267ebee8f43ac5d33d96010b2b5f86ad1f27 Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Mon, 8 May 2023 02:38:45 +0200 Subject: [PATCH 5/7] split BulkResponse into multiple files --- .../executor/response/BulkResponse.scala | 124 +----------------- .../executor/response/Error.scala | 32 +++++ .../executor/response/Item.scala | 109 +++++++++++++++ .../executor/response/ShardsResponse.scala | 29 ++++ .../executor/response/Status.scala | 28 ++++ 5 files changed, 199 insertions(+), 123 deletions(-) create mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala create mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala create mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala create mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala index 07c4c6819..1dcf397dc 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/BulkResponse.scala @@ -16,129 +16,7 @@ package zio.elasticsearch.executor.response -import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField, jsonHint} - -final case class Error private[elasticsearch]( - `type`: String, - reason: String, - @jsonField("index_uuid") - indexUuid: String, - shard: String, - index: String -) - -private[elasticsearch] object Error { - implicit val decoder: JsonDecoder[Error] = DeriveJsonDecoder.gen[Error] -} - -final case class Status private[elasticsearch]( - status: Int, - error: Error -) - -private[elasticsearch] object Status { - implicit val decoder: JsonDecoder[Status] = DeriveJsonDecoder.gen[Status] -} - -final case class ShardsResponse private[elasticsearch] ( - total: Int, - successful: Int, - failed: Int -) - -private[elasticsearch] object ShardsResponse { - implicit val decoder: JsonDecoder[ShardsResponse] = DeriveJsonDecoder.gen[ShardsResponse] -} - -sealed trait Item { - def index: String - def id: String - def version: Option[Int] - def result: Option[String] - def shards: Option[ShardsResponse] - def status: Option[Int] - def error: Option[Error] -} - -@jsonHint("create") -final case class Create private[elasticsearch]( - @jsonField("_index") - index: String, - @jsonField("_id") - id: String, - @jsonField("_version") - version: Option[Int], - result: Option[String], - @jsonField("_shards") - shards: Option[ShardsResponse], - status: Option[Int], - error: Option[Error] -) extends Item - -private[elasticsearch] object Create { - implicit val decoder: JsonDecoder[Create] = DeriveJsonDecoder.gen[Create] -} - -@jsonHint("delete") -final case class Delete private[elasticsearch]( - @jsonField("_index") - index: String, - @jsonField("_id") - id: String, - @jsonField("_version") - version: Option[Int], - result: Option[String], - @jsonField("_shards") - shards: Option[ShardsResponse], - status: Option[Int], - error: Option[Error] -) extends Item - -private[elasticsearch] object Delete { - implicit val decoder: JsonDecoder[Delete] = DeriveJsonDecoder.gen[Delete] -} - -@jsonHint("index") -final case class Index private[elasticsearch]( - @jsonField("_index") - index: String, - @jsonField("_id") - id: String, - @jsonField("_version") - version: Option[Int], - result: Option[String], - @jsonField("_shards") - shards: Option[ShardsResponse], - status: Option[Int], - error: Option[Error] -) extends Item - -private[elasticsearch] object Index { - implicit val decoder: JsonDecoder[Index] = DeriveJsonDecoder.gen[Index] -} - -@jsonHint("update") -final case class Update private[elasticsearch] ( - @jsonField("_index") - index: String, - @jsonField("_id") - id: String, - @jsonField("_version") - version: Option[Int], - result: Option[String], - @jsonField("_shards") - shards: Option[ShardsResponse], - status: Option[Int], - error: Option[Error] -) extends Item - -private[elasticsearch] object Update { - implicit val decoder: JsonDecoder[Update] = DeriveJsonDecoder.gen[Update] -} - -private[elasticsearch] object Item { - implicit val decoder: JsonDecoder[Item] = DeriveJsonDecoder.gen[Item] -} +import zio.json.{DeriveJsonDecoder, JsonDecoder} final case class BulkResponse private[elasticsearch] ( took: Int, diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala new file mode 100644 index 000000000..28415dbd6 --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala @@ -0,0 +1,32 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.executor.response + +import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField} + +final case class Error private[elasticsearch]( + `type`: String, + reason: String, + @jsonField("index_uuid") + indexUuid: String, + shard: String, + index: String +) + +private[elasticsearch] object Error { + implicit val decoder: JsonDecoder[Error] = DeriveJsonDecoder.gen[Error] +} diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala new file mode 100644 index 000000000..917e32dc5 --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala @@ -0,0 +1,109 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.executor.response + +import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField, jsonHint} + +sealed trait Item { + def index: String + def id: String + def version: Option[Int] + def result: Option[String] + def shards: Option[ShardsResponse] + def status: Option[Int] + def error: Option[Error] +} + +@jsonHint("create") +final case class Create private[elasticsearch]( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Create { + implicit val decoder: JsonDecoder[Create] = DeriveJsonDecoder.gen[Create] +} + +@jsonHint("delete") +final case class Delete private[elasticsearch]( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Delete { + implicit val decoder: JsonDecoder[Delete] = DeriveJsonDecoder.gen[Delete] +} + +@jsonHint("index") +final case class Index private[elasticsearch]( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Index { + implicit val decoder: JsonDecoder[Index] = DeriveJsonDecoder.gen[Index] +} + +@jsonHint("update") +final case class Update private[elasticsearch] ( + @jsonField("_index") + index: String, + @jsonField("_id") + id: String, + @jsonField("_version") + version: Option[Int], + result: Option[String], + @jsonField("_shards") + shards: Option[ShardsResponse], + status: Option[Int], + error: Option[Error] +) extends Item + +private[elasticsearch] object Update { + implicit val decoder: JsonDecoder[Update] = DeriveJsonDecoder.gen[Update] +} + +private[elasticsearch] object Item { + implicit val decoder: JsonDecoder[Item] = DeriveJsonDecoder.gen[Item] +} diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala new file mode 100644 index 000000000..6cf0d7e64 --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.executor.response + +import zio.json.{DeriveJsonDecoder, JsonDecoder} + +final case class ShardsResponse private[elasticsearch] ( + total: Int, + successful: Int, + failed: Int +) + +private[elasticsearch] object ShardsResponse { + implicit val decoder: JsonDecoder[ShardsResponse] = DeriveJsonDecoder.gen[ShardsResponse] +} diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala new file mode 100644 index 000000000..fa571bdfb --- /dev/null +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala @@ -0,0 +1,28 @@ +/* + * Copyright 2022 LambdaWorks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zio.elasticsearch.executor.response + +import zio.json.{DeriveJsonDecoder, JsonDecoder} + +final case class Status private[elasticsearch]( + status: Int, + error: Error +) + +private[elasticsearch] object Status { + implicit val decoder: JsonDecoder[Status] = DeriveJsonDecoder.gen[Status] +} From 0e5f69d123a6494421b952ea9a308d81fc38b267 Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Mon, 8 May 2023 02:46:53 +0200 Subject: [PATCH 6/7] scalafmt --- .../zio/elasticsearch/executor/HttpExecutor.scala | 11 +++++++---- .../zio/elasticsearch/executor/response/Error.scala | 2 +- .../zio/elasticsearch/executor/response/Item.scala | 6 +++--- .../zio/elasticsearch/executor/response/Status.scala | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index 3a18df668..bf0330dcb 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -134,8 +134,11 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig }).withParams(getQueryParams(List(("refresh", r.refresh), ("routing", r.routing)))) sendRequestWithCustomResponse( - baseRequest.post(uri).contentType(ApplicationJson) - .body(r.body).response(asJson[BulkResponse]) + baseRequest + .post(uri) + .contentType(ApplicationJson) + .body(r.body) + .response(asJson[BulkResponse]) ).flatMap { response => response.code match { case HttpOk => @@ -147,7 +150,7 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig } } } - + private def executeCount(r: Count): Task[Int] = { val req = baseRequest .get(uri"${esConfig.uri}/${r.index}/$Count".withParams(getQueryParams(List(("routing", r.routing))))) @@ -640,6 +643,6 @@ private[elasticsearch] object HttpExecutor { DeriveJsonDecoder.gen[PointInTimeResponse] } - def apply(esConfig: ElasticConfig, client: SttpBackend[Task, Any]) = + def apply(esConfig: ElasticConfig, client: SttpBackend[Task, Any]) = new HttpExecutor(esConfig, client) } diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala index 28415dbd6..f531d7881 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Error.scala @@ -18,7 +18,7 @@ package zio.elasticsearch.executor.response import zio.json.{DeriveJsonDecoder, JsonDecoder, jsonField} -final case class Error private[elasticsearch]( +final case class Error private[elasticsearch] ( `type`: String, reason: String, @jsonField("index_uuid") diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala index 917e32dc5..148001ca6 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala @@ -29,7 +29,7 @@ sealed trait Item { } @jsonHint("create") -final case class Create private[elasticsearch]( +final case class Create private[elasticsearch] ( @jsonField("_index") index: String, @jsonField("_id") @@ -48,7 +48,7 @@ private[elasticsearch] object Create { } @jsonHint("delete") -final case class Delete private[elasticsearch]( +final case class Delete private[elasticsearch] ( @jsonField("_index") index: String, @jsonField("_id") @@ -67,7 +67,7 @@ private[elasticsearch] object Delete { } @jsonHint("index") -final case class Index private[elasticsearch]( +final case class Index private[elasticsearch] ( @jsonField("_index") index: String, @jsonField("_id") diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala index fa571bdfb..00479ddcb 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala @@ -18,7 +18,7 @@ package zio.elasticsearch.executor.response import zio.json.{DeriveJsonDecoder, JsonDecoder} -final case class Status private[elasticsearch]( +final case class Status private[elasticsearch] ( status: Int, error: Error ) From 93b2bd11a04c24e2f1a22ff9629351398eff4223 Mon Sep 17 00:00:00 2001 From: Jean-Luc CANELA Date: Mon, 8 May 2023 11:20:54 +0200 Subject: [PATCH 7/7] fixed according to review --- .../zio/elasticsearch/HttpExecutorSpec.scala | 4 ++- .../elasticsearch/executor/HttpExecutor.scala | 2 +- .../executor/response/Item.scala | 10 +++---- .../executor/response/Shards.scala | 2 +- .../executor/response/ShardsResponse.scala | 29 ------------------- .../executor/response/Status.scala | 28 ------------------ .../HttpElasticExecutorSpec.scala | 7 +++-- 7 files changed, 14 insertions(+), 68 deletions(-) delete mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala delete mode 100644 modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala diff --git a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala index 71b55dab1..94c10e87e 100644 --- a/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala +++ b/modules/library/src/it/scala/zio/elasticsearch/HttpExecutorSpec.scala @@ -1439,7 +1439,8 @@ object HttpExecutorSpec extends IntegrationSpec { req7 = ElasticRequest .update[TestDocument](index, DocumentId("invalid-document-id"), document.copy(intField = 100)) - res <- Executor.execute(ElasticRequest.bulk(req1, req2, req3, req4, req5, req6, req7).refreshTrue) + res <- + Executor.execute(ElasticRequest.bulk(req1, req2, req3, req4, req5, req6, req7).refreshTrue) doc1 <- Executor.execute(ElasticRequest.getById(index, firstDocumentId)).documentAs[TestDocument] doc2 <- Executor.execute(ElasticRequest.getById(index, secondDocumentId)).documentAs[TestDocument] doc3 <- Executor.execute(ElasticRequest.getById(index, thirdDocumentId)).documentAs[TestDocument] @@ -1447,6 +1448,7 @@ object HttpExecutorSpec extends IntegrationSpec { assert(res.items.map(_.error.isDefined))( equalTo(List(false, false, false, false, false, false, true)) ) && + assert(res.items(6).status)(equalTo(Some(404))) && assert(res.items(6).error.map(_.`type`))(equalTo(Some("document_missing_exception"))) && assert(doc3)(isSome(equalTo(document.copy(intField = 100)))) && assert(doc2)(isNone) && assert(doc1)( diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala index bf0330dcb..184f47e64 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/HttpExecutor.scala @@ -127,7 +127,7 @@ private[elasticsearch] final class HttpExecutor private (esConfig: ElasticConfig } } - private def executeBulk[A](r: Bulk): Task[BulkResponse] = { + private def executeBulk(r: Bulk): Task[BulkResponse] = { val uri = (r.index match { case Some(index) => uri"${esConfig.uri}/$index/$Bulk" case None => uri"${esConfig.uri}/$Bulk" diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala index 148001ca6..5f39ea1e1 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Item.scala @@ -23,7 +23,7 @@ sealed trait Item { def id: String def version: Option[Int] def result: Option[String] - def shards: Option[ShardsResponse] + def shards: Option[Shards] def status: Option[Int] def error: Option[Error] } @@ -38,7 +38,7 @@ final case class Create private[elasticsearch] ( version: Option[Int], result: Option[String], @jsonField("_shards") - shards: Option[ShardsResponse], + shards: Option[Shards], status: Option[Int], error: Option[Error] ) extends Item @@ -57,7 +57,7 @@ final case class Delete private[elasticsearch] ( version: Option[Int], result: Option[String], @jsonField("_shards") - shards: Option[ShardsResponse], + shards: Option[Shards], status: Option[Int], error: Option[Error] ) extends Item @@ -76,7 +76,7 @@ final case class Index private[elasticsearch] ( version: Option[Int], result: Option[String], @jsonField("_shards") - shards: Option[ShardsResponse], + shards: Option[Shards], status: Option[Int], error: Option[Error] ) extends Item @@ -95,7 +95,7 @@ final case class Update private[elasticsearch] ( version: Option[Int], result: Option[String], @jsonField("_shards") - shards: Option[ShardsResponse], + shards: Option[Shards], status: Option[Int], error: Option[Error] ) extends Item diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Shards.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Shards.scala index 04ba9bab6..dbce62b84 100644 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Shards.scala +++ b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Shards.scala @@ -21,7 +21,7 @@ import zio.json.{DeriveJsonDecoder, JsonDecoder} private[elasticsearch] final case class Shards( total: Int, successful: Int, - skipped: Int, + skipped: Int = 0, failed: Int ) diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala deleted file mode 100644 index 6cf0d7e64..000000000 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/ShardsResponse.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2022 LambdaWorks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package zio.elasticsearch.executor.response - -import zio.json.{DeriveJsonDecoder, JsonDecoder} - -final case class ShardsResponse private[elasticsearch] ( - total: Int, - successful: Int, - failed: Int -) - -private[elasticsearch] object ShardsResponse { - implicit val decoder: JsonDecoder[ShardsResponse] = DeriveJsonDecoder.gen[ShardsResponse] -} diff --git a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala b/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala deleted file mode 100644 index 00479ddcb..000000000 --- a/modules/library/src/main/scala/zio/elasticsearch/executor/response/Status.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2022 LambdaWorks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package zio.elasticsearch.executor.response - -import zio.json.{DeriveJsonDecoder, JsonDecoder} - -final case class Status private[elasticsearch] ( - status: Int, - error: Error -) - -private[elasticsearch] object Status { - implicit val decoder: JsonDecoder[Status] = DeriveJsonDecoder.gen[Status] -} diff --git a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala index 89b816c89..e8239bf4c 100644 --- a/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala +++ b/modules/library/src/test/scala/zio/elasticsearch/HttpElasticExecutorSpec.scala @@ -23,7 +23,7 @@ import zio.elasticsearch.executor.Executor import zio.elasticsearch.executor.response.{ BulkResponse, Create, - ShardsResponse, + Shards, TermsAggregationBucket, TermsAggregationResponse } @@ -65,10 +65,11 @@ object HttpElasticExecutorSpec extends SttpBackendStubSpec { version = Some(1), result = Some("created"), shards = Some( - ShardsResponse( + Shards( total = 1, successful = 1, - failed = 0 + failed = 0, + skipped = 0 ) ), status = Some(201),