From 81526bd00dcb904ccb83397b6361b57242a4f302 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Wed, 31 Jan 2024 14:56:54 +0100 Subject: [PATCH 01/15] wip --- .../Http/AlgoliaHttpRequester.cs | 1 + .../algoliasearch/Http/TimeoutHandler.cs | 1 + .../Models/Common/AbstractSchema.cs | 77 ++--- .../Serializer/DefaultSerializer.cs | 50 ++- .../algoliasearch/Serializer/JsonConfig.cs | 18 +- .../algoliasearch/Transport/HttpTransport.cs | 13 +- .../algoliasearch/Transport/StatefulHost.cs | 24 +- playground/csharp/Algolia.sln | 12 + .../csharp/Performaces/Data/searchResult.json | 311 ++++++++++++++++++ .../csharp/Performaces/Model/TestObject.cs | 7 + .../csharp/Performaces/Performaces.csproj | 24 ++ playground/csharp/Performaces/Program.cs | 153 +++++++++ .../PerformanceLegacy.csproj | 14 + .../csharp/PerformanceLegacy/Program.cs | 48 +++ .../Playground/Playgrounds/Monitoring.cs | 2 +- playground/csharp/WorkerService1/Program.cs | 8 + .../Properties/launchSettings.json | 12 + playground/csharp/WorkerService1/Worker.cs | 31 ++ .../WorkerService1/WorkerService1.csproj | 17 + .../appsettings.Development.json | 8 + playground/javascript/node/search.ts | 7 + templates/csharp/generic_type.mustache | 2 +- templates/csharp/modelGeneric.mustache | 12 +- templates/csharp/modelOneOf.mustache | 10 +- .../csharp/tests/requests/requests.mustache | 5 +- 25 files changed, 790 insertions(+), 77 deletions(-) create mode 100644 playground/csharp/Performaces/Data/searchResult.json create mode 100644 playground/csharp/Performaces/Model/TestObject.cs create mode 100644 playground/csharp/Performaces/Performaces.csproj create mode 100644 playground/csharp/Performaces/Program.cs create mode 100644 playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj create mode 100644 playground/csharp/PerformanceLegacy/Program.cs create mode 100644 playground/csharp/WorkerService1/Program.cs create mode 100644 playground/csharp/WorkerService1/Properties/launchSettings.json create mode 100644 playground/csharp/WorkerService1/Worker.cs create mode 100644 playground/csharp/WorkerService1/WorkerService1.csproj create mode 100644 playground/csharp/WorkerService1/appsettings.Development.json diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs index 6711ac7629..54587e70ec 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs b/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs index a05a289279..48a7cfd500 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Net.Http; using System.Threading; using System.Threading.Tasks; diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs b/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs index c333ee9101..1a682a3a01 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs @@ -1,65 +1,36 @@ +// +// Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT. +// + using System; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Algolia.Search.Models.Common; - -/// -/// Abstract base class for oneOf, anyOf schemas in the API specification -/// -public abstract class AbstractSchema +namespace Algolia.Search.Models { /// - /// Custom JSON serializer + /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification /// - public static readonly JsonSerializerSettings SerializerSettings = new() + public abstract partial class AbstractSchema { - // OpenAPI generated types generally hide default constructors. - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, - MissingMemberHandling = MissingMemberHandling.Error, - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new CamelCaseNamingStrategy - { - OverrideSpecifiedNames = false - } - } - }; + /// + /// Gets or Sets the actual instance + /// + public abstract Object ActualInstance { get; set; } - /// - /// Custom JSON serializer for objects with additional properties - /// - public static readonly JsonSerializerSettings AdditionalPropertiesSerializerSettings = new JsonSerializerSettings - { - // OpenAPI generated types generally hide default constructors. - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, - MissingMemberHandling = MissingMemberHandling.Ignore, - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new CamelCaseNamingStrategy - { - OverrideSpecifiedNames = false - } - } - }; + /// + /// Gets or Sets IsNullable to indicate whether the instance is nullable + /// + public bool IsNullable { get; protected set; } - /// - /// Gets or Sets the actual instance - /// - public abstract object ActualInstance { get; set; } + /// + /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf` + /// + public string SchemaType { get; protected set; } - /// - /// Gets or Sets IsNullable to indicate whether the instance is nullable - /// - public bool IsNullable { get; protected set; } - - /// - /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf` - /// - public string SchemaType { get; protected set; } - - /// - /// Converts the instance into JSON string. - /// - public abstract string ToJson(); + /// + /// Converts the instance into JSON string. + /// + public abstract string ToJson(); + } } diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs index 3fd471a107..88992fdc9f 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs @@ -1,8 +1,10 @@ using System; +using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; using Algolia.Search.Exceptions; +using Algolia.Search.Models; using Algolia.Search.Models.Common; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -25,15 +27,34 @@ public DefaultJsonSerializer(JsonSerializerSettings serializerSettings, ILoggerF /// /// Object to be serialized. /// A JSON string. - public string Serialize(object obj) + public string Serialize(object data) { - if (obj is AbstractSchema schema) + if (data is AbstractSchema schema) { // the object to be serialized is an oneOf/anyOf schema - return schema.ToJson(); + var serialize = schema.ToJson(); + return serialize; } - return JsonConvert.SerializeObject(obj, _serializerSettings); + // using (var sw = new StreamWriter(memoryStream)) + // using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None }) + // { + // Serializer.MaxDepth = 123456789; + // Serializer.Serialize(jtw, data); + // jtw.Flush(); + // } + // stop.Stop(); + // Console.WriteLine($"Serialize: {stop.ElapsedTicks}ms"); + // + // + // memoryStream.Seek(0, SeekOrigin.Begin); + // Stopwatch stop2 = new Stopwatch(); + // stop2.Start(); + // + // stop2.Stop(); + // Console.WriteLine($"Serialize: {stop2.ElapsedMilliseconds}ms"); + + return JsonConvert.SerializeObject(data, _serializerSettings); } public async Task Deserialize(Stream response) @@ -80,7 +101,26 @@ private async Task Deserialize(Stream response, Type type) { using var reader = new StreamReader(response); var text = await reader.ReadToEndAsync().ConfigureAwait(false); - return JsonConvert.DeserializeObject(text, type, _serializerSettings); + // Stopwatch sw = new Stopwatch(); + // sw.Start(); + // + // + // if (response == null || response.CanRead == false) + // return default; + // + // using (response) + // using (var sr = new StreamReader(response)) + // using (var jtr = new JsonTextReader(sr)) + // { + // return Serializer.Deserialize(jtr); + // } + + + + var deserializeObject = JsonConvert.DeserializeObject(text, type, _serializerSettings); + // sw.Stop(); + // Console.WriteLine($"DeserializeObject: {sw.ElapsedMilliseconds}ms"); + return deserializeObject; } catch (Exception ex) { diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs index 9f94902343..b07e6ec686 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/JsonConfig.cs @@ -10,15 +10,29 @@ internal static class JsonConfig { public const string JsonContentType = "application/json"; - public static JsonSerializerSettings AlgoliaJsonSerializerSettings => new() + private static readonly DefaultContractResolver Resolver = new() { NamingStrategy = new CamelCaseNamingStrategy() }; + + public static readonly JsonSerializerSettings AlgoliaJsonSerializerSettings = new() { Formatting = Formatting.None, NullValueHandling = NullValueHandling.Ignore, - ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() }, + ContractResolver = Resolver, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, DateParseHandling = DateParseHandling.DateTime, ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, MissingMemberHandling = MissingMemberHandling.Ignore, }; + + // When DeserializeOneOfSettings is used, we set MissingMemberHandling to Error to throw an exception if a property is missing + public static readonly JsonSerializerSettings DeserializeOneOfSettings = new() + { + Formatting = Formatting.None, + NullValueHandling = NullValueHandling.Ignore, + ContractResolver = Resolver, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + DateParseHandling = DateParseHandling.DateTime, + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + MissingMemberHandling = MissingMemberHandling.Error, + }; } } diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs index 106c793e5b..d8375d4e36 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; @@ -116,7 +117,7 @@ private async Task ExecuteRequestAsync(HttpMethod metho foreach (var host in _retryStrategy.GetTryableHost(callType)) { request.Body = CreateRequestContent(requestOptions?.Data, request.CanCompress, _logger); - request.Uri = BuildUri(host.Url, uri, requestOptions?.CustomPathParameters, requestOptions?.PathParameters, + request.Uri = BuildUri(host, uri, requestOptions?.CustomPathParameters, requestOptions?.PathParameters, requestOptions?.QueryParameters); var requestTimeout = TimeSpan.FromTicks((requestOptions?.Timeout ?? GetTimeOut(callType)).Ticks * (host.RetryCount + 1)); @@ -228,13 +229,14 @@ private IDictionary GenerateHeaders(IDictionary /// /// Build uri depending on the method /// - /// + /// /// /// /// /// /// - private static Uri BuildUri(string url, string baseUri, IDictionary customPathParameters = null, + private static Uri BuildUri(StatefulHost host, string baseUri, + IDictionary customPathParameters = null, IDictionary pathParameters = null, IDictionary optionalQueryParameters = null) { @@ -258,10 +260,11 @@ private static Uri BuildUri(string url, string baseUri, IDictionary diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs index 02547f5096..22155c1d6c 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs @@ -8,10 +8,20 @@ namespace Algolia.Search.Transport; public class StatefulHost { /// - /// Url endpoint without the scheme + /// Url endpoint without the scheme, without the port /// public string Url { get; set; } + /// + /// Scheme of the URL + /// + public HttpScheme Scheme { get; set; } = HttpScheme.Https; + + /// + /// Port of the URL (Optional) + /// + public int Port { get; set; } = -1; + /// /// Is the host up or not /// @@ -33,6 +43,18 @@ public class StatefulHost public CallType Accept { get; set; } } +public enum HttpScheme +{ + /// + /// Http + /// + Http, + /// + /// Https + /// + Https +} + /// /// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/enumeration-types /// Binary enums beware when adding new values diff --git a/playground/csharp/Algolia.sln b/playground/csharp/Algolia.sln index 10fc823b1a..77385ce818 100644 --- a/playground/csharp/Algolia.sln +++ b/playground/csharp/Algolia.sln @@ -6,6 +6,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search", "..\..\cli EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search.Tests", "..\..\tests\output\csharp\src\Algolia.Search.Tests.csproj", "{5F6F1865-31E1-4984-B575-430A42217820}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Performaces", "Performaces\Performaces.csproj", "{5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceLegacy", "PerformanceLegacy\PerformanceLegacy.csproj", "{67814440-28A1-4344-873A-2E1F6F2FAAAC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +28,13 @@ Global {5F6F1865-31E1-4984-B575-430A42217820}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F6F1865-31E1-4984-B575-430A42217820}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F6F1865-31E1-4984-B575-430A42217820}.Release|Any CPU.Build.0 = Release|Any CPU + {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Release|Any CPU.Build.0 = Release|Any CPU + {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/playground/csharp/Performaces/Data/searchResult.json b/playground/csharp/Performaces/Data/searchResult.json new file mode 100644 index 0000000000..46bd8e883c --- /dev/null +++ b/playground/csharp/Performaces/Data/searchResult.json @@ -0,0 +1,311 @@ +{ + "hits": [ + { + "value": "batch3", + "otherValue": "otherValue3", + "objectID": "test5", + "_snippetResult": { + "value": { + "value": "batch3", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue3", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch3", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue3", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 3, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "batch2", + "otherValue": "otherValue2", + "objectID": "test4", + "_snippetResult": { + "value": { + "value": "batch2", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue2", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch2", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue2", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 2, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "batch1", + "otherValue": "otherValue1", + "objectID": "test3", + "_snippetResult": { + "value": { + "value": "batch1", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue1", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch1", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue1", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 1, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "test", + "otherValue": "otherValue", + "objectID": "test2", + "_snippetResult": { + "value": { + "value": "test", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "test", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 0, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + } + ], + "nbHits": 4, + "page": 0, + "nbPages": 1, + "hitsPerPage": 10, + "facets": { + "value": { + "batch1": 1, + "batch2": 1, + "batch3": 1, + "test": 1 + }, + "otherValue": { + "otherValue": 1, + "otherValue1": 1, + "otherValue2": 1, + "otherValue3": 1 + } + }, + "exhaustiveFacetsCount": true, + "exhaustiveNbHits": true, + "exhaustiveTypo": true, + "exhaustive": { + "facetsCount": true, + "nbHits": true, + "typo": true + }, + "query": "", + "params": "analytics=false&attributesToRetrieve=%5B%22*%22%5D&attributesToSnippet=%5B%22*%3A20%22%5D&enableABTest=false&explain=%5B%22*%22%5D&facets=%5B%22*%22%5D&getRankingInfo=true&highlightPostTag=%3C%2Fais-highlight-0%3E&highlightPreTag=%3Cais-highlight-0%3E&hitsPerPage=10&maxValuesPerFacet=100&page=0&query=&responseFields=%5B%22*%22%5D&snippetEllipsisText=%E2%80%A6&tagFilters=", + "index": "test-csharp-new-client", + "serverUsed": "c42-eu-3.algolia.net", + "indexUsed": "test-csharp-new-client", + "parsedQuery": "", + "timeoutCounts": false, + "timeoutHits": false, + "explain": { + "match": { + "alternatives": [] + }, + "params": { + "client": { + "query": "", + "analytics": false, + "page": 0, + "hitsPerPage": 10, + "attributesToRetrieve": [ + "*" + ], + "attributesToSnippet": [ + "*:20" + ], + "getRankingInfo": true, + "highlightPreTag": "", + "highlightPostTag": "", + "snippetEllipsisText": "…", + "tagFilters": [], + "facets": [ + "*" + ], + "maxValuesPerFacet": 100, + "responseFields": [ + "exhaustive", + "exhaustiveFacetValues", + "facets_stats", + "extensions", + "renderingContent", + "userData", + "aroundLatLng", + "queryAfterRemoval", + "exhaustiveFacetsCount", + "length", + "params", + "processingTimingsMS", + "facets", + "offset", + "hitsPerPage", + "automaticRadius", + "processingTimeMS", + "nbPages", + "page", + "query", + "serverTimeMS", + "index", + "exhaustiveTypo", + "nbHits", + "exhaustiveNbHits", + "hits" + ], + "enableABTest": false, + "explain": true + }, + "apiKey": {}, + "abTest": {}, + "rules": {}, + "final": { + "query": "", + "analytics": false, + "page": 0, + "hitsPerPage": 10, + "attributesToRetrieve": [ + "*" + ], + "attributesToSnippet": [ + "*:20" + ], + "getRankingInfo": true, + "highlightPreTag": "", + "highlightPostTag": "", + "snippetEllipsisText": "…", + "tagFilters": [], + "facets": [ + "*" + ], + "maxValuesPerFacet": 100, + "responseFields": [ + "exhaustive", + "exhaustiveFacetValues", + "facets_stats", + "extensions", + "renderingContent", + "userData", + "aroundLatLng", + "queryAfterRemoval", + "exhaustiveFacetsCount", + "length", + "params", + "processingTimingsMS", + "facets", + "offset", + "hitsPerPage", + "automaticRadius", + "processingTimeMS", + "nbPages", + "page", + "query", + "serverTimeMS", + "index", + "exhaustiveTypo", + "nbHits", + "exhaustiveNbHits", + "hits" + ], + "enableABTest": false, + "explain": true + } + } + }, + "renderingContent": {}, + "processingTimeMS": 1, + "processingTimingsMS": { + "_request": { + "queue": 4, + "roundTrip": 16 + } + }, + "serverTimeMS": 5 +} diff --git a/playground/csharp/Performaces/Model/TestObject.cs b/playground/csharp/Performaces/Model/TestObject.cs new file mode 100644 index 0000000000..0d5e3eb9fe --- /dev/null +++ b/playground/csharp/Performaces/Model/TestObject.cs @@ -0,0 +1,7 @@ +using Algolia.Search.Models.Search; + +public class TestObject : Hit +{ + public string? value { get; set; } + public string? otherValue { get; set; } +} diff --git a/playground/csharp/Performaces/Performaces.csproj b/playground/csharp/Performaces/Performaces.csproj new file mode 100644 index 0000000000..93ea135f50 --- /dev/null +++ b/playground/csharp/Performaces/Performaces.csproj @@ -0,0 +1,24 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/playground/csharp/Performaces/Program.cs b/playground/csharp/Performaces/Program.cs new file mode 100644 index 0000000000..c21e36fecc --- /dev/null +++ b/playground/csharp/Performaces/Program.cs @@ -0,0 +1,153 @@ +using System.Diagnostics; +using Algolia.Search.Clients; +using Algolia.Search.Models.Search; +using Algolia.Search.Transport; +using Newtonsoft.Json; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using Action = Algolia.Search.Models.Search.Action; + +var server = WireMockServer.Start(); +var client = new SearchClient(new SearchConfig("XXX", "XXXX") +{ + CustomHosts = + [ + new() + { + Scheme = HttpScheme.Http, + Port = server.Port, + Url = "localhost", + Accept = CallType.Read | CallType.Write, + Up = true + } + ] +}); + + +var searchResults = File.ReadAllText("Data/searchResult.json"); +server + .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/query").UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(searchResults) + ); + +var batchResponse = new BatchResponse(1, new List()); +server + .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/batch").UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(JsonConvert.SerializeObject(batchResponse)) + ); + + +Console.WriteLine("Starting..."); + +Stopwatch stopwatch = new(); +stopwatch.Start(); +for (var i = 0; i < 100; i++) +{ + await client + .SearchSingleIndexAsync("test-csharp-new-client", new SearchParams(new SearchParamsObject())); +} + +stopwatch.Stop(); +Console.WriteLine( + $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); + +Console.WriteLine(); + + +Console.WriteLine("Starting..."); + +stopwatch.Restart(); +for (var i = 0; i < 100; i++) +{ + await client + .BatchAsync("test-csharp-new-client", new BatchWriteParams(CreateRequests())).ConfigureAwait(false); +} + +stopwatch.Stop(); +Console.WriteLine( + $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); + +List CreateRequests() +{ + var requests = new List(); + + for (var i = 0; i < 100; i++) + { + requests.Add( + new() + { + Action = Action.AddObject, + Body = new + { + objectID = Guid.NewGuid(), + name = "Test" + i, + age = i, + city = "Paris", + country = "France", + hobbies = new[] { "sport", "music" }, + friends = new[] + { + new { name = "John", age = 42 }, + new { name = "Paul", age = 32 } + }, + company = new { name = "Algolia", country = "France", city = "Paris" }, + email = "test" + i + "@algolia.com", + objectIDWithNumbers = "42", + objectIDWithDates = "2020-01-01T00:00:00Z", + objectIDWithBoolean = "true", + objectIDWithArray = "[]", + objectIDWithObject = "{}", + objectIDWithNull = "null", + objectIDWithGeoPoint = "48.8584,2.2945", + objectIDWithGeoJSON = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON1 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON2 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON3 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON4 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON5 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON6 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON7 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON8 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON9 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithPolygon1 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon2 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon3 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon4 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon5 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon6 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon7 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon8 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon9 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon10 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithNullGeoPoint = "null", + objectIDWithNullGeoJSON = "null", + objectIDWithNullPolygon = "null", + objectIDWithEmptyGeoPoint = "", + objectIDWithEmptyGeoJSON = "", + objectIDWithEmptyPolygon = "", + objectIDWithEmptyArray = "", + objectIDWithEmptyObject = "", + objectIDWithEmptyString = "", + objectIDWithEmptyBoolean = "", + objectIDWithEmptyNull = "", + objectIDWithEmptyNumber = "", + objectIDWithEmptyDate = "", + objectIDWithEmptyPolygonArray = "", + objectIDWithEmptyGeoPointArray = "", + objectIDWithEmptyGeoJSONArray = "", + objectIDWithEmptyNullArray = "", + objectIDWithEmptyStringArray = "", + objectIDWithEmptyBooleanArray = "", + } + }); + } + + return requests; +} diff --git a/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj b/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj new file mode 100644 index 0000000000..c42371e037 --- /dev/null +++ b/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/playground/csharp/PerformanceLegacy/Program.cs b/playground/csharp/PerformanceLegacy/Program.cs new file mode 100644 index 0000000000..e3abdecee3 --- /dev/null +++ b/playground/csharp/PerformanceLegacy/Program.cs @@ -0,0 +1,48 @@ +// See https://aka.ms/new-console-template for more information + +using System.Diagnostics; +using Algolia.Search.Clients; +using Algolia.Search.Models.Search; + +Console.WriteLine("Hello, World!"); + +// dotnet dev-certs https +// dotnet dev-certs https --trust + +// var server = WireMockServer.Start(); +// +// +// server +// .Given(Request.Create().WithPath("/1/indexes/test/query").UsingPost()) +// .RespondWith( +// Response.Create() +// .WithStatusCode(200) +// .WithBody(@"{ ""params"": "" "", ""query"": "" "", ""processingTimeMS"": ""2"", ""hitsPerPage"": ""2"", ""nbHits"": ""10"", ""page"": ""0"", ""nbPages"": ""5"", ""hits"": [ { ""firstname"": ""Jimmie"", ""lastname"": ""Barninger"", ""objectID"": ""433"" }, { ""firstname"": ""Warren"", ""lastname"": ""Speach"", ""objectID"": ""2"" } ] }") +// ); + +var client = new SearchClient(new SearchConfig("LEKUUYKIXX", "XXX")); +// { +// CustomHosts = +// [ +// new() +// { +// Scheme = HttpScheme.Http, +// Port = server.Port, +// Url = "localhost", +// Accept = CallType.Read | CallType.Write, +// Up = true +// } +// ] +// }); + +for (int i = 0; i < 5; i++) +{ + Stopwatch stopwatch = new(); + stopwatch.Start(); + + var searchIndex = client.InitIndex("test-csharp-new-client"); + var searchResponse = await searchIndex.SearchAsync(new Query() { }).ConfigureAwait(false); + + stopwatch.Stop(); + Console.WriteLine($"Elapsed: {stopwatch.ElapsedMilliseconds}ms " + searchResponse.Hits.Count); +} diff --git a/playground/csharp/Playground/Playgrounds/Monitoring.cs b/playground/csharp/Playground/Playgrounds/Monitoring.cs index 74a5f97340..04745f7827 100644 --- a/playground/csharp/Playground/Playgrounds/Monitoring.cs +++ b/playground/csharp/Playground/Playgrounds/Monitoring.cs @@ -22,7 +22,7 @@ public static async Task Run(Configuration configuration) foreach (var incident in incidentsResponse.Incidents) { Console.WriteLine( - $"{incident.Key}: {Environment.NewLine}- {string.Join($"{Environment.NewLine} -", incident.Value.Select(inner => $" { DateTimeOffset.FromUnixTimeMilliseconds(inner.T).ToString(CultureInfo.InvariantCulture)} - {inner.V.Title}"))} {Environment.NewLine}"); + $"{incident.Key}: {Environment.NewLine}- {string.Join($"{Environment.NewLine} -", incident.Value.Select(inner => $" { DateTimeOffset.FromUnixTimeMilliseconds(inner.T.Value).ToString(CultureInfo.InvariantCulture)} - {inner.V.Title}"))} {Environment.NewLine}"); } } } diff --git a/playground/csharp/WorkerService1/Program.cs b/playground/csharp/WorkerService1/Program.cs new file mode 100644 index 0000000000..bae56c14fc --- /dev/null +++ b/playground/csharp/WorkerService1/Program.cs @@ -0,0 +1,8 @@ +using WorkerService1; + +var builder = Host.CreateApplicationBuilder(args); +builder.Services.AddHostedService(); +builder.Logging.AddFilter("Algolia", LogLevel.Information).AddConsole(); + +var host = builder.Build(); +host.Run(); diff --git a/playground/csharp/WorkerService1/Properties/launchSettings.json b/playground/csharp/WorkerService1/Properties/launchSettings.json new file mode 100644 index 0000000000..e5d9dbdb85 --- /dev/null +++ b/playground/csharp/WorkerService1/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "WorkerService1": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/playground/csharp/WorkerService1/Worker.cs b/playground/csharp/WorkerService1/Worker.cs new file mode 100644 index 0000000000..0b9170d7af --- /dev/null +++ b/playground/csharp/WorkerService1/Worker.cs @@ -0,0 +1,31 @@ +using Algolia.Search.Clients; +using Algolia.Search.Models.Search; + +namespace WorkerService1; + +public class Worker : BackgroundService +{ + private readonly ILogger _logger; + private readonly SearchClient _searchClient; + + public Worker(ILogger logger) + { + _logger = logger; + _searchClient = new SearchClient("test-app-id", "test-api-key"); + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + await _searchClient.SearchSingleIndexAsync("test", new SearchParams(new SearchParamsObject() { Query = "" }), cancellationToken: stoppingToken); + + while (!stoppingToken.IsCancellationRequested) + { + if (_logger.IsEnabled(LogLevel.Information)) + { + _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); + } + + await Task.Delay(1000, stoppingToken); + } + } +} diff --git a/playground/csharp/WorkerService1/WorkerService1.csproj b/playground/csharp/WorkerService1/WorkerService1.csproj new file mode 100644 index 0000000000..b7b02fea4e --- /dev/null +++ b/playground/csharp/WorkerService1/WorkerService1.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + enable + dotnet-WorkerService1-CB087983-1F62-46D2-B8A7-8D0DD04F82FF + + + + + + + + + + diff --git a/playground/csharp/WorkerService1/appsettings.Development.json b/playground/csharp/WorkerService1/appsettings.Development.json new file mode 100644 index 0000000000..b2dcdb6742 --- /dev/null +++ b/playground/csharp/WorkerService1/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/playground/javascript/node/search.ts b/playground/javascript/node/search.ts index 99b800d123..8904333115 100644 --- a/playground/javascript/node/search.ts +++ b/playground/javascript/node/search.ts @@ -23,6 +23,13 @@ console.log('version', apiClientVersion, 'requests', requests); async function testSearch() { try { + + let start = Date.now(); + + let resp = await client.searchSingleIndex({ indexName: "test-csharp-new-client", searchParams: { query: " " } }); + + console.log('searchSingleIndex', Date.now() - start); + const res = await client.browseRules({ indexName: "cts_e2e_search_facet", aggregator: (resp: any) => {console.log(resp)} }); console.log(`[OK]`, res); diff --git a/templates/csharp/generic_type.mustache b/templates/csharp/generic_type.mustache index d2a51d3a2e..a57ae0c8a2 100644 --- a/templates/csharp/generic_type.mustache +++ b/templates/csharp/generic_type.mustache @@ -1 +1 @@ -{{#vendorExtensions}}{{#isContainer}}{{#x-has-child-generic}}List<{{{complexType}}}>{{/x-has-child-generic}}{{^x-has-child-generic}}{{#x-propagated-generic}}List{{/x-propagated-generic}}{{^x-propagated-generic}}{{{datatypeWithEnum}}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/x-propagated-generic}}{{/x-has-child-generic}}{{/isContainer}}{{^isContainer}}{{#x-is-generic}}T{{/x-is-generic}}{{^x-is-generic}}{{{datatypeWithEnum}}}{{^isNullable}}{{#isInteger}}?{{/isInteger}}{{#isBoolean}}?{{/isBoolean}}{{/isNullable}}{{/x-is-generic}}{{/isContainer}}{{/vendorExtensions}} \ No newline at end of file +{{#vendorExtensions}}{{#isContainer}}{{#x-has-child-generic}}List<{{{complexType}}}>{{/x-has-child-generic}}{{^x-has-child-generic}}{{#x-propagated-generic}}List{{/x-propagated-generic}}{{^x-propagated-generic}}{{{datatypeWithEnum}}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/x-propagated-generic}}{{/x-has-child-generic}}{{/isContainer}}{{^isContainer}}{{#x-is-generic}}T{{/x-is-generic}}{{^x-is-generic}}{{{datatypeWithEnum}}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{/x-is-generic}}{{/isContainer}}{{/vendorExtensions}} \ No newline at end of file diff --git a/templates/csharp/modelGeneric.mustache b/templates/csharp/modelGeneric.mustache index b8bb9df549..00c850e211 100644 --- a/templates/csharp/modelGeneric.mustache +++ b/templates/csharp/modelGeneric.mustache @@ -41,7 +41,7 @@ /// {{{.}}} {{/description}} {{^conditionalSerialization}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#deprecated}} [Obsolete] {{/deprecated}} @@ -60,7 +60,7 @@ {{/conditionalSerialization}} {{#conditionalSerialization}} {{#isReadOnly}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#deprecated}} [Obsolete] {{/deprecated}} @@ -78,7 +78,7 @@ {{/isReadOnly}} {{^isReadOnly}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#deprecated}} [Obsolete] {{/deprecated}} @@ -177,7 +177,7 @@ /// {{#description}} /// {{{.}}}{{/description}} {{^conditionalSerialization}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#isDate}} [JsonConverter(typeof(OpenAPIDateConverter))] {{/isDate}} @@ -199,7 +199,7 @@ {{/conditionalSerialization}} {{#conditionalSerialization}} {{#isReadOnly}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#isDate}} [JsonConverter(typeof(OpenAPIDateConverter))] {{/isDate}} @@ -221,7 +221,7 @@ {{#isDate}} [JsonConverter(typeof(OpenAPIDateConverter))] {{/isDate}} - [DataMember(Name = "{{baseName}}"{{#required}}, IsRequired = true{{/required}}, EmitDefaultValue = false)] + [DataMember(Name = "{{baseName}}")] {{#deprecated}} [Obsolete] {{/deprecated}} diff --git a/templates/csharp/modelOneOf.mustache b/templates/csharp/modelOneOf.mustache index 1179311fab..b80aa230a0 100644 --- a/templates/csharp/modelOneOf.mustache +++ b/templates/csharp/modelOneOf.mustache @@ -159,7 +159,15 @@ {{#composedSchemas.oneOf}} try { - return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, AdditionalPropertiesSerializerSettings)); + // if it does not contains "AdditionalProperties", use SerializerSettings to deserialize + if (typeof({{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}).GetProperty("AdditionalProperties") == null) + { + return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings)); + } + else + { + return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings)); + } } catch (Exception exception) { diff --git a/templates/csharp/tests/requests/requests.mustache b/templates/csharp/tests/requests/requests.mustache index b4fb89727f..4cc5ad5b0e 100644 --- a/templates/csharp/tests/requests/requests.mustache +++ b/templates/csharp/tests/requests/requests.mustache @@ -18,7 +18,8 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; _client = new {{client}}(new {{clientPrefix}}Config("appId", "apiKey"{{#hasRegionalHost}},"{{defaultRegion}}"{{/hasRegionalHost}}), _echo); {{#hasE2E}} - DotEnv.Load(); + DotEnv.Load(options: new DotEnvOptions(ignoreExceptions: false, probeForEnv: true, probeLevelsToSearch: 8, envFilePaths: new[] { ".env" })); + var e2EAppId = Environment.GetEnvironmentVariable("ALGOLIA_APPLICATION_ID"); if (e2EAppId == null) { @@ -113,7 +114,7 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; {{/statusCode}} {{#body}} - JsonAssert.EqualOverrideDefault("{{#lambda.escapeQuotes}}{{{.}}}{{/lambda.escapeQuotes}}", JsonConvert.SerializeObject(resp), new JsonDiffConfig(true)); + JsonAssert.EqualOverrideDefault("{{#lambda.escapeQuotes}}{{{.}}}{{/lambda.escapeQuotes}}", JsonConvert.SerializeObject(resp, settings: JsonConfig.AlgoliaJsonSerializerSettings), new JsonDiffConfig(true)); {{/body}} } catch (Exception e) { From 9086f9e6828ea2462f437465d6696ff26c6e02fe Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Wed, 31 Jan 2024 14:57:53 +0100 Subject: [PATCH 02/15] wip --- playground/csharp/WorkerService1/Program.cs | 8 ----- .../Properties/launchSettings.json | 12 ------- playground/csharp/WorkerService1/Worker.cs | 31 ------------------- .../WorkerService1/WorkerService1.csproj | 17 ---------- .../appsettings.Development.json | 8 ----- 5 files changed, 76 deletions(-) delete mode 100644 playground/csharp/WorkerService1/Program.cs delete mode 100644 playground/csharp/WorkerService1/Properties/launchSettings.json delete mode 100644 playground/csharp/WorkerService1/Worker.cs delete mode 100644 playground/csharp/WorkerService1/WorkerService1.csproj delete mode 100644 playground/csharp/WorkerService1/appsettings.Development.json diff --git a/playground/csharp/WorkerService1/Program.cs b/playground/csharp/WorkerService1/Program.cs deleted file mode 100644 index bae56c14fc..0000000000 --- a/playground/csharp/WorkerService1/Program.cs +++ /dev/null @@ -1,8 +0,0 @@ -using WorkerService1; - -var builder = Host.CreateApplicationBuilder(args); -builder.Services.AddHostedService(); -builder.Logging.AddFilter("Algolia", LogLevel.Information).AddConsole(); - -var host = builder.Build(); -host.Run(); diff --git a/playground/csharp/WorkerService1/Properties/launchSettings.json b/playground/csharp/WorkerService1/Properties/launchSettings.json deleted file mode 100644 index e5d9dbdb85..0000000000 --- a/playground/csharp/WorkerService1/Properties/launchSettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "WorkerService1": { - "commandName": "Project", - "dotnetRunMessages": true, - "environmentVariables": { - "DOTNET_ENVIRONMENT": "Development" - } - } - } -} diff --git a/playground/csharp/WorkerService1/Worker.cs b/playground/csharp/WorkerService1/Worker.cs deleted file mode 100644 index 0b9170d7af..0000000000 --- a/playground/csharp/WorkerService1/Worker.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Algolia.Search.Clients; -using Algolia.Search.Models.Search; - -namespace WorkerService1; - -public class Worker : BackgroundService -{ - private readonly ILogger _logger; - private readonly SearchClient _searchClient; - - public Worker(ILogger logger) - { - _logger = logger; - _searchClient = new SearchClient("test-app-id", "test-api-key"); - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - await _searchClient.SearchSingleIndexAsync("test", new SearchParams(new SearchParamsObject() { Query = "" }), cancellationToken: stoppingToken); - - while (!stoppingToken.IsCancellationRequested) - { - if (_logger.IsEnabled(LogLevel.Information)) - { - _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); - } - - await Task.Delay(1000, stoppingToken); - } - } -} diff --git a/playground/csharp/WorkerService1/WorkerService1.csproj b/playground/csharp/WorkerService1/WorkerService1.csproj deleted file mode 100644 index b7b02fea4e..0000000000 --- a/playground/csharp/WorkerService1/WorkerService1.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net8.0 - enable - enable - dotnet-WorkerService1-CB087983-1F62-46D2-B8A7-8D0DD04F82FF - - - - - - - - - - diff --git a/playground/csharp/WorkerService1/appsettings.Development.json b/playground/csharp/WorkerService1/appsettings.Development.json deleted file mode 100644 index b2dcdb6742..0000000000 --- a/playground/csharp/WorkerService1/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - } -} From 85a421d44a700d0f300cc3edf6f5a88304328372 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Mon, 5 Feb 2024 15:58:08 +0100 Subject: [PATCH 03/15] review --- playground/csharp/Algolia.sln | 6 + .../csharp/Performaces/Performaces.csproj | 4 + playground/csharp/Performaces/Program.cs | 168 +++++----- .../PerformanceLegacy/Data/searchResult.json | 311 ++++++++++++++++++ .../PerformanceLegacy/Model/TestObject.cs | 7 + .../PerformanceLegacy.csproj | 16 +- .../csharp/PerformanceLegacy/Program.cs | 212 +++++++++--- .../csharp/tests/requests/requests.mustache | 1 + 8 files changed, 609 insertions(+), 116 deletions(-) create mode 100644 playground/csharp/PerformanceLegacy/Data/searchResult.json create mode 100644 playground/csharp/PerformanceLegacy/Model/TestObject.cs diff --git a/playground/csharp/Algolia.sln b/playground/csharp/Algolia.sln index 77385ce818..cd04630b9f 100644 --- a/playground/csharp/Algolia.sln +++ b/playground/csharp/Algolia.sln @@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Performaces", "Performaces\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceLegacy", "PerformanceLegacy\PerformanceLegacy.csproj", "{67814440-28A1-4344-873A-2E1F6F2FAAAC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search", "..\..\..\..\RiderProjects\algoliasearch-client-csharp\src\Algolia.Search\Algolia.Search.csproj", "{FA9B6991-346D-4C75-A63C-01CD6B207A47}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -36,5 +38,9 @@ Global {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.ActiveCfg = Release|Any CPU {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.Build.0 = Release|Any CPU + {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/playground/csharp/Performaces/Performaces.csproj b/playground/csharp/Performaces/Performaces.csproj index 93ea135f50..dc7200b91a 100644 --- a/playground/csharp/Performaces/Performaces.csproj +++ b/playground/csharp/Performaces/Performaces.csproj @@ -21,4 +21,8 @@ + + + + diff --git a/playground/csharp/Performaces/Program.cs b/playground/csharp/Performaces/Program.cs index c21e36fecc..b5dbc712c0 100644 --- a/playground/csharp/Performaces/Program.cs +++ b/playground/csharp/Performaces/Program.cs @@ -9,7 +9,7 @@ using Action = Algolia.Search.Models.Search.Action; var server = WireMockServer.Start(); -var client = new SearchClient(new SearchConfig("XXX", "XXXX") +var client = new SearchClient(new SearchConfig("FakeAppID", "FakeApiKey") { CustomHosts = [ @@ -26,6 +26,7 @@ var searchResults = File.ReadAllText("Data/searchResult.json"); + server .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/query").UsingPost()) .RespondWith( @@ -34,21 +35,28 @@ .WithBody(searchResults) ); -var batchResponse = new BatchResponse(1, new List()); server .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/batch").UsingPost()) .RespondWith( Response.Create() .WithStatusCode(200) - .WithBody(JsonConvert.SerializeObject(batchResponse)) + .WithBody(JsonConvert.SerializeObject(new BatchResponse(1, new List()))) ); -Console.WriteLine("Starting..."); +Console.WriteLine("Starting performance tests..."); + +Console.WriteLine("----------------"); +Console.WriteLine("---- Search ----"); +Console.WriteLine("----------------"); +const int iterations = 10000; Stopwatch stopwatch = new(); + +Console.WriteLine($"Calling SearchAsync {iterations} times, with a response payload of {searchResults.Length / 1024} ko"); + stopwatch.Start(); -for (var i = 0; i < 100; i++) +for (var i = 0; i < iterations; i++) { await client .SearchSingleIndexAsync("test-csharp-new-client", new SearchParams(new SearchParamsObject())); @@ -61,10 +69,16 @@ await client Console.WriteLine(); -Console.WriteLine("Starting..."); +Console.WriteLine("-----------------------------------"); +Console.WriteLine("---- Save records, using Batch ----"); +Console.WriteLine("-----------------------------------"); + +const int iterationsBatch = 100; +const int iterationsRecords = 1000; +Console.WriteLine($"Saving {iterationsBatch*iterationsRecords} records by calling BatchAsync {iterationsBatch} times, with request payload containing {iterationsRecords} record of {JsonConvert.SerializeObject(CreateBody(0)).Length / 1024} ko."); stopwatch.Restart(); -for (var i = 0; i < 100; i++) +for (var i = 0; i < iterationsBatch; i++) { await client .BatchAsync("test-csharp-new-client", new BatchWriteParams(CreateRequests())).ConfigureAwait(false); @@ -78,76 +92,82 @@ List CreateRequests() { var requests = new List(); - for (var i = 0; i < 100; i++) + for (var i = 0; i < iterationsRecords; i++) { + var batchRequest = new BatchRequest() + { + Action = Action.AddObject, + Body = CreateBody(i) + }; requests.Add( - new() - { - Action = Action.AddObject, - Body = new - { - objectID = Guid.NewGuid(), - name = "Test" + i, - age = i, - city = "Paris", - country = "France", - hobbies = new[] { "sport", "music" }, - friends = new[] - { - new { name = "John", age = 42 }, - new { name = "Paul", age = 32 } - }, - company = new { name = "Algolia", country = "France", city = "Paris" }, - email = "test" + i + "@algolia.com", - objectIDWithNumbers = "42", - objectIDWithDates = "2020-01-01T00:00:00Z", - objectIDWithBoolean = "true", - objectIDWithArray = "[]", - objectIDWithObject = "{}", - objectIDWithNull = "null", - objectIDWithGeoPoint = "48.8584,2.2945", - objectIDWithGeoJSON = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON1 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON2 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON3 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON4 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON5 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON6 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON7 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON8 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON9 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithPolygon1 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon2 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon3 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon4 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon5 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon6 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon7 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon8 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon9 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon10 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithNullGeoPoint = "null", - objectIDWithNullGeoJSON = "null", - objectIDWithNullPolygon = "null", - objectIDWithEmptyGeoPoint = "", - objectIDWithEmptyGeoJSON = "", - objectIDWithEmptyPolygon = "", - objectIDWithEmptyArray = "", - objectIDWithEmptyObject = "", - objectIDWithEmptyString = "", - objectIDWithEmptyBoolean = "", - objectIDWithEmptyNull = "", - objectIDWithEmptyNumber = "", - objectIDWithEmptyDate = "", - objectIDWithEmptyPolygonArray = "", - objectIDWithEmptyGeoPointArray = "", - objectIDWithEmptyGeoJSONArray = "", - objectIDWithEmptyNullArray = "", - objectIDWithEmptyStringArray = "", - objectIDWithEmptyBooleanArray = "", - } - }); + batchRequest); } return requests; } + +object CreateBody(int i1) +{ + return new + { + objectID = Guid.NewGuid(), + name = "Test" + i1, + age = i1, + city = "Paris", + country = "France", + hobbies = new[] { "sport", "music" }, + friends = new[] + { + new { name = "John", age = 42 }, + new { name = "Paul", age = 32 } + }, + company = new { name = "Algolia", country = "France", city = "Paris" }, + email = "test" + i1 + "@algolia.com", + objectIDWithNumbers = "42", + objectIDWithDates = "2020-01-01T00:00:00Z", + objectIDWithBoolean = "true", + objectIDWithArray = "[]", + objectIDWithObject = "{}", + objectIDWithNull = "null", + objectIDWithGeoPoint = "48.8584,2.2945", + objectIDWithGeoJSON = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON1 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON2 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON3 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON4 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON5 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON6 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON7 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON8 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON9 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithPolygon1 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon2 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon3 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon4 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon5 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon6 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon7 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon8 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon9 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon10 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithNullGeoPoint = "null", + objectIDWithNullGeoJSON = "null", + objectIDWithNullPolygon = "null", + objectIDWithEmptyGeoPoint = "", + objectIDWithEmptyGeoJSON = "", + objectIDWithEmptyPolygon = "", + objectIDWithEmptyArray = "", + objectIDWithEmptyObject = "", + objectIDWithEmptyString = "", + objectIDWithEmptyBoolean = "", + objectIDWithEmptyNull = "", + objectIDWithEmptyNumber = "", + objectIDWithEmptyDate = "", + objectIDWithEmptyPolygonArray = "", + objectIDWithEmptyGeoPointArray = "", + objectIDWithEmptyGeoJSONArray = "", + objectIDWithEmptyNullArray = "", + objectIDWithEmptyStringArray = "", + objectIDWithEmptyBooleanArray = "", + }; +} diff --git a/playground/csharp/PerformanceLegacy/Data/searchResult.json b/playground/csharp/PerformanceLegacy/Data/searchResult.json new file mode 100644 index 0000000000..46bd8e883c --- /dev/null +++ b/playground/csharp/PerformanceLegacy/Data/searchResult.json @@ -0,0 +1,311 @@ +{ + "hits": [ + { + "value": "batch3", + "otherValue": "otherValue3", + "objectID": "test5", + "_snippetResult": { + "value": { + "value": "batch3", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue3", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch3", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue3", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 3, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "batch2", + "otherValue": "otherValue2", + "objectID": "test4", + "_snippetResult": { + "value": { + "value": "batch2", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue2", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch2", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue2", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 2, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "batch1", + "otherValue": "otherValue1", + "objectID": "test3", + "_snippetResult": { + "value": { + "value": "batch1", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue1", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "batch1", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue1", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 1, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + }, + { + "value": "test", + "otherValue": "otherValue", + "objectID": "test2", + "_snippetResult": { + "value": { + "value": "test", + "matchLevel": "none" + }, + "otherValue": { + "value": "otherValue", + "matchLevel": "none" + } + }, + "_highlightResult": { + "value": { + "value": "test", + "matchLevel": "none", + "matchedWords": [] + }, + "otherValue": { + "value": "otherValue", + "matchLevel": "none", + "matchedWords": [] + } + }, + "_rankingInfo": { + "nbTypos": 0, + "firstMatchedWord": 0, + "proximityDistance": 0, + "userScore": 0, + "geoDistance": 0, + "geoPrecision": 0, + "nbExactWords": 0, + "words": 0, + "filters": 0 + } + } + ], + "nbHits": 4, + "page": 0, + "nbPages": 1, + "hitsPerPage": 10, + "facets": { + "value": { + "batch1": 1, + "batch2": 1, + "batch3": 1, + "test": 1 + }, + "otherValue": { + "otherValue": 1, + "otherValue1": 1, + "otherValue2": 1, + "otherValue3": 1 + } + }, + "exhaustiveFacetsCount": true, + "exhaustiveNbHits": true, + "exhaustiveTypo": true, + "exhaustive": { + "facetsCount": true, + "nbHits": true, + "typo": true + }, + "query": "", + "params": "analytics=false&attributesToRetrieve=%5B%22*%22%5D&attributesToSnippet=%5B%22*%3A20%22%5D&enableABTest=false&explain=%5B%22*%22%5D&facets=%5B%22*%22%5D&getRankingInfo=true&highlightPostTag=%3C%2Fais-highlight-0%3E&highlightPreTag=%3Cais-highlight-0%3E&hitsPerPage=10&maxValuesPerFacet=100&page=0&query=&responseFields=%5B%22*%22%5D&snippetEllipsisText=%E2%80%A6&tagFilters=", + "index": "test-csharp-new-client", + "serverUsed": "c42-eu-3.algolia.net", + "indexUsed": "test-csharp-new-client", + "parsedQuery": "", + "timeoutCounts": false, + "timeoutHits": false, + "explain": { + "match": { + "alternatives": [] + }, + "params": { + "client": { + "query": "", + "analytics": false, + "page": 0, + "hitsPerPage": 10, + "attributesToRetrieve": [ + "*" + ], + "attributesToSnippet": [ + "*:20" + ], + "getRankingInfo": true, + "highlightPreTag": "", + "highlightPostTag": "", + "snippetEllipsisText": "…", + "tagFilters": [], + "facets": [ + "*" + ], + "maxValuesPerFacet": 100, + "responseFields": [ + "exhaustive", + "exhaustiveFacetValues", + "facets_stats", + "extensions", + "renderingContent", + "userData", + "aroundLatLng", + "queryAfterRemoval", + "exhaustiveFacetsCount", + "length", + "params", + "processingTimingsMS", + "facets", + "offset", + "hitsPerPage", + "automaticRadius", + "processingTimeMS", + "nbPages", + "page", + "query", + "serverTimeMS", + "index", + "exhaustiveTypo", + "nbHits", + "exhaustiveNbHits", + "hits" + ], + "enableABTest": false, + "explain": true + }, + "apiKey": {}, + "abTest": {}, + "rules": {}, + "final": { + "query": "", + "analytics": false, + "page": 0, + "hitsPerPage": 10, + "attributesToRetrieve": [ + "*" + ], + "attributesToSnippet": [ + "*:20" + ], + "getRankingInfo": true, + "highlightPreTag": "", + "highlightPostTag": "", + "snippetEllipsisText": "…", + "tagFilters": [], + "facets": [ + "*" + ], + "maxValuesPerFacet": 100, + "responseFields": [ + "exhaustive", + "exhaustiveFacetValues", + "facets_stats", + "extensions", + "renderingContent", + "userData", + "aroundLatLng", + "queryAfterRemoval", + "exhaustiveFacetsCount", + "length", + "params", + "processingTimingsMS", + "facets", + "offset", + "hitsPerPage", + "automaticRadius", + "processingTimeMS", + "nbPages", + "page", + "query", + "serverTimeMS", + "index", + "exhaustiveTypo", + "nbHits", + "exhaustiveNbHits", + "hits" + ], + "enableABTest": false, + "explain": true + } + } + }, + "renderingContent": {}, + "processingTimeMS": 1, + "processingTimingsMS": { + "_request": { + "queue": 4, + "roundTrip": 16 + } + }, + "serverTimeMS": 5 +} diff --git a/playground/csharp/PerformanceLegacy/Model/TestObject.cs b/playground/csharp/PerformanceLegacy/Model/TestObject.cs new file mode 100644 index 0000000000..7566d6187d --- /dev/null +++ b/playground/csharp/PerformanceLegacy/Model/TestObject.cs @@ -0,0 +1,7 @@ +using Algolia.Search.Models.Search; + +public class TestObject +{ + public string? value { get; set; } + public string? otherValue { get; set; } +} diff --git a/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj b/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj index c42371e037..34dd9932ff 100644 --- a/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj +++ b/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj @@ -8,7 +8,21 @@ - + + + + + + PreserveNewest + + + + + + + + + diff --git a/playground/csharp/PerformanceLegacy/Program.cs b/playground/csharp/PerformanceLegacy/Program.cs index e3abdecee3..6ecd88efcf 100644 --- a/playground/csharp/PerformanceLegacy/Program.cs +++ b/playground/csharp/PerformanceLegacy/Program.cs @@ -1,48 +1,178 @@ -// See https://aka.ms/new-console-template for more information - -using System.Diagnostics; +using System.Diagnostics; using Algolia.Search.Clients; +using Algolia.Search.Models.Batch; +using Algolia.Search.Models.Common; +using Algolia.Search.Models.Enums; using Algolia.Search.Models.Search; +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; +using Newtonsoft.Json; +using WireMock.ResponseBuilders; +using WireMock.Server; +using HttpScheme = Algolia.Search.Transport.HttpScheme; +using Request = WireMock.RequestBuilders.Request; + +var server = WireMockServer.Start(); +var client = new SearchClient(new SearchConfig("FakeAppID", "FakeApiKey") +{ + CustomHosts = + [ + new() + { + Scheme = HttpScheme.Http, + Port = server.Port, + Url = "localhost", + Accept = CallType.Read | CallType.Write, + Up = true + } + ] +}); + +var searchIndex = client.InitIndex("test-csharp-new-client"); + +var searchResults = File.ReadAllText("Data/searchResult.json"); + +server + .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/query").UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(searchResults) + ); + +server + .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/batch").UsingPost()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(JsonConvert.SerializeObject(new BatchResponse() { })) + ); -Console.WriteLine("Hello, World!"); - -// dotnet dev-certs https -// dotnet dev-certs https --trust - -// var server = WireMockServer.Start(); -// -// -// server -// .Given(Request.Create().WithPath("/1/indexes/test/query").UsingPost()) -// .RespondWith( -// Response.Create() -// .WithStatusCode(200) -// .WithBody(@"{ ""params"": "" "", ""query"": "" "", ""processingTimeMS"": ""2"", ""hitsPerPage"": ""2"", ""nbHits"": ""10"", ""page"": ""0"", ""nbPages"": ""5"", ""hits"": [ { ""firstname"": ""Jimmie"", ""lastname"": ""Barninger"", ""objectID"": ""433"" }, { ""firstname"": ""Warren"", ""lastname"": ""Speach"", ""objectID"": ""2"" } ] }") -// ); - -var client = new SearchClient(new SearchConfig("LEKUUYKIXX", "XXX")); -// { -// CustomHosts = -// [ -// new() -// { -// Scheme = HttpScheme.Http, -// Port = server.Port, -// Url = "localhost", -// Accept = CallType.Read | CallType.Write, -// Up = true -// } -// ] -// }); - -for (int i = 0; i < 5; i++) + +Console.WriteLine("Starting performance tests..."); + +Console.WriteLine("----------------"); +Console.WriteLine("---- Search ----"); +Console.WriteLine("----------------"); + +const int iterations = 10000; +Stopwatch stopwatch = new(); + +Console.WriteLine( + $"Calling SearchAsync {iterations} times, with a response payload of {searchResults.Length / 1024} ko"); + +stopwatch.Start(); +for (var i = 0; i < iterations; i++) { - Stopwatch stopwatch = new(); - stopwatch.Start(); + await searchIndex.SearchAsync(new Query()); +} + +stopwatch.Stop(); +Console.WriteLine( + $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); - var searchIndex = client.InitIndex("test-csharp-new-client"); - var searchResponse = await searchIndex.SearchAsync(new Query() { }).ConfigureAwait(false); +Console.WriteLine(); - stopwatch.Stop(); - Console.WriteLine($"Elapsed: {stopwatch.ElapsedMilliseconds}ms " + searchResponse.Hits.Count); + +Console.WriteLine("-----------------------------------"); +Console.WriteLine("---- Save records, using Batch ----"); +Console.WriteLine("-----------------------------------"); + +const int iterationsBatch = 100; +const int iterationsRecords = 1000; +Console.WriteLine( + $"Saving {iterationsBatch * iterationsRecords} records by calling BatchAsync {iterationsBatch} times, with request payload containing {iterationsRecords} record of {JsonConvert.SerializeObject(CreateBody(0)).Length / 1024} ko."); + +stopwatch.Restart(); +for (var i = 0; i < iterationsBatch; i++) +{ + await searchIndex + .BatchAsync(CreateRequests()); +} + +stopwatch.Stop(); +Console.WriteLine( + $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); + +List> CreateRequests() +{ + var requests = new List>(); + + for (var i = 0; i < iterationsRecords; i++) + { + var batchRequest = new BatchOperation + { + Action = BatchActionType.AddObject, + Body = CreateBody(i) + }; + requests.Add( + batchRequest); + } + + return requests; +} + +object CreateBody(int i1) +{ + return new + { + objectID = Guid.NewGuid(), + name = "Test" + i1, + age = i1, + city = "Paris", + country = "France", + hobbies = new[] { "sport", "music" }, + friends = new[] + { + new { name = "John", age = 42 }, + new { name = "Paul", age = 32 } + }, + company = new { name = "Algolia", country = "France", city = "Paris" }, + email = "test" + i1 + "@algolia.com", + objectIDWithNumbers = "42", + objectIDWithDates = "2020-01-01T00:00:00Z", + objectIDWithBoolean = "true", + objectIDWithArray = "[]", + objectIDWithObject = "{}", + objectIDWithNull = "null", + objectIDWithGeoPoint = "48.8584,2.2945", + objectIDWithGeoJSON = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON1 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON2 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON3 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON4 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON5 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON6 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON7 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON8 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithGeoJSON9 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", + objectIDWithPolygon1 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon2 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon3 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon4 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon5 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon6 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon7 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon8 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon9 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithPolygon10 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", + objectIDWithNullGeoPoint = "null", + objectIDWithNullGeoJSON = "null", + objectIDWithNullPolygon = "null", + objectIDWithEmptyGeoPoint = "", + objectIDWithEmptyGeoJSON = "", + objectIDWithEmptyPolygon = "", + objectIDWithEmptyArray = "", + objectIDWithEmptyObject = "", + objectIDWithEmptyString = "", + objectIDWithEmptyBoolean = "", + objectIDWithEmptyNull = "", + objectIDWithEmptyNumber = "", + objectIDWithEmptyDate = "", + objectIDWithEmptyPolygonArray = "", + objectIDWithEmptyGeoPointArray = "", + objectIDWithEmptyGeoJSONArray = "", + objectIDWithEmptyNullArray = "", + objectIDWithEmptyStringArray = "", + objectIDWithEmptyBooleanArray = "", + }; } diff --git a/templates/csharp/tests/requests/requests.mustache b/templates/csharp/tests/requests/requests.mustache index 4cc5ad5b0e..8b344dcd06 100644 --- a/templates/csharp/tests/requests/requests.mustache +++ b/templates/csharp/tests/requests/requests.mustache @@ -1,6 +1,7 @@ using Algolia.Search.Http; using Algolia.Search.Clients; using Algolia.Search.Models.{{clientPrefix}}; +using Algolia.Search.Serializer; using Xunit; using Newtonsoft.Json; using Quibble.Xunit; From 2e08dc0804b21baa164a20357712c0352ee0f9e8 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 16:25:58 +0100 Subject: [PATCH 04/15] remove duplicate From e3a2dd431232d34961e2e677fc70594a8ef9460d Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 16:41:35 +0100 Subject: [PATCH 05/15] remove duplicate --- .../algoliasearch/Models/AbstractSchema.cs | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 clients/algoliasearch-client-csharp/algoliasearch/Models/AbstractSchema.cs diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Models/AbstractSchema.cs b/clients/algoliasearch-client-csharp/algoliasearch/Models/AbstractSchema.cs deleted file mode 100644 index 586c2944e1..0000000000 --- a/clients/algoliasearch-client-csharp/algoliasearch/Models/AbstractSchema.cs +++ /dev/null @@ -1,70 +0,0 @@ -// -// Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT. -// - -using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Algolia.Search.Models -{ - /// - /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification - /// - public abstract partial class AbstractSchema - { - /// - /// Custom JSON serializer - /// - static public readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings - { - // OpenAPI generated types generally hide default constructors. - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, - MissingMemberHandling = MissingMemberHandling.Error, - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new CamelCaseNamingStrategy - { - OverrideSpecifiedNames = false - } - } - }; - - /// - /// Custom JSON serializer for objects with additional properties - /// - static public readonly JsonSerializerSettings AdditionalPropertiesSerializerSettings = new JsonSerializerSettings - { - // OpenAPI generated types generally hide default constructors. - ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, - MissingMemberHandling = MissingMemberHandling.Ignore, - ContractResolver = new DefaultContractResolver - { - NamingStrategy = new CamelCaseNamingStrategy - { - OverrideSpecifiedNames = false - } - } - }; - - /// - /// Gets or Sets the actual instance - /// - public abstract Object ActualInstance { get; set; } - - /// - /// Gets or Sets IsNullable to indicate whether the instance is nullable - /// - public bool IsNullable { get; protected set; } - - /// - /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf` - /// - public string SchemaType { get; protected set; } - - /// - /// Converts the instance into JSON string. - /// - public abstract string ToJson(); - } -} From c740b8d624cb9635c8964c8339efea0014a9a516 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 16:44:55 +0100 Subject: [PATCH 06/15] remove legacy playground --- .../Algolia-Old-Client.csproj | 15 - .../csharp/Algolia-Old-Client/Program.cs | 13 - .../PerformanceLegacy/Data/searchResult.json | 311 ------------------ .../PerformanceLegacy/Model/TestObject.cs | 7 - .../PerformanceLegacy.csproj | 28 -- .../csharp/PerformanceLegacy/Program.cs | 178 ---------- 6 files changed, 552 deletions(-) delete mode 100644 playground/csharp/Algolia-Old-Client/Algolia-Old-Client.csproj delete mode 100644 playground/csharp/Algolia-Old-Client/Program.cs delete mode 100644 playground/csharp/PerformanceLegacy/Data/searchResult.json delete mode 100644 playground/csharp/PerformanceLegacy/Model/TestObject.cs delete mode 100644 playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj delete mode 100644 playground/csharp/PerformanceLegacy/Program.cs diff --git a/playground/csharp/Algolia-Old-Client/Algolia-Old-Client.csproj b/playground/csharp/Algolia-Old-Client/Algolia-Old-Client.csproj deleted file mode 100644 index 5d82839e89..0000000000 --- a/playground/csharp/Algolia-Old-Client/Algolia-Old-Client.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net8.0 - Algolia_Old_Client - enable - enable - - - - - - - diff --git a/playground/csharp/Algolia-Old-Client/Program.cs b/playground/csharp/Algolia-Old-Client/Program.cs deleted file mode 100644 index e58960d7bb..0000000000 --- a/playground/csharp/Algolia-Old-Client/Program.cs +++ /dev/null @@ -1,13 +0,0 @@ -// See https://aka.ms/new-console-template for more information - -using Algolia.Search.Clients; - -Console.WriteLine("Hello, World!"); - -var searchClient = new SearchClient("NIOXZRNMTV", "XXX"); - -var index = searchClient.InitIndex("test-csharp-legacy-client"); - -var saved = await index.SaveObjectAsync(new { ObjectID = "test", value = "test" }); - -Console.WriteLine(saved); diff --git a/playground/csharp/PerformanceLegacy/Data/searchResult.json b/playground/csharp/PerformanceLegacy/Data/searchResult.json deleted file mode 100644 index 46bd8e883c..0000000000 --- a/playground/csharp/PerformanceLegacy/Data/searchResult.json +++ /dev/null @@ -1,311 +0,0 @@ -{ - "hits": [ - { - "value": "batch3", - "otherValue": "otherValue3", - "objectID": "test5", - "_snippetResult": { - "value": { - "value": "batch3", - "matchLevel": "none" - }, - "otherValue": { - "value": "otherValue3", - "matchLevel": "none" - } - }, - "_highlightResult": { - "value": { - "value": "batch3", - "matchLevel": "none", - "matchedWords": [] - }, - "otherValue": { - "value": "otherValue3", - "matchLevel": "none", - "matchedWords": [] - } - }, - "_rankingInfo": { - "nbTypos": 0, - "firstMatchedWord": 0, - "proximityDistance": 0, - "userScore": 3, - "geoDistance": 0, - "geoPrecision": 0, - "nbExactWords": 0, - "words": 0, - "filters": 0 - } - }, - { - "value": "batch2", - "otherValue": "otherValue2", - "objectID": "test4", - "_snippetResult": { - "value": { - "value": "batch2", - "matchLevel": "none" - }, - "otherValue": { - "value": "otherValue2", - "matchLevel": "none" - } - }, - "_highlightResult": { - "value": { - "value": "batch2", - "matchLevel": "none", - "matchedWords": [] - }, - "otherValue": { - "value": "otherValue2", - "matchLevel": "none", - "matchedWords": [] - } - }, - "_rankingInfo": { - "nbTypos": 0, - "firstMatchedWord": 0, - "proximityDistance": 0, - "userScore": 2, - "geoDistance": 0, - "geoPrecision": 0, - "nbExactWords": 0, - "words": 0, - "filters": 0 - } - }, - { - "value": "batch1", - "otherValue": "otherValue1", - "objectID": "test3", - "_snippetResult": { - "value": { - "value": "batch1", - "matchLevel": "none" - }, - "otherValue": { - "value": "otherValue1", - "matchLevel": "none" - } - }, - "_highlightResult": { - "value": { - "value": "batch1", - "matchLevel": "none", - "matchedWords": [] - }, - "otherValue": { - "value": "otherValue1", - "matchLevel": "none", - "matchedWords": [] - } - }, - "_rankingInfo": { - "nbTypos": 0, - "firstMatchedWord": 0, - "proximityDistance": 0, - "userScore": 1, - "geoDistance": 0, - "geoPrecision": 0, - "nbExactWords": 0, - "words": 0, - "filters": 0 - } - }, - { - "value": "test", - "otherValue": "otherValue", - "objectID": "test2", - "_snippetResult": { - "value": { - "value": "test", - "matchLevel": "none" - }, - "otherValue": { - "value": "otherValue", - "matchLevel": "none" - } - }, - "_highlightResult": { - "value": { - "value": "test", - "matchLevel": "none", - "matchedWords": [] - }, - "otherValue": { - "value": "otherValue", - "matchLevel": "none", - "matchedWords": [] - } - }, - "_rankingInfo": { - "nbTypos": 0, - "firstMatchedWord": 0, - "proximityDistance": 0, - "userScore": 0, - "geoDistance": 0, - "geoPrecision": 0, - "nbExactWords": 0, - "words": 0, - "filters": 0 - } - } - ], - "nbHits": 4, - "page": 0, - "nbPages": 1, - "hitsPerPage": 10, - "facets": { - "value": { - "batch1": 1, - "batch2": 1, - "batch3": 1, - "test": 1 - }, - "otherValue": { - "otherValue": 1, - "otherValue1": 1, - "otherValue2": 1, - "otherValue3": 1 - } - }, - "exhaustiveFacetsCount": true, - "exhaustiveNbHits": true, - "exhaustiveTypo": true, - "exhaustive": { - "facetsCount": true, - "nbHits": true, - "typo": true - }, - "query": "", - "params": "analytics=false&attributesToRetrieve=%5B%22*%22%5D&attributesToSnippet=%5B%22*%3A20%22%5D&enableABTest=false&explain=%5B%22*%22%5D&facets=%5B%22*%22%5D&getRankingInfo=true&highlightPostTag=%3C%2Fais-highlight-0%3E&highlightPreTag=%3Cais-highlight-0%3E&hitsPerPage=10&maxValuesPerFacet=100&page=0&query=&responseFields=%5B%22*%22%5D&snippetEllipsisText=%E2%80%A6&tagFilters=", - "index": "test-csharp-new-client", - "serverUsed": "c42-eu-3.algolia.net", - "indexUsed": "test-csharp-new-client", - "parsedQuery": "", - "timeoutCounts": false, - "timeoutHits": false, - "explain": { - "match": { - "alternatives": [] - }, - "params": { - "client": { - "query": "", - "analytics": false, - "page": 0, - "hitsPerPage": 10, - "attributesToRetrieve": [ - "*" - ], - "attributesToSnippet": [ - "*:20" - ], - "getRankingInfo": true, - "highlightPreTag": "", - "highlightPostTag": "", - "snippetEllipsisText": "…", - "tagFilters": [], - "facets": [ - "*" - ], - "maxValuesPerFacet": 100, - "responseFields": [ - "exhaustive", - "exhaustiveFacetValues", - "facets_stats", - "extensions", - "renderingContent", - "userData", - "aroundLatLng", - "queryAfterRemoval", - "exhaustiveFacetsCount", - "length", - "params", - "processingTimingsMS", - "facets", - "offset", - "hitsPerPage", - "automaticRadius", - "processingTimeMS", - "nbPages", - "page", - "query", - "serverTimeMS", - "index", - "exhaustiveTypo", - "nbHits", - "exhaustiveNbHits", - "hits" - ], - "enableABTest": false, - "explain": true - }, - "apiKey": {}, - "abTest": {}, - "rules": {}, - "final": { - "query": "", - "analytics": false, - "page": 0, - "hitsPerPage": 10, - "attributesToRetrieve": [ - "*" - ], - "attributesToSnippet": [ - "*:20" - ], - "getRankingInfo": true, - "highlightPreTag": "", - "highlightPostTag": "", - "snippetEllipsisText": "…", - "tagFilters": [], - "facets": [ - "*" - ], - "maxValuesPerFacet": 100, - "responseFields": [ - "exhaustive", - "exhaustiveFacetValues", - "facets_stats", - "extensions", - "renderingContent", - "userData", - "aroundLatLng", - "queryAfterRemoval", - "exhaustiveFacetsCount", - "length", - "params", - "processingTimingsMS", - "facets", - "offset", - "hitsPerPage", - "automaticRadius", - "processingTimeMS", - "nbPages", - "page", - "query", - "serverTimeMS", - "index", - "exhaustiveTypo", - "nbHits", - "exhaustiveNbHits", - "hits" - ], - "enableABTest": false, - "explain": true - } - } - }, - "renderingContent": {}, - "processingTimeMS": 1, - "processingTimingsMS": { - "_request": { - "queue": 4, - "roundTrip": 16 - } - }, - "serverTimeMS": 5 -} diff --git a/playground/csharp/PerformanceLegacy/Model/TestObject.cs b/playground/csharp/PerformanceLegacy/Model/TestObject.cs deleted file mode 100644 index 7566d6187d..0000000000 --- a/playground/csharp/PerformanceLegacy/Model/TestObject.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Algolia.Search.Models.Search; - -public class TestObject -{ - public string? value { get; set; } - public string? otherValue { get; set; } -} diff --git a/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj b/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj deleted file mode 100644 index 34dd9932ff..0000000000 --- a/playground/csharp/PerformanceLegacy/PerformanceLegacy.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - - - - - PreserveNewest - - - - - - - - - - - - diff --git a/playground/csharp/PerformanceLegacy/Program.cs b/playground/csharp/PerformanceLegacy/Program.cs deleted file mode 100644 index 6ecd88efcf..0000000000 --- a/playground/csharp/PerformanceLegacy/Program.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System.Diagnostics; -using Algolia.Search.Clients; -using Algolia.Search.Models.Batch; -using Algolia.Search.Models.Common; -using Algolia.Search.Models.Enums; -using Algolia.Search.Models.Search; -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; -using Newtonsoft.Json; -using WireMock.ResponseBuilders; -using WireMock.Server; -using HttpScheme = Algolia.Search.Transport.HttpScheme; -using Request = WireMock.RequestBuilders.Request; - -var server = WireMockServer.Start(); -var client = new SearchClient(new SearchConfig("FakeAppID", "FakeApiKey") -{ - CustomHosts = - [ - new() - { - Scheme = HttpScheme.Http, - Port = server.Port, - Url = "localhost", - Accept = CallType.Read | CallType.Write, - Up = true - } - ] -}); - -var searchIndex = client.InitIndex("test-csharp-new-client"); - -var searchResults = File.ReadAllText("Data/searchResult.json"); - -server - .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/query").UsingPost()) - .RespondWith( - Response.Create() - .WithStatusCode(200) - .WithBody(searchResults) - ); - -server - .Given(Request.Create().WithPath("/1/indexes/test-csharp-new-client/batch").UsingPost()) - .RespondWith( - Response.Create() - .WithStatusCode(200) - .WithBody(JsonConvert.SerializeObject(new BatchResponse() { })) - ); - - -Console.WriteLine("Starting performance tests..."); - -Console.WriteLine("----------------"); -Console.WriteLine("---- Search ----"); -Console.WriteLine("----------------"); - -const int iterations = 10000; -Stopwatch stopwatch = new(); - -Console.WriteLine( - $"Calling SearchAsync {iterations} times, with a response payload of {searchResults.Length / 1024} ko"); - -stopwatch.Start(); -for (var i = 0; i < iterations; i++) -{ - await searchIndex.SearchAsync(new Query()); -} - -stopwatch.Stop(); -Console.WriteLine( - $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); - -Console.WriteLine(); - - -Console.WriteLine("-----------------------------------"); -Console.WriteLine("---- Save records, using Batch ----"); -Console.WriteLine("-----------------------------------"); - -const int iterationsBatch = 100; -const int iterationsRecords = 1000; -Console.WriteLine( - $"Saving {iterationsBatch * iterationsRecords} records by calling BatchAsync {iterationsBatch} times, with request payload containing {iterationsRecords} record of {JsonConvert.SerializeObject(CreateBody(0)).Length / 1024} ko."); - -stopwatch.Restart(); -for (var i = 0; i < iterationsBatch; i++) -{ - await searchIndex - .BatchAsync(CreateRequests()); -} - -stopwatch.Stop(); -Console.WriteLine( - $"Elapsed: {stopwatch.Elapsed.Seconds} s {stopwatch.Elapsed.Milliseconds} ms {stopwatch.Elapsed.Microseconds} μs"); - -List> CreateRequests() -{ - var requests = new List>(); - - for (var i = 0; i < iterationsRecords; i++) - { - var batchRequest = new BatchOperation - { - Action = BatchActionType.AddObject, - Body = CreateBody(i) - }; - requests.Add( - batchRequest); - } - - return requests; -} - -object CreateBody(int i1) -{ - return new - { - objectID = Guid.NewGuid(), - name = "Test" + i1, - age = i1, - city = "Paris", - country = "France", - hobbies = new[] { "sport", "music" }, - friends = new[] - { - new { name = "John", age = 42 }, - new { name = "Paul", age = 32 } - }, - company = new { name = "Algolia", country = "France", city = "Paris" }, - email = "test" + i1 + "@algolia.com", - objectIDWithNumbers = "42", - objectIDWithDates = "2020-01-01T00:00:00Z", - objectIDWithBoolean = "true", - objectIDWithArray = "[]", - objectIDWithObject = "{}", - objectIDWithNull = "null", - objectIDWithGeoPoint = "48.8584,2.2945", - objectIDWithGeoJSON = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON1 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON2 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON3 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON4 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON5 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON6 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON7 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON8 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithGeoJSON9 = "{\"type\":\"Point\",\"coordinates\":[2.2945,48.8584]}", - objectIDWithPolygon1 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon2 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon3 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon4 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon5 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon6 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon7 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon8 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon9 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithPolygon10 = "[[[-74.0059413,40.7127837],[-74.0059413,40.7127837],[-74.0059413,40.7127837]]]", - objectIDWithNullGeoPoint = "null", - objectIDWithNullGeoJSON = "null", - objectIDWithNullPolygon = "null", - objectIDWithEmptyGeoPoint = "", - objectIDWithEmptyGeoJSON = "", - objectIDWithEmptyPolygon = "", - objectIDWithEmptyArray = "", - objectIDWithEmptyObject = "", - objectIDWithEmptyString = "", - objectIDWithEmptyBoolean = "", - objectIDWithEmptyNull = "", - objectIDWithEmptyNumber = "", - objectIDWithEmptyDate = "", - objectIDWithEmptyPolygonArray = "", - objectIDWithEmptyGeoPointArray = "", - objectIDWithEmptyGeoJSONArray = "", - objectIDWithEmptyNullArray = "", - objectIDWithEmptyStringArray = "", - objectIDWithEmptyBooleanArray = "", - }; -} From 51fd27beadbd55f9eae38e4414e9218b513c5e3a Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 17:00:50 +0100 Subject: [PATCH 07/15] cleanup --- .../Http/AlgoliaHttpRequester.cs | 1 - .../algoliasearch/Http/TimeoutHandler.cs | 1 - .../Models/Common/AbstractSchema.cs | 8 +- .../Serializer/DefaultSerializer.cs | 79 ++----------------- .../algoliasearch/Transport/CallType.cs | 21 +++++ .../algoliasearch/Transport/HttpScheme.cs | 16 ++++ .../algoliasearch/Transport/HttpTransport.cs | 3 +- .../algoliasearch/Transport/StatefulHost.cs | 36 +-------- playground/javascript/node/search.ts | 7 -- 9 files changed, 48 insertions(+), 124 deletions(-) create mode 100644 clients/algoliasearch-client-csharp/algoliasearch/Transport/CallType.cs create mode 100644 clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpScheme.cs diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs index 54587e70ec..6711ac7629 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaHttpRequester.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs b/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs index 48a7cfd500..a05a289279 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Http/TimeoutHandler.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Net.Http; using System.Threading; using System.Threading.Tasks; diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs b/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs index 1a682a3a01..f6f4d33d3c 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Models/Common/AbstractSchema.cs @@ -1,12 +1,6 @@ -// -// Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT. -// - using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -namespace Algolia.Search.Models +namespace Algolia.Search.Models.Common { /// /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs index 88992fdc9f..b48ab8ca0b 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Serializer/DefaultSerializer.cs @@ -1,10 +1,7 @@ using System; -using System.Diagnostics; using System.IO; -using System.Text; using System.Threading.Tasks; using Algolia.Search.Exceptions; -using Algolia.Search.Models; using Algolia.Search.Models.Common; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -13,19 +10,17 @@ namespace Algolia.Search.Serializer; internal class DefaultJsonSerializer : ISerializer { - private readonly JsonSerializerSettings _serializerSettings; private readonly ILogger _logger; - public DefaultJsonSerializer(JsonSerializerSettings serializerSettings, ILoggerFactory logger) + public DefaultJsonSerializer(ILoggerFactory logger) { - _serializerSettings = serializerSettings; _logger = logger.CreateLogger(); } /// /// Serialize the object into a JSON string. /// - /// Object to be serialized. + /// Object to be serialized. /// A JSON string. public string Serialize(object data) { @@ -36,25 +31,7 @@ public string Serialize(object data) return serialize; } - // using (var sw = new StreamWriter(memoryStream)) - // using (var jtw = new JsonTextWriter(sw) { Formatting = Formatting.None }) - // { - // Serializer.MaxDepth = 123456789; - // Serializer.Serialize(jtw, data); - // jtw.Flush(); - // } - // stop.Stop(); - // Console.WriteLine($"Serialize: {stop.ElapsedTicks}ms"); - // - // - // memoryStream.Seek(0, SeekOrigin.Begin); - // Stopwatch stop2 = new Stopwatch(); - // stop2.Start(); - // - // stop2.Stop(); - // Console.WriteLine($"Serialize: {stop2.ElapsedMilliseconds}ms"); - - return JsonConvert.SerializeObject(data, _serializerSettings); + return JsonConvert.SerializeObject(data, JsonConfig.AlgoliaJsonSerializerSettings); } public async Task Deserialize(Stream response) @@ -71,56 +48,12 @@ public async Task Deserialize(Stream response) /// Object representation of the JSON string. private async Task Deserialize(Stream response, Type type) { - if (type == typeof(byte[])) // return a byte array - { - using var reader = new StreamReader(response); - return Encoding.UTF8.GetBytes(await reader.ReadToEndAsync().ConfigureAwait(false)); - } - - if (type == typeof(Stream)) - { - return response; - } - - if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object - { - using var reader = new StreamReader(response); - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - return DateTime.Parse(text, null, System.Globalization.DateTimeStyles.RoundtripKind); - } - - if (type == typeof(string) || type.Name.StartsWith("System.Nullable")) // return primitive type - { - using var reader = new StreamReader(response); - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - return Convert.ChangeType(text, type); - } - - // Json Model try { using var reader = new StreamReader(response); - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - // Stopwatch sw = new Stopwatch(); - // sw.Start(); - // - // - // if (response == null || response.CanRead == false) - // return default; - // - // using (response) - // using (var sr = new StreamReader(response)) - // using (var jtr = new JsonTextReader(sr)) - // { - // return Serializer.Deserialize(jtr); - // } - - - - var deserializeObject = JsonConvert.DeserializeObject(text, type, _serializerSettings); - // sw.Stop(); - // Console.WriteLine($"DeserializeObject: {sw.ElapsedMilliseconds}ms"); - return deserializeObject; + var readToEndAsync = await reader.ReadToEndAsync().ConfigureAwait(false); + return JsonConvert.DeserializeObject(readToEndAsync, type, + JsonConfig.AlgoliaJsonSerializerSettings); } catch (Exception ex) { diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/CallType.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/CallType.cs new file mode 100644 index 0000000000..3d08f2bc0b --- /dev/null +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/CallType.cs @@ -0,0 +1,21 @@ +using System; + +namespace Algolia.Search.Transport; + +/// +/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/enumeration-types +/// Binary enums beware when adding new values +/// +[Flags] +public enum CallType +{ + /// + /// Read Call + /// + Read = 1, + + /// + /// Write Call + /// + Write = 2 +} diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpScheme.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpScheme.cs new file mode 100644 index 0000000000..b4caad26ee --- /dev/null +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpScheme.cs @@ -0,0 +1,16 @@ +namespace Algolia.Search.Transport; + +/// +/// Http Scheme +/// +public enum HttpScheme +{ + /// + /// Http + /// + Http, + /// + /// Https + /// + Https +} diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs index d8375d4e36..39836f4801 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; @@ -44,7 +43,7 @@ public HttpTransport(AlgoliaConfig config, IHttpRequester httpClient, ILoggerFac _algoliaConfig = config ?? throw new ArgumentNullException(nameof(config)); _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); _retryStrategy = new RetryStrategy(config); - _serializer = new DefaultJsonSerializer(JsonConfig.AlgoliaJsonSerializerSettings, loggerFactory); + _serializer = new DefaultJsonSerializer(loggerFactory); _logger = loggerFactory.CreateLogger(); } diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs index 22155c1d6c..aa42271f2d 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs @@ -8,7 +8,7 @@ namespace Algolia.Search.Transport; public class StatefulHost { /// - /// Url endpoint without the scheme, without the port + /// Url endpoint without the scheme and the port /// public string Url { get; set; } @@ -18,7 +18,7 @@ public class StatefulHost public HttpScheme Scheme { get; set; } = HttpScheme.Https; /// - /// Port of the URL (Optional) + /// Port of the URL (Optional - Default is -1) /// public int Port { get; set; } = -1; @@ -38,37 +38,7 @@ public class StatefulHost public DateTime LastUse { get; set; } = DateTime.UtcNow; /// - /// Calltype accepted by the host + /// CallType accepted by the host /// public CallType Accept { get; set; } } - -public enum HttpScheme -{ - /// - /// Http - /// - Http, - /// - /// Https - /// - Https -} - -/// -/// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/enumeration-types -/// Binary enums beware when adding new values -/// -[Flags] -public enum CallType -{ - /// - /// Read Call - /// - Read = 1, - - /// - /// Write Call - /// - Write = 2 -} diff --git a/playground/javascript/node/search.ts b/playground/javascript/node/search.ts index 8904333115..99b800d123 100644 --- a/playground/javascript/node/search.ts +++ b/playground/javascript/node/search.ts @@ -23,13 +23,6 @@ console.log('version', apiClientVersion, 'requests', requests); async function testSearch() { try { - - let start = Date.now(); - - let resp = await client.searchSingleIndex({ indexName: "test-csharp-new-client", searchParams: { query: " " } }); - - console.log('searchSingleIndex', Date.now() - start); - const res = await client.browseRules({ indexName: "cts_e2e_search_facet", aggregator: (resp: any) => {console.log(resp)} }); console.log(`[OK]`, res); From 6ec25324f5f67e9474036b0301ae5f950dde73fc Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 17:19:44 +0100 Subject: [PATCH 08/15] only error --- scripts/cts/runCts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cts/runCts.ts b/scripts/cts/runCts.ts index c1b1edc611..1f2e60098e 100644 --- a/scripts/cts/runCts.ts +++ b/scripts/cts/runCts.ts @@ -6,7 +6,7 @@ async function runCtsOne(language: string): Promise { const cwd = `tests/output/${language}`; switch (language) { case 'csharp': - await run('dotnet test', { cwd, language }); + await run('dotnet test /clp:ErrorsOnly', { cwd, language }); break; case 'dart': await run('dart test', { cwd, language }); From dff85487458ab03c6904bbf8083580c2161adb59 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 17:26:54 +0100 Subject: [PATCH 09/15] only error --- templates/csharp/tests/requests/requests.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/csharp/tests/requests/requests.mustache b/templates/csharp/tests/requests/requests.mustache index 8b344dcd06..e760213008 100644 --- a/templates/csharp/tests/requests/requests.mustache +++ b/templates/csharp/tests/requests/requests.mustache @@ -19,7 +19,7 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; _client = new {{client}}(new {{clientPrefix}}Config("appId", "apiKey"{{#hasRegionalHost}},"{{defaultRegion}}"{{/hasRegionalHost}}), _echo); {{#hasE2E}} - DotEnv.Load(options: new DotEnvOptions(ignoreExceptions: false, probeForEnv: true, probeLevelsToSearch: 8, envFilePaths: new[] { ".env" })); + DotEnv.Load(options: new DotEnvOptions(ignoreExceptions: false, probeForEnv: false, probeLevelsToSearch: 8, envFilePaths: new[] { ".env" })); var e2EAppId = Environment.GetEnvironmentVariable("ALGOLIA_APPLICATION_ID"); if (e2EAppId == null) From 3436d9bd64489f4d79f610366c46c748f763cafa Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 18:27:18 +0100 Subject: [PATCH 10/15] only error --- templates/csharp/tests/requests/requests.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/csharp/tests/requests/requests.mustache b/templates/csharp/tests/requests/requests.mustache index e760213008..4cd0ce4bf2 100644 --- a/templates/csharp/tests/requests/requests.mustache +++ b/templates/csharp/tests/requests/requests.mustache @@ -19,7 +19,7 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; _client = new {{client}}(new {{clientPrefix}}Config("appId", "apiKey"{{#hasRegionalHost}},"{{defaultRegion}}"{{/hasRegionalHost}}), _echo); {{#hasE2E}} - DotEnv.Load(options: new DotEnvOptions(ignoreExceptions: false, probeForEnv: false, probeLevelsToSearch: 8, envFilePaths: new[] { ".env" })); + DotEnv.Load(options: new DotEnvOptions(ignoreExceptions: true, probeForEnv: true, probeLevelsToSearch: 8, envFilePaths: new[] { ".env" })); var e2EAppId = Environment.GetEnvironmentVariable("ALGOLIA_APPLICATION_ID"); if (e2EAppId == null) From 3aad5f5b6332517504c46af939f94b91a37f9039 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 19:01:40 +0100 Subject: [PATCH 11/15] change port --- .../algoliasearch/Transport/HttpTransport.cs | 15 ++++++++++----- .../algoliasearch/Transport/StatefulHost.cs | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs index 39836f4801..1baea3ffcd 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/HttpTransport.cs @@ -256,14 +256,19 @@ private static Uri BuildUri(StatefulHost host, string baseUri, } } - if (optionalQueryParameters != null) + var builder = new UriBuilder { Scheme = host.Scheme.ToString(), Host = host.Url, Path = path }; + + if (optionalQueryParameters != null && optionalQueryParameters.Any()) + { + builder.Query = optionalQueryParameters.ToQueryString(); + } + + if (host.Port.HasValue) { - var queryParams = optionalQueryParameters.ToQueryString(); - return new UriBuilder - { Scheme = host.Scheme.ToString(), Host = host.Url, Port = host.Port, Path = path, Query = queryParams }.Uri; + builder.Port = host.Port.Value; } - return new UriBuilder { Scheme = host.Scheme.ToString(), Host = host.Url, Port = host.Port, Path = path }.Uri; + return builder.Uri; } /// diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs index aa42271f2d..9541a363ee 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Transport/StatefulHost.cs @@ -18,9 +18,9 @@ public class StatefulHost public HttpScheme Scheme { get; set; } = HttpScheme.Https; /// - /// Port of the URL (Optional - Default is -1) + /// Port of the URL (Optional) /// - public int Port { get; set; } = -1; + public int? Port { get; set; } /// /// Is the host up or not From c2cc015462e7d1682837d258a0e7d5d088812494 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Tue, 6 Feb 2024 21:55:46 +0100 Subject: [PATCH 12/15] review --- .../Data/searchResult.json | 0 .../Model/TestObject.cs | 0 .../Performaces.csproj | 0 .../{Performaces => Performances}/Program.cs | 0 templates/csharp/modelOneOf.mustache | 17 ++--------------- 5 files changed, 2 insertions(+), 15 deletions(-) rename playground/csharp/{Performaces => Performances}/Data/searchResult.json (100%) rename playground/csharp/{Performaces => Performances}/Model/TestObject.cs (100%) rename playground/csharp/{Performaces => Performances}/Performaces.csproj (100%) rename playground/csharp/{Performaces => Performances}/Program.cs (100%) diff --git a/playground/csharp/Performaces/Data/searchResult.json b/playground/csharp/Performances/Data/searchResult.json similarity index 100% rename from playground/csharp/Performaces/Data/searchResult.json rename to playground/csharp/Performances/Data/searchResult.json diff --git a/playground/csharp/Performaces/Model/TestObject.cs b/playground/csharp/Performances/Model/TestObject.cs similarity index 100% rename from playground/csharp/Performaces/Model/TestObject.cs rename to playground/csharp/Performances/Model/TestObject.cs diff --git a/playground/csharp/Performaces/Performaces.csproj b/playground/csharp/Performances/Performaces.csproj similarity index 100% rename from playground/csharp/Performaces/Performaces.csproj rename to playground/csharp/Performances/Performaces.csproj diff --git a/playground/csharp/Performaces/Program.cs b/playground/csharp/Performances/Program.cs similarity index 100% rename from playground/csharp/Performaces/Program.cs rename to playground/csharp/Performances/Program.cs diff --git a/templates/csharp/modelOneOf.mustache b/templates/csharp/modelOneOf.mustache index b80aa230a0..1f36d4eb24 100644 --- a/templates/csharp/modelOneOf.mustache +++ b/templates/csharp/modelOneOf.mustache @@ -123,12 +123,6 @@ /// An instance of {{classname}} public static {{classname}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}} FromJson(string jsonString) { - {{classname}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}} new{{classname}} = null; - - if (string.IsNullOrEmpty(jsonString)) - { - return new{{classname}}; - } {{#useOneOfDiscriminatorLookup}} {{#discriminator}} @@ -159,15 +153,8 @@ {{#composedSchemas.oneOf}} try { - // if it does not contains "AdditionalProperties", use SerializerSettings to deserialize - if (typeof({{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}).GetProperty("AdditionalProperties") == null) - { - return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings)); - } - else - { - return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings)); - } + {{#getAdditionalPropertiesIsAnyType}}return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings));{{/getAdditionalPropertiesIsAnyType}} + {{^getAdditionalPropertiesIsAnyType}}return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings));{{/getAdditionalPropertiesIsAnyType}} } catch (Exception exception) { From 397895cbbeb779313a0734d6efe94b33ab9a8fc3 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Wed, 7 Feb 2024 11:39:41 +0100 Subject: [PATCH 13/15] review --- playground/csharp/Algolia.sln | 28 ++++--------------- ...Performaces.csproj => Performances.csproj} | 5 +--- templates/csharp/modelOneOf.mustache | 3 +- 3 files changed, 7 insertions(+), 29 deletions(-) rename playground/csharp/Performances/{Performaces.csproj => Performances.csproj} (90%) diff --git a/playground/csharp/Algolia.sln b/playground/csharp/Algolia.sln index cd04630b9f..94bd083bd8 100644 --- a/playground/csharp/Algolia.sln +++ b/playground/csharp/Algolia.sln @@ -4,13 +4,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Playground", "Playground\Pl EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search", "..\..\clients\algoliasearch-client-csharp\algoliasearch\Algolia.Search.csproj", "{2485A285-E565-4407-95E1-0F216142AAA8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search.Tests", "..\..\tests\output\csharp\src\Algolia.Search.Tests.csproj", "{5F6F1865-31E1-4984-B575-430A42217820}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Performaces", "Performaces\Performaces.csproj", "{5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceLegacy", "PerformanceLegacy\PerformanceLegacy.csproj", "{67814440-28A1-4344-873A-2E1F6F2FAAAC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Algolia.Search", "..\..\..\..\RiderProjects\algoliasearch-client-csharp\src\Algolia.Search\Algolia.Search.csproj", "{FA9B6991-346D-4C75-A63C-01CD6B207A47}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Performances", "Performances\Performances.csproj", "{229F8B19-7731-47C3-9DB4-323577B95E97}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -26,21 +20,9 @@ Global {2485A285-E565-4407-95E1-0F216142AAA8}.Debug|Any CPU.Build.0 = Debug|Any CPU {2485A285-E565-4407-95E1-0F216142AAA8}.Release|Any CPU.ActiveCfg = Release|Any CPU {2485A285-E565-4407-95E1-0F216142AAA8}.Release|Any CPU.Build.0 = Release|Any CPU - {5F6F1865-31E1-4984-B575-430A42217820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5F6F1865-31E1-4984-B575-430A42217820}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5F6F1865-31E1-4984-B575-430A42217820}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5F6F1865-31E1-4984-B575-430A42217820}.Release|Any CPU.Build.0 = Release|Any CPU - {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5E5DD034-6BC2-46FB-B9EF-7C18C3C214EF}.Release|Any CPU.Build.0 = Release|Any CPU - {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {67814440-28A1-4344-873A-2E1F6F2FAAAC}.Release|Any CPU.Build.0 = Release|Any CPU - {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA9B6991-346D-4C75-A63C-01CD6B207A47}.Release|Any CPU.Build.0 = Release|Any CPU + {229F8B19-7731-47C3-9DB4-323577B95E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {229F8B19-7731-47C3-9DB4-323577B95E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {229F8B19-7731-47C3-9DB4-323577B95E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {229F8B19-7731-47C3-9DB4-323577B95E97}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/playground/csharp/Performances/Performaces.csproj b/playground/csharp/Performances/Performances.csproj similarity index 90% rename from playground/csharp/Performances/Performaces.csproj rename to playground/csharp/Performances/Performances.csproj index dc7200b91a..4ea9f48209 100644 --- a/playground/csharp/Performances/Performaces.csproj +++ b/playground/csharp/Performances/Performances.csproj @@ -5,6 +5,7 @@ net8.0 enable enable + Performaces @@ -21,8 +22,4 @@ - - - - diff --git a/templates/csharp/modelOneOf.mustache b/templates/csharp/modelOneOf.mustache index 1f36d4eb24..f598f2e6b5 100644 --- a/templates/csharp/modelOneOf.mustache +++ b/templates/csharp/modelOneOf.mustache @@ -153,8 +153,7 @@ {{#composedSchemas.oneOf}} try { - {{#getAdditionalPropertiesIsAnyType}}return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.AlgoliaJsonSerializerSettings));{{/getAdditionalPropertiesIsAnyType}} - {{^getAdditionalPropertiesIsAnyType}}return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings));{{/getAdditionalPropertiesIsAnyType}} + return new {{classname}}{{#x-has-child-generic}}{{/x-has-child-generic}}(JsonConvert.DeserializeObject<{{{datatypeWithEnum}}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}>(jsonString, JsonConfig.DeserializeOneOfSettings)); } catch (Exception exception) { From 4195970962f266df83552287f74d7d5ede896470 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Wed, 7 Feb 2024 14:18:52 +0100 Subject: [PATCH 14/15] review --- playground/csharp/Performances/Performances.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/csharp/Performances/Performances.csproj b/playground/csharp/Performances/Performances.csproj index 4ea9f48209..64e6dc5996 100644 --- a/playground/csharp/Performances/Performances.csproj +++ b/playground/csharp/Performances/Performances.csproj @@ -5,7 +5,7 @@ net8.0 enable enable - Performaces + Performances From a48fad7bf7636acded84d056cbf015629e21ed36 Mon Sep 17 00:00:00 2001 From: Morgan Leroi Date: Wed, 7 Feb 2024 15:46:03 +0100 Subject: [PATCH 15/15] review --- templates/csharp/modelOneOf.mustache | 4 ++-- templates/csharp/tests/requests/requests.mustache | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/csharp/modelOneOf.mustache b/templates/csharp/modelOneOf.mustache index f598f2e6b5..a6da7bbe98 100644 --- a/templates/csharp/modelOneOf.mustache +++ b/templates/csharp/modelOneOf.mustache @@ -242,7 +242,7 @@ /// JSON Serializer public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - writer.WriteRawValue((string)(typeof({{classname}}{{#vendorExtensions.x-has-child-generic}}{{/vendorExtensions.x-has-child-generic}}).GetMethod("ToJson")?.Invoke(value, null))); + writer.WriteRawValue((string)value?.GetType().GetMethod("ToJson")?.Invoke(value, null)); } /// @@ -257,7 +257,7 @@ { if(reader.TokenType != JsonToken.Null) { - return objectType.GetMethod("FromJson")?.Invoke(null, new object[] { JObject.Load(reader).ToString(Formatting.None) }); + return objectType.GetMethod("FromJson")?.Invoke(null, new object[] { JToken.Load(reader).ToString(Formatting.None) }); } return null; } diff --git a/templates/csharp/tests/requests/requests.mustache b/templates/csharp/tests/requests/requests.mustache index 4cd0ce4bf2..d71867c632 100644 --- a/templates/csharp/tests/requests/requests.mustache +++ b/templates/csharp/tests/requests/requests.mustache @@ -48,7 +48,7 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; [Fact(DisplayName = "{{{testName}}}")] public async Task {{#lambda.pascalcase}}{{method}}Test{{testIndex}}{{/lambda.pascalcase}}() { - await _client.{{#lambda.pascalcase}}{{method}}{{/lambda.pascalcase}}Async{{#isGeneric}}{{/isGeneric}}({{#parametersWithDataType}}{{> tests/generateParams}}{{^-last}},{{/-last}}{{/parametersWithDataType}}{{#hasRequestOptions}}, new RequestOptions(){ + await _client.{{#lambda.pascalcase}}{{method}}{{/lambda.pascalcase}}Async{{#isGeneric}}{{/isGeneric}}({{#parametersWithDataType}}{{> tests/generateParams}}{{^-last}},{{/-last}}{{/parametersWithDataType}}{{#hasRequestOptions}}, new RequestOptions(){ {{#requestOptions.queryParameters.parametersWithDataType}} QueryParameters = new Dictionary(){ {"{{{key}}}", {{> tests/requests/requestOptionsParams}} }}, {{/requestOptions.queryParameters.parametersWithDataType}} @@ -101,7 +101,7 @@ private readonly {{client}} _client{{#hasE2E}}, _e2eClient{{/hasE2E}}; {{#response}} // e2e try { - var resp = await _e2eClient.{{#lambda.pascalcase}}{{method}}{{/lambda.pascalcase}}Async{{#isGeneric}}{{/isGeneric}}({{#parametersWithDataType}}{{> tests/generateParams}}{{^-last}},{{/-last}}{{/parametersWithDataType}}{{#hasRequestOptions}}, new RequestOptions(){ + var resp = await _e2eClient.{{#lambda.pascalcase}}{{method}}{{/lambda.pascalcase}}Async{{#isGeneric}}{{/isGeneric}}({{#parametersWithDataType}}{{> tests/generateParams}}{{^-last}},{{/-last}}{{/parametersWithDataType}}{{#hasRequestOptions}}, new RequestOptions(){ {{#requestOptions.queryParameters.parametersWithDataType}} QueryParameters = new Dictionary(){ {"{{{key}}}", {{> tests/requests/requestOptionsParams}} }}, {{/requestOptions.queryParameters.parametersWithDataType}}