From e163b212c16c6da7acb57a0d8b48c9e35db6346b Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Fri, 6 Sep 2024 09:02:28 +0200 Subject: [PATCH 1/2] fix(csharp): add helpers to ISearchClient --- .../algoliasearch/Http/AlgoliaUserAgent.cs | 3 +- .../Utils/SearchClientExtensions.cs | 460 +++++++++--------- templates/csharp/api.mustache | 93 ++-- templates/csharp/netcore_project.mustache | 4 +- 4 files changed, 281 insertions(+), 279 deletions(-) diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaUserAgent.cs b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaUserAgent.cs index f277972d3e4..da07d287bc8 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaUserAgent.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Http/AlgoliaUserAgent.cs @@ -19,7 +19,8 @@ public class AlgoliaUserAgent /// /// Create a new user-agent header /// - /// + /// The client name + /// The client version public AlgoliaUserAgent(string clientName, string clientVersion) { AddSegment("Algolia for Csharp", $"({clientVersion})"); diff --git a/clients/algoliasearch-client-csharp/algoliasearch/Utils/SearchClientExtensions.cs b/clients/algoliasearch-client-csharp/algoliasearch/Utils/SearchClientExtensions.cs index cbd2d7ddf04..ea0ebd2e67b 100644 --- a/clients/algoliasearch-client-csharp/algoliasearch/Utils/SearchClientExtensions.cs +++ b/clients/algoliasearch-client-csharp/algoliasearch/Utils/SearchClientExtensions.cs @@ -13,10 +13,8 @@ namespace Algolia.Search.Clients; -public partial class SearchClient +public partial interface ISearchClient { - private const int DefaultMaxRetries = 50; - /// /// Wait for a task to complete with `indexName` and `taskID`. /// @@ -26,34 +24,209 @@ public partial class SearchClient /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) /// Cancellation token (optional) - public async Task WaitForTaskAsync(string indexName, long taskId, int maxRetries = DefaultMaxRetries, - Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) - { - return await RetryUntil(async () => await GetTaskAsync(indexName, taskId, requestOptions, ct), - resp => resp.Status == Models.Search.TaskStatus.Published, maxRetries, timeout, ct).ConfigureAwait(false); - } + Task WaitForTaskAsync(string indexName, long taskId, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); + /// + GetTaskResponse WaitForTask(string indexName, long taskId, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); /// - /// Wait for a task to complete with `indexName` and `taskID`. (Synchronous version) + /// Wait for an application-level task to complete with `taskID`. /// - /// The `indexName` where the operation was performed. /// The `taskID` returned in the method response. /// The maximum number of retry. 50 by default. (optional) /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) /// Cancellation token (optional) - public GetTaskResponse WaitForTask(string indexName, long taskId, int maxRetries = DefaultMaxRetries, - Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) => - AsyncHelper.RunSync(() => WaitForTaskAsync(indexName, taskId, maxRetries, timeout, requestOptions, ct)); + Task WaitForAppTaskAsync(long taskId, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); + /// + GetTaskResponse WaitForAppTask(long taskId, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); /// - /// Wait for an application-level task to complete with `taskID`. + /// Helper method that waits for an API key task to be processed. /// - /// The `taskID` returned in the method response. + /// The key that has been added, deleted or updated. + /// The `operation` that was done on a `key`. + /// Necessary to know if an `update` operation has been processed, compare fields of the response with it. (optional - mandatory if operation is UPDATE) /// The maximum number of retry. 50 by default. (optional) /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) /// Cancellation token (optional) + Task WaitForApiKeyAsync(string key, ApiKeyOperation operation, ApiKey apiKey = default, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); + /// + GetApiKeyResponse WaitForApiKey(string key, ApiKeyOperation operation, ApiKey apiKey = default, int maxRetries = SearchClient.DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default); + + /// + /// Iterate on the `browse` method of the client to allow aggregating objects of an index. + /// + /// The index in which to perform the request. + /// The `browse` parameters. + /// The requestOptions to send along with the query, they will be forwarded to the `browse` method and merged with the transporter requestOptions. + /// The model of the record + Task> BrowseObjectsAsync(string indexName, BrowseParamsObject browseParams, RequestOptions requestOptions = null); + /// + IEnumerable BrowseObjects(string indexName, BrowseParamsObject browseParams, RequestOptions requestOptions = null); + + /// + /// Iterate on the `SearchRules` method of the client to allow aggregating rules of an index. + /// + /// The index in which to perform the request. + /// The `SearchRules` parameters + /// The requestOptions to send along with the query, they will be forwarded to the `searchRules` method and merged with the transporter requestOptions. + Task> BrowseRulesAsync(string indexName, SearchRulesParams searchRulesParams, RequestOptions requestOptions = null); + /// + IEnumerable BrowseRules(string indexName, SearchRulesParams searchRulesParams, RequestOptions requestOptions = null); + + /// + /// Iterate on the `SearchSynonyms` method of the client to allow aggregating rules of an index. + /// + /// The index in which to perform the request. + /// The `SearchSynonyms` parameters. + /// The requestOptions to send along with the query, they will be forwarded to the `searchSynonyms` method and merged with the transporter requestOptions. + Task> BrowseSynonymsAsync(string indexName, SearchSynonymsParams synonymsParams, RequestOptions requestOptions = null); + /// + IEnumerable BrowseSynonyms(string indexName, SearchSynonymsParams synonymsParams, RequestOptions requestOptions = null); + + /// + /// Generate a virtual API Key without any call to the server. + /// + /// Parent API Key + /// Restriction to add the key + /// + string GenerateSecuredApiKey(string parentApiKey, SecuredApiKeyRestrictions restriction); + /// + /// Get the remaining validity of a key generated by `GenerateSecuredApiKey`. + /// + /// The secured API Key + /// + /// + /// + TimeSpan GetSecuredApiKeyRemainingValidity(string securedApiKey); + + /// + /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia records (hits). Results will be received in the same order as the queries. + /// + /// A list of search requests to be executed. + /// The search strategy to be employed during the search. (optional) + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + /// Thrown when arguments are not correct + /// Thrown when the API call was rejected by Algolia + /// Thrown when the client failed to call the endpoint + /// Task of List{SearchResponse{T}} + Task>> SearchForHitsAsync(IEnumerable requests, SearchStrategy? searchStrategy = null, RequestOptions options = null, CancellationToken cancellationToken = default); + /// + List> SearchForHits(IEnumerable requests, SearchStrategy? searchStrategy = null, RequestOptions options = null, CancellationToken cancellationToken = default); + + /// + /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia facets. Results will be received in the same order as the queries. + /// + /// A list of search requests to be executed. + /// The search strategy to be employed during the search. (optional) + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + /// Thrown when arguments are not correct + /// Thrown when the API call was rejected by Algolia + /// Thrown when the client failed to call the endpoint + /// Task of List{SearchResponse{T}} + Task> SearchForFacetsAsync(IEnumerable requests, SearchStrategy? searchStrategy, RequestOptions options = null, CancellationToken cancellationToken = default); + /// + List SearchForFacets(IEnumerable requests, SearchStrategy? searchStrategy, RequestOptions options = null, CancellationToken cancellationToken = default); + + /// + /// Push a new set of objects and remove all previous ones. Settings, synonyms and query rules are untouched. + /// Replace all objects in an index without any downtime. Internally, this method copies the existing index settings, synonyms and query rules and indexes all passed objects. + /// Finally, the temporary one replaces the existing index. + /// See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details. + /// + /// The index in which to perform the request. + /// The list of `objects` to store in the given Algolia `indexName`. + /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + Task ReplaceAllObjectsAsync(string indexName, IEnumerable objects, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + /// + ReplaceAllObjectsResponse ReplaceAllObjects(string indexName, IEnumerable objects, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + + /// + /// Helper: Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests. + /// + /// The index in which to perform the request. + /// The list of `objects` to store in the given Algolia `indexName`. + /// The `batch` `action` to perform on the given array of `objects`. Defaults to `addObject`. + /// Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable. Defaults to `false`. + /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + /// + Task> ChunkedBatchAsync(string indexName, IEnumerable objects, Action action = Action.AddObject, bool waitForTasks = false, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + /// + List ChunkedBatch(string indexName, IEnumerable objects, Action action = Action.AddObject, bool waitForTasks = false, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + + /// + /// Helper: Saves the given array of objects in the given index. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. + /// + /// The index in which to perform the request. + /// The list of `objects` to store in the given Algolia `indexName`. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + /// + Task> SaveObjectsAsync(string indexName, IEnumerable objects, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + /// + List SaveObjects(string indexName, IEnumerable objects, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + + /// + /// Helper: Deletes every records for the given objectIDs. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objectIDs in it. + /// + /// The index in which to perform the request. + /// The list of `objectIDs` to remove from the given Algolia `indexName`. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + Task> DeleteObjectsAsync(string indexName, IEnumerable objectIDs, RequestOptions options = null, CancellationToken cancellationToken = default); + /// + List DeleteObjects(string indexName, IEnumerable objectIDs, RequestOptions options = null, CancellationToken cancellationToken = default); + + /// + /// Helper: Replaces object content of all the given objects according to their respective `objectID` field. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. + /// + /// The index in which to perform the request. + /// The list of `objects` to update in the given Algolia `indexName`. + /// To be provided if non-existing objects are passed, otherwise, the call will fail. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + Task> PartialUpdateObjectsAsync(string indexName, IEnumerable objects, bool createIfNotExists, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + /// + List PartialUpdateObjects(string indexName, IEnumerable objects, bool createIfNotExists, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class; + + /// + /// Helper: Check if an index exists. + /// + /// The index in which to check. + /// Cancellation Token to cancel the request. + Task IndexExistsAsync(string indexName, CancellationToken cancellationToken = default); + /// + bool IndexExists(string indexName, CancellationToken cancellationToken = default); +} + +public partial class SearchClient : ISearchClient +{ + /// + /// The default maximum number of retries for search operations. + /// + public const int DefaultMaxRetries = 50; + + /// + public async Task WaitForTaskAsync(string indexName, long taskId, int maxRetries = DefaultMaxRetries, + Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) + { + return await RetryUntil(async () => await GetTaskAsync(indexName, taskId, requestOptions, ct), + resp => resp.Status == Models.Search.TaskStatus.Published, maxRetries, timeout, ct).ConfigureAwait(false); + } + + /// + public GetTaskResponse WaitForTask(string indexName, long taskId, int maxRetries = DefaultMaxRetries, + Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) => + AsyncHelper.RunSync(() => WaitForTaskAsync(indexName, taskId, maxRetries, timeout, requestOptions, ct)); + + /// public async Task WaitForAppTaskAsync(long taskId, int maxRetries = DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) { @@ -61,28 +234,12 @@ public async Task WaitForAppTaskAsync(long taskId, int maxRetri resp => resp.Status == Models.Search.TaskStatus.Published, maxRetries, timeout, ct).ConfigureAwait(false); } - /// - /// Wait for an application-level task to complete with `taskID`. (Synchronous version) - /// - /// The `taskID` returned in the method response. - /// The maximum number of retry. 50 by default. (optional) - /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) - /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) - /// Cancellation token (optional) + /// public GetTaskResponse WaitForAppTask(long taskId, int maxRetries = DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) => AsyncHelper.RunSync(() => WaitForAppTaskAsync(taskId, maxRetries, timeout, requestOptions, ct)); - /// - /// Helper method that waits for an API key task to be processed. - /// - /// The key that has been added, deleted or updated. - /// The `operation` that was done on a `key`. - /// Necessary to know if an `update` operation has been processed, compare fields of the response with it. (optional - mandatory if operation is UPDATE) - /// The maximum number of retry. 50 by default. (optional) - /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) - /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) - /// Cancellation token (optional) + /// public async Task WaitForApiKeyAsync(string key, ApiKeyOperation operation, ApiKey apiKey = default, int maxRetries = DefaultMaxRetries, Func timeout = null, @@ -144,29 +301,14 @@ public async Task WaitForApiKeyAsync(string key, maxRetries, timeout, ct); } - /// - /// Helper method that waits for an API key task to be processed. (Synchronous version) - /// - /// The `operation` that was done on a `key`. - /// The key that has been added, deleted or updated. - /// Necessary to know if an `update` operation has been processed, compare fields of the response with it. (optional - mandatory if operation is UPDATE) - /// The maximum number of retry. 50 by default. (optional) - /// The function to decide how long to wait between retries. Math.Min(retryCount * 200, 5000) by default. (optional) - /// The requestOptions to send along with the query, they will be merged with the transporter requestOptions. (optional) - /// Cancellation token (optional) + /// public GetApiKeyResponse WaitForApiKey(string key, ApiKeyOperation operation, ApiKey apiKey = default, int maxRetries = DefaultMaxRetries, Func timeout = null, RequestOptions requestOptions = null, CancellationToken ct = default) => AsyncHelper.RunSync(() => WaitForApiKeyAsync(key, operation, apiKey, maxRetries, timeout, requestOptions, ct)); - /// - /// Iterate on the `browse` method of the client to allow aggregating objects of an index. - /// - /// The index in which to perform the request. - /// The `browse` parameters. - /// The requestOptions to send along with the query, they will be forwarded to the `browse` method and merged with the transporter requestOptions. - /// The model of the record + /// public async Task> BrowseObjectsAsync(string indexName, BrowseParamsObject browseParams, RequestOptions requestOptions = null) { @@ -181,24 +323,13 @@ public async Task> BrowseObjectsAsync(string indexName, Browse } - /// - /// Iterate on the `browse` method of the client to allow aggregating objects of an index. (Synchronous version) - /// - /// The index in which to perform the request. - /// The `browse` parameters. - /// The requestOptions to send along with the query, they will be forwarded to the `browse` method and merged with the transporter requestOptions. - /// The model of the record + /// public IEnumerable BrowseObjects(string indexName, BrowseParamsObject browseParams, RequestOptions requestOptions = null) => AsyncHelper.RunSync(() => BrowseObjectsAsync(indexName, browseParams, requestOptions)); - /// - /// Iterate on the `SearchRules` method of the client to allow aggregating rules of an index. - /// - /// The index in which to perform the request. - /// The `SearchRules` parameters - /// The requestOptions to send along with the query, they will be forwarded to the `searchRules` method and merged with the transporter requestOptions. + /// public async Task> BrowseRulesAsync(string indexName, SearchRulesParams searchRulesParams, RequestOptions requestOptions = null) { @@ -215,23 +346,13 @@ public async Task> BrowseRulesAsync(string indexName, SearchRu return all.SelectMany(u => u.Item1.Hits); } - /// - /// Iterate on the `SearchRules` method of the client to allow aggregating rules of an index. (Synchronous version) - /// - /// The index in which to perform the request. - /// The `SearchRules` parameters - /// The requestOptions to send along with the query, they will be forwarded to the `searchRules` method and merged with the transporter requestOptions. + /// public IEnumerable BrowseRules(string indexName, SearchRulesParams searchRulesParams, RequestOptions requestOptions = null) => AsyncHelper.RunSync(() => BrowseRulesAsync(indexName, searchRulesParams, requestOptions)); - /// - /// Iterate on the `SearchSynonyms` method of the client to allow aggregating rules of an index. - /// - /// The index in which to perform the request. - /// The `SearchSynonyms` parameters. - /// The requestOptions to send along with the query, they will be forwarded to the `searchSynonyms` method and merged with the transporter requestOptions. + /// public async Task> BrowseSynonymsAsync(string indexName, SearchSynonymsParams synonymsParams, RequestOptions requestOptions = null) { @@ -248,22 +369,13 @@ public async Task> BrowseSynonymsAsync(string indexName, return all.SelectMany(u => u.Item1.Hits); } - /// - /// Iterate on the `SearchSynonyms` method of the client to allow aggregating rules of an index. (Synchronous version) - /// - /// The index in which to perform the request. - /// The `SearchSynonyms` parameters. - /// The requestOptions to send along with the query, they will be forwarded to the `searchSynonyms` method and merged with the transporter requestOptions. + /// public IEnumerable BrowseSynonyms(string indexName, SearchSynonymsParams synonymsParams, RequestOptions requestOptions = null) => AsyncHelper.RunSync(() => BrowseSynonymsAsync(indexName, synonymsParams, requestOptions)); - /// - /// Generate a virtual API Key without any call to the server. - /// - /// Parent API Key - /// Restriction to add the key - /// + + /// public string GenerateSecuredApiKey(string parentApiKey, SecuredApiKeyRestrictions restriction) { var queryParams = restriction.ToQueryString(); @@ -272,13 +384,7 @@ public string GenerateSecuredApiKey(string parentApiKey, SecuredApiKeyRestrictio } - /// - /// Get the remaining validity of a key generated by `GenerateSecuredApiKey`. - /// - /// The secured API Key - /// - /// - /// + /// public TimeSpan GetSecuredApiKeyRemainingValidity(string securedApiKey) { if (string.IsNullOrWhiteSpace(securedApiKey)) @@ -309,17 +415,7 @@ public TimeSpan GetSecuredApiKeyRemainingValidity(string securedApiKey) } - /// - /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia records (hits). Results will be received in the same order as the queries. - /// - /// A list of search requests to be executed. - /// The search strategy to be employed during the search. (optional) - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// Task of List{SearchResponse{T}} + /// public async Task>> SearchForHitsAsync(IEnumerable requests, SearchStrategy? searchStrategy = null, RequestOptions options = null, CancellationToken cancellationToken = default) { @@ -329,17 +425,7 @@ public async Task>> SearchForHitsAsync(IEnumerable x.IsSearchResponse()).Select(x => x.AsSearchResponse()).ToList(); } - /// - /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia records (hits). Results will be received in the same order as the queries. (Synchronous version) - /// - /// A list of search requests to be executed. - /// The search strategy to be employed during the search. (optional) - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// Task of List{SearchResponse{T}} + /// public List> SearchForHits(IEnumerable requests, SearchStrategy? searchStrategy = null, RequestOptions options = null, CancellationToken cancellationToken = default) => @@ -347,17 +433,7 @@ public List> SearchForHits(IEnumerable reque SearchForHitsAsync(requests, searchStrategy, options, cancellationToken)); - /// - /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia facets. Results will be received in the same order as the queries. - /// - /// A list of search requests to be executed. - /// The search strategy to be employed during the search. (optional) - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// Task of List{SearchResponse{T}} + /// public async Task> SearchForFacetsAsync(IEnumerable requests, SearchStrategy? searchStrategy, RequestOptions options = null, CancellationToken cancellationToken = default) { @@ -368,17 +444,7 @@ public async Task> SearchForFacetsAsync(IEnum .Select(x => x.AsSearchForFacetValuesResponse()).ToList(); } - /// - /// Executes a synchronous search for the provided search requests, with certainty that we will only request Algolia facets. Results will be received in the same order as the queries. - /// - /// A list of search requests to be executed. - /// The search strategy to be employed during the search. (optional) - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// Task of List{SearchResponse{T}} + /// public List SearchForFacets(IEnumerable requests, SearchStrategy? searchStrategy, RequestOptions options = null, CancellationToken cancellationToken = default) => AsyncHelper.RunSync(() => SearchForFacetsAsync(requests, searchStrategy, options, cancellationToken)); @@ -405,33 +471,12 @@ private static async Task RetryUntil(Func> func, Func val "The maximum number of retries exceeded. (" + (retryCount + 1) + "/" + maxRetries + ")"); } + private static int NextDelay(int retryCount) + { + return Math.Min(retryCount * 200, 5000); + } - /// - /// Push a new set of objects and remove all previous ones. Settings, synonyms and query rules are untouched. - /// Replace all objects in an index without any downtime. Internally, this method copies the existing index settings, synonyms and query rules and indexes all passed objects. - /// Finally, the temporary one replaces the existing index. (Synchronous version) - /// See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details. - /// - /// The index in which to perform the request. - /// The list of `objects` to store in the given Algolia `indexName`. - /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - public ReplaceAllObjectsResponse ReplaceAllObjects(string indexName, IEnumerable objects, int batchSize = 1000, - RequestOptions options = null, CancellationToken cancellationToken = default) where T : class => - AsyncHelper.RunSync(() => ReplaceAllObjectsAsync(indexName, objects, batchSize, options, cancellationToken)); - - /// - /// Push a new set of objects and remove all previous ones. Settings, synonyms and query rules are untouched. - /// Replace all objects in an index without any downtime. Internally, this method copies the existing index settings, synonyms and query rules and indexes all passed objects. - /// Finally, the temporary one replaces the existing index. - /// See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details. - /// - /// The index in which to perform the request. - /// The list of `objects` to store in the given Algolia `indexName`. - /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. + /// public async Task ReplaceAllObjectsAsync(string indexName, IEnumerable objects, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class { @@ -476,31 +521,12 @@ await WaitForTaskAsync(tmpIndexName, moveResponse.TaskID, requestOptions: option }; } - /// - /// Helper: Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests. (Synchronous version) - /// - /// The index in which to perform the request. - /// The list of `objects` to store in the given Algolia `indexName`. - /// The `batch` `action` to perform on the given array of `objects`, defaults to `addObject`. - /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// - public List ChunkedBatch(string indexName, IEnumerable objects, Action action = Action.AddObject, - bool waitForTasks = false, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) - where T : class => - AsyncHelper.RunSync(() => ChunkedBatchAsync(indexName, objects, action, waitForTasks, batchSize, options, cancellationToken)); + /// + public ReplaceAllObjectsResponse ReplaceAllObjects(string indexName, IEnumerable objects, int batchSize = 1000, + RequestOptions options = null, CancellationToken cancellationToken = default) where T : class => + AsyncHelper.RunSync(() => ReplaceAllObjectsAsync(indexName, objects, batchSize, options, cancellationToken)); - /// - /// Helper: Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests. - /// - /// The index in which to perform the request. - /// The list of `objects` to store in the given Algolia `indexName`. - /// The `batch` `action` to perform on the given array of `objects`, defaults to `addObject`. - /// The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// + /// public async Task> ChunkedBatchAsync(string indexName, IEnumerable objects, Action action = Action.AddObject, bool waitForTasks = false, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class @@ -530,19 +556,13 @@ await WaitForTaskAsync(indexName, batch.TaskID, requestOptions: options, ct: can return responses; } - private static int NextDelay(int retryCount) - { - return Math.Min(retryCount * 200, 5000); - } + /// + public List ChunkedBatch(string indexName, IEnumerable objects, Action action = Action.AddObject, + bool waitForTasks = false, int batchSize = 1000, RequestOptions options = null, CancellationToken cancellationToken = default) + where T : class => + AsyncHelper.RunSync(() => ChunkedBatchAsync(indexName, objects, action, waitForTasks, batchSize, options, cancellationToken)); - /// - /// Helper: Saves the given array of objects in the given index. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. - /// - /// The index in which to perform the request. - /// The list of `objects` to store in the given Algolia `indexName`. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - /// + /// public async Task> SaveObjectsAsync(string indexName, IEnumerable objects, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class @@ -550,13 +570,12 @@ public async Task> SaveObjectsAsync(string indexName, IEn return await ChunkedBatchAsync(indexName, objects, Action.AddObject, false, 1000, options, cancellationToken).ConfigureAwait(false); } - /// - /// Helper: Deletes every records for the given objectIDs. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objectIDs in it. - /// - /// The index in which to perform the request. - /// The list of `objectIDs` to remove from the given Algolia `indexName`. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. + /// + public List SaveObjects(string indexName, IEnumerable objects, RequestOptions options = null, + CancellationToken cancellationToken = default) where T : class => + AsyncHelper.RunSync(() => SaveObjectsAsync(indexName, objects, options, cancellationToken)); + + /// public async Task> DeleteObjectsAsync(string indexName, IEnumerable objectIDs, RequestOptions options = null, CancellationToken cancellationToken = default) @@ -564,14 +583,12 @@ public async Task> DeleteObjectsAsync(string indexName, IEnu return await ChunkedBatchAsync(indexName, objectIDs.Select(id => new { objectID = id }), Action.DeleteObject, false, 1000, options, cancellationToken).ConfigureAwait(false); } - /// - /// Helper: Replaces object content of all the given objects according to their respective `objectID` field. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. - /// - /// The index in which to perform the request. - /// The list of `objects` to update in the given Algolia `indexName`. - /// To be provided if non-existing objects are passed, otherwise, the call will fail. - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. + /// + public List DeleteObjects(string indexName, IEnumerable objectIDs, RequestOptions options = null, + CancellationToken cancellationToken = default) => + AsyncHelper.RunSync(() => DeleteObjectsAsync(indexName, objectIDs, options, cancellationToken)); + + /// public async Task> PartialUpdateObjectsAsync(string indexName, IEnumerable objects, bool createIfNotExists, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class @@ -579,6 +596,11 @@ public async Task> PartialUpdateObjectsAsync(string index return await ChunkedBatchAsync(indexName, objects, createIfNotExists ? Action.PartialUpdateObject : Action.PartialUpdateObjectNoCreate, false, 1000, options, cancellationToken).ConfigureAwait(false); } + /// + public List PartialUpdateObjects(string indexName, IEnumerable objects, bool createIfNotExists, + RequestOptions options = null, CancellationToken cancellationToken = default) where T : class => + AsyncHelper.RunSync(() => PartialUpdateObjectsAsync(indexName, objects, createIfNotExists, options, cancellationToken)); + private static async Task> CreateIterable(Func> executeQuery, Func stopCondition) { @@ -594,8 +616,7 @@ private static async Task> CreateIterable(Func> execut return responses; } - public bool Exists(string indexName, CancellationToken cancellationToken = default) => AsyncHelper.RunSync(() => IndexExistsAsync(indexName, cancellationToken)); - + /// public async Task IndexExistsAsync(string indexName, CancellationToken cancellationToken = default) { try @@ -613,4 +634,7 @@ public async Task IndexExistsAsync(string indexName, CancellationToken can return await Task.FromResult(true); } + + /// + public bool IndexExists(string indexName, CancellationToken cancellationToken = default) => AsyncHelper.RunSync(() => IndexExistsAsync(indexName, cancellationToken)); } diff --git a/templates/csharp/api.mustache b/templates/csharp/api.mustache index 2dabd2429b4..3c85c3eec8a 100644 --- a/templates/csharp/api.mustache +++ b/templates/csharp/api.mustache @@ -22,41 +22,53 @@ namespace Algolia.Search.Clients; /// /// Represents a collection of functions to interact with the API endpoints /// - {{> visibility}} interface {{interfacePrefix}}{{classname}} + {{> visibility}} {{#isSearchClient}}partial {{/isSearchClient}}interface {{interfacePrefix}}{{classname}} { {{#operation}} /// /// {{{notes}}} - /// + /// {{#vendorExtensions}}{{#x-acl.0}} + /// + /// Required API Key ACLs:{{/x-acl.0}} + {{#x-acl}} + /// - {{.}} + {{/x-acl}} + {{/vendorExtensions}} {{#allParams}} /// {{{description}}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}} {{/allParams}} /// Add extra http header or query parameters to Algolia. /// Cancellation Token to cancel the request. - {{#isDeprecated}} - [Obsolete] - {{/isDeprecated}} /// Thrown when arguments are not correct /// Thrown when the API call was rejected by Algolia /// Thrown when the client failed to call the endpoint /// Task of {{> return_type_doc}} + {{#isDeprecated}} + [Obsolete] + {{/isDeprecated}} Task{{#returnType}}<{{> return_type}}>{{/returnType}} {{operationId}}Async{{#returnType}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}{{/returnType}}({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}RequestOptions options = null, CancellationToken cancellationToken = default); - /// - /// {{{notes}}} (Synchronous version) - /// + /// + /// {{{notes}}} (Synchronous version) + /// {{#vendorExtensions}}{{#x-acl.0}} + /// + /// Required API Key ACLs:{{/x-acl.0}} + {{#x-acl}} + /// - {{.}} + {{/x-acl}} + {{/vendorExtensions}} {{#allParams}} - /// {{{description}}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}} + /// {{{description}}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}} {{/allParams}} - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. + /// Add extra http header or query parameters to Algolia. + /// Cancellation Token to cancel the request. + /// Thrown when arguments are not correct + /// Thrown when the API call was rejected by Algolia + /// Thrown when the client failed to call the endpoint + /// {{> return_type_doc}} {{#isDeprecated}} - [Obsolete] + [Obsolete] {{/isDeprecated}} - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// {{> return_type_doc}} {{^returnType}}void{{/returnType}}{{#returnType}}{{> return_type}}{{/returnType}} {{operationId}}{{#returnType}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}{{/returnType}}({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}RequestOptions options = null, CancellationToken cancellationToken = default); {{/operation}} @@ -131,27 +143,10 @@ namespace Algolia.Search.Clients; {{#operation}} {{#supportsAsync}} - /// - /// {{{notes}}} - /// {{#vendorExtensions}}{{#x-acl.0}} - /// - /// Required API Key ACLs:{{/x-acl.0}} - {{#x-acl}} - /// - {{.}} - {{/x-acl}} - {{/vendorExtensions}} - {{#allParams}} - /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}} - {{/allParams}} - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. + /// {{#isDeprecated}} [Obsolete] {{/isDeprecated}} - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// Task of {{> return_type_doc}} public async Task{{#returnType}}<{{> return_type}}>{{/returnType}} {{operationId}}Async{{#returnType}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}{{/returnType}}({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}RequestOptions options = null, CancellationToken cancellationToken = default) { {{#allParams}} @@ -225,32 +220,14 @@ namespace Algolia.Search.Clients; } - /// - /// {{{notes}}} (Synchronous version) - /// {{#vendorExtensions}}{{#x-acl.0}} - /// - /// Required API Key ACLs:{{/x-acl.0}} - {{#x-acl}} - /// - {{.}} - {{/x-acl}} - {{/vendorExtensions}} - {{#allParams}} - /// {{description}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isDeprecated}} (deprecated){{/isDeprecated}} - {{/allParams}} - /// Add extra http header or query parameters to Algolia. - /// Cancellation Token to cancel the request. - {{#isDeprecated}} - [Obsolete] - {{/isDeprecated}} - /// Thrown when arguments are not correct - /// Thrown when the API call was rejected by Algolia - /// Thrown when the client failed to call the endpoint - /// {{> return_type_doc}} - public {{^returnType}}void{{/returnType}}{{#returnType}}{{> return_type}}{{/returnType}} {{operationId}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}RequestOptions options = null, CancellationToken cancellationToken = default) => - AsyncHelper.RunSync(() => {{operationId}}Async{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}} options, cancellationToken)); + /// + {{#isDeprecated}} + [Obsolete] + {{/isDeprecated}} + public {{^returnType}}void{{/returnType}}{{#returnType}}{{> return_type}}{{/returnType}} {{operationId}}{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}({{#allParams}}{{{dataType}}} {{paramName}}{{^required}}{{#optionalMethodArgument}} = default{{/optionalMethodArgument}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}}RequestOptions options = null, CancellationToken cancellationToken = default) => + AsyncHelper.RunSync(() => {{operationId}}Async{{#vendorExtensions.x-is-generic}}{{/vendorExtensions.x-is-generic}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#allParams.0}}, {{/allParams.0}} options, cancellationToken)); {{/supportsAsync}} {{/operation}} } {{/operations}} - diff --git a/templates/csharp/netcore_project.mustache b/templates/csharp/netcore_project.mustache index c85b458c15c..3949f096e2e 100644 --- a/templates/csharp/netcore_project.mustache +++ b/templates/csharp/netcore_project.mustache @@ -41,7 +41,7 @@ - + @@ -57,4 +57,4 @@ -{{> netcore_project.additions}} \ No newline at end of file +{{> netcore_project.additions}} From 6c37566daa5d9cef51093f2a88fd276b7865ae4c Mon Sep 17 00:00:00 2001 From: Pierre Millot Date: Fri, 6 Sep 2024 09:13:07 +0200 Subject: [PATCH 2/2] update cts --- tests/output/csharp/src/Algolia.Search.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/output/csharp/src/Algolia.Search.Tests.csproj b/tests/output/csharp/src/Algolia.Search.Tests.csproj index c321d39e4e5..07582883edb 100644 --- a/tests/output/csharp/src/Algolia.Search.Tests.csproj +++ b/tests/output/csharp/src/Algolia.Search.Tests.csproj @@ -20,7 +20,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive