From 7accab6ece99167bb50c57977036ef86c508438e Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 26 Jan 2023 13:27:06 +0000 Subject: [PATCH] Fix MultiGet response deserialization for non-matched IDs (#7181) * Correct handling for non-matched multi get IDs * Fix license header * Fix converter logic by switching order * Update integration jobs for latest versions --- .github/workflows/integration-jobs.yml | 3 +- .../ResponseItemConverterFactory.cs | 16 ++--- .../MGet/MGetResponseSerialization.cs | 63 +++++++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 tests/Tests/Document/Multiple/MGet/MGetResponseSerialization.cs diff --git a/.github/workflows/integration-jobs.yml b/.github/workflows/integration-jobs.yml index a48076529a2..9c075b05dee 100644 --- a/.github/workflows/integration-jobs.yml +++ b/.github/workflows/integration-jobs.yml @@ -27,7 +27,8 @@ jobs: '8.3.3', '8.4.3', "8.5.3", - '8.6.0-SNAPSHOT', + '8.6.1', + "8.7.0-SNAPSHOT" 'latest-8' ] diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/ResponseItemConverterFactory.cs b/src/Elastic.Clients.Elasticsearch/Serialization/ResponseItemConverterFactory.cs index aebec65ae42..06f503d1e55 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/ResponseItemConverterFactory.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/ResponseItemConverterFactory.cs @@ -40,32 +40,32 @@ private sealed class ResponseItemConverter : JsonConverter>(ref readerCopy, options); + var result = JsonSerializer.Deserialize(ref reader, options); - // If we have a version number, we can be sure this isn't an error - if (result is not null && result.Version is not null) + if (result is not null && result.Error is not null) { - reader = readerCopy; // Ensure we swap the reader to reflect the data we have consumed. return new MultiGetResponseItem(result); } } catch (Exception ex) { - getResultException = ex; + errorException = ex; } try { - var result = JsonSerializer.Deserialize(ref reader, options); + var result = JsonSerializer.Deserialize>(ref readerCopy, options); - if (result is not null && result.Error is not null) + // If we have a version number, we can be sure this isn't an error + if (result is not null) { + reader = readerCopy; // Ensure we swap the reader to reflect the data we have consumed. return new MultiGetResponseItem(result); } } catch (Exception ex) { - errorException = ex; + getResultException = ex; } Exception innerException = null; diff --git a/tests/Tests/Document/Multiple/MGet/MGetResponseSerialization.cs b/tests/Tests/Document/Multiple/MGet/MGetResponseSerialization.cs new file mode 100644 index 00000000000..85ceb50b577 --- /dev/null +++ b/tests/Tests/Document/Multiple/MGet/MGetResponseSerialization.cs @@ -0,0 +1,63 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Tests.Serialization; +using Xunit; + +namespace Tests.Document.Multiple.MGet; + +public class MGetResponseSerialization : SerializerTestBase +{ + private const string ResponseJson = @"{ + ""docs"": [ + { + ""_index"": ""foos"", + ""_id"": ""001"", + ""_version"": 5, + ""_seq_no"": 8, + ""_primary_term"": 1, + ""found"": true, + ""_source"": { + ""id"": ""001"", + ""name"": ""FooA"" + } + }, + { + ""_index"": ""foos"", + ""_id"": ""002"", + ""_version"": 5, + ""_seq_no"": 9, + ""_primary_term"": 1, + ""found"": true, + ""_source"": { + ""id"": ""002"", + ""name"": ""FooB"" + } + }, + { + ""_index"": ""foos"", + ""_id"": ""nonexistant"", + ""found"": false + } + ] +}"; + + [U] + public void MultiGetResponse_DeserializesCorrectly_WhenIdsAreNotFound() + { + var response = DeserializeJsonString>(ResponseJson); + + response.Docs.Should().HaveCount(3); + response.Docs.ElementAt(0).Match(r => r.Found.Should().BeTrue(), _ => Assert.Fail("Union item should not have matched.")); + response.Docs.ElementAt(1).Match(r => r.Found.Should().BeTrue(), _ => Assert.Fail("Union item should not have matched.")); + response.Docs.ElementAt(2).Match(r => r.Found.Should().BeFalse(), _ => Assert.Fail("Union item should not have matched.")); + } +} + +internal class Foo +{ + public string Id { get; set; } + public string Name { get; set; } +}