Skip to content

[Backport 8.3] Community backports for 8.1.3 #7804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/Elastic.Clients.Elasticsearch/Api/ResponseItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// 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;

namespace Elastic.Clients.Elasticsearch.Core.Bulk;

public abstract partial class ResponseItem
Expand All @@ -15,12 +17,19 @@ public bool IsValid
if (Error is not null)
return false;

return Operation.ToLowerInvariant() switch
var operation = Operation;

if (operation.Equals("delete", StringComparison.OrdinalIgnoreCase))
return Status is 200 or 404;

if (operation.Equals("create", StringComparison.OrdinalIgnoreCase) ||
operation.Equals("update", StringComparison.OrdinalIgnoreCase) ||
operation.Equals("index", StringComparison.OrdinalIgnoreCase))
{
"delete" => Status == 200 || Status == 404,
"update" or "index" or "create" => Status == 200 || Status == 201,
_ => false,
};
return Status is 200 or 201;
}

return false;
}
}
}
11 changes: 11 additions & 0 deletions src/Elastic.Clients.Elasticsearch/Core/IEnumStruct.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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.

namespace Elastic.Clients.Elasticsearch.Core;

internal interface IEnumStruct<TSelf> where TSelf : struct, IEnumStruct<TSelf>
{
// TODO: Can be made static when targeting .NET 7 and higher
TSelf Create(string value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public Field(PropertyInfo property, double? boost = null, string format = null)
/// </remarks>
public string? Format { get; set; }

[JsonIgnore]
internal bool CachableExpression { get; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ namespace Elastic.Clients.Elasticsearch;

internal sealed class FieldConverter : JsonConverter<Field>
{
private static readonly JsonEncodedText FieldProperty = JsonEncodedText.Encode("field");
private static readonly JsonEncodedText FormatProperty = JsonEncodedText.Encode("format");

private IElasticsearchClientSettings _settings;

public override void WriteAsPropertyName(Utf8JsonWriter writer, Field value, JsonSerializerOptions options)
Expand Down Expand Up @@ -48,19 +51,19 @@ private static Field ReadObjectField(ref Utf8JsonReader reader)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();

switch (propertyName)
if (reader.ValueTextEquals(FieldProperty.EncodedUtf8Bytes))
{
reader.Read();
field = reader.GetString();
}
else if (reader.ValueTextEquals(FormatProperty.EncodedUtf8Bytes))
{
reader.Read();
format = reader.GetString();
}
else
{
case "field":
field = reader.GetString();
break;
case "format":
format = reader.GetString();
break;
default:
throw new JsonException("Unexpected property while reading `Field`.");
throw new JsonException($"Unexpected property while reading `{nameof(Field)}`.");
}
}
}
Expand All @@ -70,19 +73,13 @@ private static Field ReadObjectField(ref Utf8JsonReader reader)
return new Field(field, format);
}

throw new JsonException("Unable to read `Field` from JSON.");
throw new JsonException($"Unable to read `{nameof(Field)}` from JSON.");
}

public override void Write(Utf8JsonWriter writer, Field value, JsonSerializerOptions options)
{
InitializeSettings(options);

if (value is null)
{
writer.WriteNullValue();
return;
}

var fieldName = _settings.Inferrer.Field(value);

if (string.IsNullOrEmpty(value.Format))
Expand All @@ -92,10 +89,8 @@ public override void Write(Utf8JsonWriter writer, Field value, JsonSerializerOpt
else
{
writer.WriteStartObject();
writer.WritePropertyName("field");
writer.WriteStringValue(fieldName);
writer.WritePropertyName("format");
writer.WriteStringValue(value.Format);
writer.WriteString(FieldProperty, fieldName);
writer.WriteString(FormatProperty, value.Format);
writer.WriteEndObject();
}
}
Expand Down
42 changes: 1 addition & 41 deletions src/Elastic.Clients.Elasticsearch/Core/Infer/Id/Ids.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Transport;

Expand All @@ -22,7 +21,7 @@ public partial class Ids : IUrlParameter, IEquatable<Ids>

public Ids(IList<Id> ids) => _ids = ids;

public Ids(IEnumerable<string> ids) => _ids = ids?.Select(i => new Id(i)).ToList();
public Ids(IEnumerable<string> ids) => _ids = ids.Select(i => new Id(i)).ToList();

public Ids(string value)
{
Expand Down Expand Up @@ -84,42 +83,3 @@ public override int GetHashCode()

public static bool operator !=(Ids left, Ids right) => !Equals(left, right);
}

internal sealed class IdsConverter : JsonConverter<Ids>
{
public override Ids? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartArray)
throw new JsonException($"Unexpected JSON token. Expected {JsonTokenType.StartArray} but read {reader.TokenType}");

var ids = new List<Id>();

while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
{
var id = JsonSerializer.Deserialize<Id>(ref reader, options);

if (id is not null)
ids.Add(id);
}

return new Ids(ids);
}

public override void Write(Utf8JsonWriter writer, Ids value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
return;
}

writer.WriteStartArray();

foreach (var id in value.IdsToSerialize)
{
JsonSerializer.Serialize<Id>(writer, id, options);
}

writer.WriteEndArray();
}
}
49 changes: 49 additions & 0 deletions src/Elastic.Clients.Elasticsearch/Core/Infer/Id/IdsConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Elastic.Clients.Elasticsearch;

internal sealed class IdsConverter : JsonConverter<Ids>
{
public override Ids? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartArray)
throw new JsonException($"Unexpected JSON token. Expected {JsonTokenType.StartArray} but read {reader.TokenType}");

