From 110dd79b3cbfa998352dc2072502e4e86973243d Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 24 Nov 2022 11:30:32 +0000 Subject: [PATCH] Fix MultiSearchTemplateRequest body (#7008) * Manually define the RequestItem for MultiSearchTemplateRequests - Manual type implements IStreamSerializable to support NDJSON. - Add serialization test * Update integration workflow stack version * Add release notes * Make headings discrete --- .github/workflows/integration-jobs.yml | 2 +- .../release-notes-8.0.1.asciidoc | 36 ++++++++++ docs/release-notes/release-notes.asciidoc | 8 ++- .../MultiSearch => Api}/MultiSearchRequest.cs | 0 .../Elastic.Clients.Elasticsearch.csproj | 3 + .../MSearch}/SearchRequestItem.cs | 4 +- .../SearchTemplateRequestItem.cs | 54 +++++++++++++++ .../Api/MultiSearchTemplateRequest.g.cs | 10 +-- .../_Generated/Types/Core/RequestItem.g.cs | 38 ---------- .../MSearchTemplateSerialization.cs | 69 +++++++++++++++++++ ...zesMultiSearchTemplateRequest.verified.txt | 4 ++ 11 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 docs/release-notes/release-notes-8.0.1.asciidoc rename src/Elastic.Clients.Elasticsearch/{Types/Documents/MultiSearch => Api}/MultiSearchRequest.cs (100%) rename src/Elastic.Clients.Elasticsearch/Types/{Documents/MultiSearch => Core/MSearch}/SearchRequestItem.cs (96%) create mode 100644 src/Elastic.Clients.Elasticsearch/Types/Core/MSearchTemplate/SearchTemplateRequestItem.cs delete mode 100644 src/Elastic.Clients.Elasticsearch/_Generated/Types/Core/RequestItem.g.cs create mode 100644 tests/Tests/Core/MSearchTemplate/MSearchTemplateSerialization.cs create mode 100644 tests/Tests/_VerifySnapshots/MSearchTemplateSerialization.SerializesMultiSearchTemplateRequest.verified.txt diff --git a/.github/workflows/integration-jobs.yml b/.github/workflows/integration-jobs.yml index 4cee0e22f11..e862ff4c224 100644 --- a/.github/workflows/integration-jobs.yml +++ b/.github/workflows/integration-jobs.yml @@ -26,7 +26,7 @@ jobs: '8.2.3', '8.3.3', '8.4.3', - "8.5.0", + "8.5.2", '8.6.0-SNAPSHOT', 'latest-8' ] diff --git a/docs/release-notes/release-notes-8.0.1.asciidoc b/docs/release-notes/release-notes-8.0.1.asciidoc new file mode 100644 index 00000000000..6a44955199d --- /dev/null +++ b/docs/release-notes/release-notes-8.0.1.asciidoc @@ -0,0 +1,36 @@ +[[release-notes-8.0.1]] +== Release notes v8.0.1 + +[discrete] +=== Bug fixes + +- Fix MultiSearchTemplateRequest serialization (issue: +https://github.com/elastic/elasticsearch-net/issues/7006[#7006]) + +[discrete] +=== Breaking changes + +This release includes the following breaking changes: + +[discrete] +==== MultiSearchTemplate type changes + +The `Core.MSearchTemplate.RequestItem` type has been renamed to +`Core.MSearchTemplate.SearchTemplateRequestItem`. It no longer derives from the +`Union` type. It has been manually designed to support serialisation to +NDJSON, as required by the MSearchTemplate endpoint. + +The `MultiSearchTemplateRequest.SearchTemplates` property has been updated to +use this newly defined type. + +This breaking change has been included in this patch release due to the +original code-generated type not functioning correctly and therefore we have +determined that this should ship ASAP. + +[discrete] +=== MultiSearch type changes + +The `Core.MSearch.SearchRequestItem` type has been sealed for consistency with +the design choices in the rest of the client. While technically breaking, we +have decided that this should be included in this release before any potential +derived types may exist in consuming applications. \ No newline at end of file diff --git a/docs/release-notes/release-notes.asciidoc b/docs/release-notes/release-notes.asciidoc index 80402ce60b6..c4f545a5daf 100644 --- a/docs/release-notes/release-notes.asciidoc +++ b/docs/release-notes/release-notes.asciidoc @@ -2,7 +2,13 @@ = Release notes * <> -* <> + +[discrete] +== Version 8.x + +* <> +* <> include::breaking-change-policy.asciidoc[] include::release-notes-8.0.0.asciidoc[] +include::release-notes-8.0.1.asciidoc[] diff --git a/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs b/src/Elastic.Clients.Elasticsearch/Api/MultiSearchRequest.cs similarity index 100% rename from src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs rename to src/Elastic.Clients.Elasticsearch/Api/MultiSearchRequest.cs diff --git a/src/Elastic.Clients.Elasticsearch/Elastic.Clients.Elasticsearch.csproj b/src/Elastic.Clients.Elasticsearch/Elastic.Clients.Elasticsearch.csproj index d07716572bf..70908f8ab1d 100644 --- a/src/Elastic.Clients.Elasticsearch/Elastic.Clients.Elasticsearch.csproj +++ b/src/Elastic.Clients.Elasticsearch/Elastic.Clients.Elasticsearch.csproj @@ -33,4 +33,7 @@ <_Parameter1>true + + + \ No newline at end of file diff --git a/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/SearchRequestItem.cs b/src/Elastic.Clients.Elasticsearch/Types/Core/MSearch/SearchRequestItem.cs similarity index 96% rename from src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/SearchRequestItem.cs rename to src/Elastic.Clients.Elasticsearch/Types/Core/MSearch/SearchRequestItem.cs index deed0df974b..9aad2fa358e 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/SearchRequestItem.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Core/MSearch/SearchRequestItem.cs @@ -11,7 +11,7 @@ namespace Elastic.Clients.Elasticsearch.Core.MSearch; // POC - If we have more than one union doing this, can we autogenerate with correct ctors etc. -public class SearchRequestItem : IStreamSerializable +public sealed class SearchRequestItem : IStreamSerializable { public SearchRequestItem(MultisearchBody body) => Body = body; @@ -52,5 +52,3 @@ async Task IStreamSerializable.SerializeAsync(Stream stream, IElasticsearchClien } } } - - diff --git a/src/Elastic.Clients.Elasticsearch/Types/Core/MSearchTemplate/SearchTemplateRequestItem.cs b/src/Elastic.Clients.Elasticsearch/Types/Core/MSearchTemplate/SearchTemplateRequestItem.cs new file mode 100644 index 00000000000..b2c44d7c227 --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Types/Core/MSearchTemplate/SearchTemplateRequestItem.cs @@ -0,0 +1,54 @@ +// 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.IO; +using System.Text.Json; +using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.Core.MSearch; +using Elastic.Clients.Elasticsearch.Serialization; +using Elastic.Transport; + +namespace Elastic.Clients.Elasticsearch.Core.MSearchTemplate; + +public sealed class SearchTemplateRequestItem : IStreamSerializable +{ + public SearchTemplateRequestItem(TemplateConfig body) => Body = body; + + public SearchTemplateRequestItem(MultisearchHeader header, TemplateConfig body) + { + Header = header; + Body = body; + } + + public MultisearchHeader Header { get; init; } + public TemplateConfig Body { get; init; } + + void IStreamSerializable.Serialize(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) + { + if (Body is null) + return; + + if (settings.RequestResponseSerializer.TryGetJsonSerializerOptions(out var options)) + { + JsonSerializer.Serialize(stream, Header, options); + stream.WriteByte((byte)'\n'); + JsonSerializer.Serialize(stream, Body, options); + stream.WriteByte((byte)'\n'); + } + } + + async Task IStreamSerializable.SerializeAsync(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) + { + if (Body is null) + return; + + if (settings.RequestResponseSerializer.TryGetJsonSerializerOptions(out var options)) + { + await JsonSerializer.SerializeAsync(stream, Header, options).ConfigureAwait(false); + stream.WriteByte((byte)'\n'); + await JsonSerializer.SerializeAsync(stream, Body, options).ConfigureAwait(false); + stream.WriteByte((byte)'\n'); + } + } +} diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Api/MultiSearchTemplateRequest.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Api/MultiSearchTemplateRequest.g.cs index c05edca0c6f..6601bf17ef6 100644 --- a/src/Elastic.Clients.Elasticsearch/_Generated/Api/MultiSearchTemplateRequest.g.cs +++ b/src/Elastic.Clients.Elasticsearch/_Generated/Api/MultiSearchTemplateRequest.g.cs @@ -75,7 +75,7 @@ public MultiSearchTemplateRequest(Elastic.Clients.Elasticsearch.Indices? indices [JsonIgnore] public bool? TypedKeys { get => Q("typed_keys"); set => Q("typed_keys", value); } - public List SearchTemplates { get; set; } + public List SearchTemplates { get; set; } void IStreamSerializable.Serialize(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) { @@ -125,7 +125,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o { } - List _items = new(); + List _items = new(); void IStreamSerializable.Serialize(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) { if (_items is null) @@ -148,7 +148,7 @@ async Task IStreamSerializable.SerializeAsync(Stream stream, IElasticsearchClien } } - public MultiSearchTemplateRequestDescriptor Add(Core.MSearchTemplate.RequestItem item) + public MultiSearchTemplateRequestDescriptor Add(Core.MSearchTemplate.SearchTemplateRequestItem item) { _items.Add(item); return this; @@ -180,7 +180,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o { } - List _items = new(); + List _items = new(); void IStreamSerializable.Serialize(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) { if (_items is null) @@ -203,7 +203,7 @@ async Task IStreamSerializable.SerializeAsync(Stream stream, IElasticsearchClien } } - public MultiSearchTemplateRequestDescriptor Add(Core.MSearchTemplate.RequestItem item) + public MultiSearchTemplateRequestDescriptor Add(Core.MSearchTemplate.SearchTemplateRequestItem item) { _items.Add(item); return this; diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Types/Core/RequestItem.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Types/Core/RequestItem.g.cs deleted file mode 100644 index 15682a71861..00000000000 --- a/src/Elastic.Clients.Elasticsearch/_Generated/Types/Core/RequestItem.g.cs +++ /dev/null @@ -1,38 +0,0 @@ -// 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. -// -// ███╗ ██╗ ██████╗ ████████╗██╗ ██████╗███████╗ -// ████╗ ██║██╔═══██╗╚══██╔══╝██║██╔════╝██╔════╝ -// ██╔██╗ ██║██║ ██║ ██║ ██║██║ █████╗ -// ██║╚██╗██║██║ ██║ ██║ ██║██║ ██╔══╝ -// ██║ ╚████║╚██████╔╝ ██║ ██║╚██████╗███████╗ -// ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝ -// ------------------------------------------------ -// -// This file is automatically generated. -// Please do not edit these files manually. -// -// ------------------------------------------------ - -using Elastic.Clients.Elasticsearch.Fluent; -using Elastic.Clients.Elasticsearch.Serialization; -using Elastic.Transport; -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Text.Json; -using System.Text.Json.Serialization; - -#nullable restore -namespace Elastic.Clients.Elasticsearch.Core.MSearchTemplate; -public partial class RequestItem : Union -{ - public RequestItem(Elastic.Clients.Elasticsearch.Core.MSearch.MultisearchHeader header) : base(header) - { - } - - public RequestItem(Elastic.Clients.Elasticsearch.Core.MSearchTemplate.TemplateConfig body) : base(body) - { - } -} \ No newline at end of file diff --git a/tests/Tests/Core/MSearchTemplate/MSearchTemplateSerialization.cs b/tests/Tests/Core/MSearchTemplate/MSearchTemplateSerialization.cs new file mode 100644 index 00000000000..1cdf892b5de --- /dev/null +++ b/tests/Tests/Core/MSearchTemplate/MSearchTemplateSerialization.cs @@ -0,0 +1,69 @@ +// 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.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Elastic.Clients.Elasticsearch.Core.MSearch; +using Elastic.Clients.Elasticsearch.Core.MSearchTemplate; +using Elastic.Clients.Elasticsearch.Serialization; +using Tests.Domain; +using VerifyTests; +using VerifyXunit; + +namespace Tests.Core.MSearchTemplate; + +[UsesVerify] +public class MSearchTemplateSerialization +{ + private readonly VerifySettings _verifySettings; + + public MSearchTemplateSerialization() + { + _verifySettings = new VerifySettings(); + _verifySettings.DisableRequireUniquePrefix(); + } + + [U] + public async Task SerializesMultiSearchTemplateRequest() + { + var settings = new ElasticsearchClientSettings(); + settings.DefaultMappingFor(m => m.IndexName("projects")); + + var ms = new MemoryStream(); + + var request = (IStreamSerializable)new MultiSearchTemplateRequest + { + SearchTemplates = new List + { + new SearchTemplateRequestItem(new MultisearchHeader { Index = Infer.Index() }, new TemplateConfig { Id = "my-search-template", Params = new Dictionary + { + { "query_string", "hello world" }, + { "from", 0 } + }}), + new SearchTemplateRequestItem(new MultisearchHeader { Index = Infer.Index() }, new TemplateConfig { Id = "my-search-template", Params = new Dictionary + { + { "query_type", "match_all" } + }}), + } + }; + + await request.SerializeAsync(ms, settings); + + ms.Position = 0; + var reader = new StreamReader(ms); + var ndjson = reader.ReadToEnd(); + + await Verifier.Verify(ndjson, _verifySettings); + + ms = new MemoryStream(); + request.Serialize(ms, settings); + + ms.Position = 0; + reader = new StreamReader(ms); + ndjson = reader.ReadToEnd(); + + await Verifier.Verify(ndjson, _verifySettings); + } +} diff --git a/tests/Tests/_VerifySnapshots/MSearchTemplateSerialization.SerializesMultiSearchTemplateRequest.verified.txt b/tests/Tests/_VerifySnapshots/MSearchTemplateSerialization.SerializesMultiSearchTemplateRequest.verified.txt new file mode 100644 index 00000000000..2ca730b6a0e --- /dev/null +++ b/tests/Tests/_VerifySnapshots/MSearchTemplateSerialization.SerializesMultiSearchTemplateRequest.verified.txt @@ -0,0 +1,4 @@ +{"index":"projects"} +{"id":"my-search-template","params":{"query_string":"hello world","from":0}} +{"index":"projects"} +{"id":"my-search-template","params":{"query_type":"match_all"}}