var ids = new List<Id>();

while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
{
var id = JsonSerializer.Deserialize<Id>(ref reader, options);

if (id is not null)
ids.Add(id);
}

return new Ids(ids);
}

public override void Write(Utf8JsonWriter writer, Ids value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
return;
}

writer.WriteStartArray();

foreach (var id in value.IdsToSerialize)
{
JsonSerializer.Serialize<Id>(writer, id, options);
}

writer.WriteEndArray();
}
}
16 changes: 12 additions & 4 deletions src/Elastic.Clients.Elasticsearch/Core/Infer/Metric/Metrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System;
using System.Collections.Generic;
using System.Linq;
using Elastic.Transport;

namespace Elastic.Clients.Elasticsearch;
Expand Down Expand Up @@ -53,8 +52,8 @@ public bool Equals(Metrics other)
{
if (other is null) return false;

// Equality is true when the metrics names in both instances are equal, regardless of their order in the set.
return Values.OrderBy(t => t).SequenceEqual(other.Values.OrderBy(t => t));
// Equality is true when both instances have the same metric names.
return Values.SetEquals(other.Values);
}

string IUrlParameter.GetString(ITransportConfiguration settings) => GetString();
Expand All @@ -71,7 +70,16 @@ private string GetString()
}

/// <inheritdoc />
public override int GetHashCode() => Values != null ? Values.GetHashCode() : 0;
public override int GetHashCode()
{
// Lifting the minimal target framework to .NET Standard 2.1
// would be the best solution ever due to the HashCode type.
var hashCode = 0;
foreach (var metric in Values)
hashCode = (hashCode * 397) ^ metric.GetHashCode();

return hashCode;
}

public static bool operator ==(Metrics left, Metrics right) => Equals(left, right);
public static bool operator !=(Metrics left, Metrics right) => !Equals(left, right);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOp
if (bytes.Length < utf8bytes.Length)
{
bytes.CopyTo(utf8bytes);
return;
}
}
catch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Clients.Elasticsearch.Core;

namespace Elastic.Clients.Elasticsearch.Serialization;

internal sealed class EnumStructConverter<T> : JsonConverter<T> where T : new()
internal sealed class EnumStructConverter<T> : JsonConverter<T> where T : struct, IEnumStruct<T>
{
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();

var instance = (T)Activator.CreateInstance(
typeof(T),
BindingFlags.Instance | BindingFlags.NonPublic,
args: new object[] { value }, // TODO: Perf - Review use of ArrayPool
binder: null,
culture: null)!;
var instance = default(T).Create(value);

return instance;
}
Expand All @@ -30,7 +24,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions
var enumValue = value.ToString();

if (!string.IsNullOrEmpty(enumValue))
writer.WriteStringValue(value.ToString());
writer.WriteStringValue(enumValue);
else
writer.WriteNullValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOpt
if (bytes.Length < utf8bytes.Length)
{
bytes.CopyTo(utf8bytes);
return;
}
}
catch
Expand Down
33 changes: 21 additions & 12 deletions src/Elastic.Clients.Elasticsearch/Serialization/UnionConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,6 @@ private class DerivedUnionConverterInner<TType, TItem1, TItem2> : JsonConverter<
public override void Write(Utf8JsonWriter writer, TType value,
JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
return;
}

if (value.Item1 is not null)
{
JsonSerializer.Serialize(writer, value.Item1, value.Item1.GetType(), options);
Expand Down Expand Up @@ -214,15 +208,30 @@ private class BucketsConverter<TBucket> : JsonConverter<Buckets<TBucket>>
{
public override Buckets<TBucket>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// TODO - Read ahead to establish the type - For now, hardcoded for lists
return reader.TokenType switch
{
JsonTokenType.Null => null,
JsonTokenType.StartArray => new(JsonSerializer.Deserialize<IReadOnlyCollection<TBucket>>(ref reader, options)),
JsonTokenType.StartObject => new(JsonSerializer.Deserialize<IReadOnlyDictionary<string, TBucket>>(ref reader, options)),
_ => throw new JsonException("Invalid bucket type")
};
}

var bucketType = typeToConvert.GetGenericArguments()[0];
public override void Write(Utf8JsonWriter writer, Buckets<TBucket> value, JsonSerializerOptions options)
{
if (value.Item1 is { } item1)
{
JsonSerializer.Serialize(writer, item1, options);
return;
}

var item = JsonSerializer.Deserialize(ref reader, typeof(IReadOnlyCollection<TBucket>), options);
if (value.Item2 is { } item2)
{
JsonSerializer.Serialize(writer, item2, options);
return;
}

return (Buckets<TBucket>)Activator.CreateInstance(typeof(Buckets<>).MakeGenericType(bucketType), item);
writer.WriteNullValue();
}

public override void Write(Utf8JsonWriter writer, Buckets<TBucket> value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Text.Json.Serialization;
using System.Runtime.Serialization;
using Elastic.Transport;
using Elastic.Clients.Elasticsearch.Core;
using Elastic.Clients.Elasticsearch.Serialization;

namespace Elastic.Clients.Elasticsearch.Aggregations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Text.Json.Serialization;
using System.Runtime.Serialization;
using Elastic.Transport;
using Elastic.Clients.Elasticsearch.Core;
using Elastic.Clients.Elasticsearch.Serialization;

namespace Elastic.Clients.Elasticsearch.Analysis;
Expand Down
Loading