Skip to content

Commit 7f5fe6b

Browse files
authored
feat(clients): expose waitForTasks to batch helpers [skip-bc] (#4030)
1 parent 8876e4b commit 7f5fe6b

File tree

17 files changed

+844
-646
lines changed

17 files changed

+844
-646
lines changed

Diff for: .github/workflows/check.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
runs-on: ubuntu-22.04
4242
timeout-minutes: 10
4343
env:
44-
CACHE_VERSION: 1.02 # bump this to run all clients on the CI.
44+
CACHE_VERSION: 1.10 # bump this to run all clients on the CI.
4545
steps:
4646
- name: debugging - dump GitHub context
4747
env:

Diff for: clients/algoliasearch-client-csharp/algoliasearch/Utils/SearchClientExtensions.cs

+21-16
Original file line numberDiff line numberDiff line change
@@ -166,35 +166,38 @@ public partial interface ISearchClient
166166
/// </summary>
167167
/// <param name="indexName">The index in which to perform the request.</param>
168168
/// <param name="objects">The list of `objects` to store in the given Algolia `indexName`.</param>
169+
/// <param name="waitForTasks">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..</param>
169170
/// <param name="options">Add extra http header or query parameters to Algolia.</param>
170171
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
171172
/// <typeparam name="T"></typeparam>
172-
Task<List<BatchResponse>> SaveObjectsAsync<T>(string indexName, IEnumerable<T> objects, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
173+
Task<List<BatchResponse>> SaveObjectsAsync<T>(string indexName, IEnumerable<T> objects, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
173174
/// <inheritdoc cref="SaveObjectsAsync{T}(string, IEnumerable{T}, RequestOptions, CancellationToken)"/>
174-
List<BatchResponse> SaveObjects<T>(string indexName, IEnumerable<T> objects, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
175+
List<BatchResponse> SaveObjects<T>(string indexName, IEnumerable<T> objects, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
175176

176177
/// <summary>
177178
/// 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.
178179
/// </summary>
179180
/// <param name="indexName">The index in which to perform the request.</param>
180181
/// <param name="objectIDs">The list of `objectIDs` to remove from the given Algolia `indexName`.</param>
182+
/// <param name="waitForTasks">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..</param>
181183
/// <param name="options">Add extra http header or query parameters to Algolia.</param>
182184
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
183-
Task<List<BatchResponse>> DeleteObjectsAsync(string indexName, IEnumerable<String> objectIDs, RequestOptions options = null, CancellationToken cancellationToken = default);
185+
Task<List<BatchResponse>> DeleteObjectsAsync(string indexName, IEnumerable<String> objectIDs, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default);
184186
/// <inheritdoc cref="DeleteObjectsAsync(string, IEnumerable{String}, RequestOptions, CancellationToken)"/>
185-
List<BatchResponse> DeleteObjects(string indexName, IEnumerable<String> objectIDs, RequestOptions options = null, CancellationToken cancellationToken = default);
187+
List<BatchResponse> DeleteObjects(string indexName, IEnumerable<String> objectIDs, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default);
186188

187189
/// <summary>
188190
/// 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.
189191
/// </summary>
190192
/// <param name="indexName">The index in which to perform the request.</param>
191193
/// <param name="objects">The list of `objects` to update in the given Algolia `indexName`.</param>
192194
/// <param name="createIfNotExists">To be provided if non-existing objects are passed, otherwise, the call will fail.</param>
195+
/// <param name="waitForTasks">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..</param>
193196
/// <param name="options">Add extra http header or query parameters to Algolia.</param>
194197
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
195-
Task<List<BatchResponse>> PartialUpdateObjectsAsync<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
198+
Task<List<BatchResponse>> PartialUpdateObjectsAsync<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
196199
/// <inheritdoc cref="PartialUpdateObjectsAsync{T}(string, IEnumerable{T}, bool, RequestOptions, CancellationToken)"/>
197-
List<BatchResponse> PartialUpdateObjects<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
200+
List<BatchResponse> PartialUpdateObjects<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, bool waitForTasks = false, RequestOptions options = null, CancellationToken cancellationToken = default) where T : class;
198201

199202
/// <summary>
200203
/// Helper: Check if an index exists.
@@ -564,42 +567,44 @@ public List<BatchResponse> ChunkedBatch<T>(string indexName, IEnumerable<T> obje
564567

565568
/// <inheritdoc/>
566569
public async Task<List<BatchResponse>> SaveObjectsAsync<T>(string indexName, IEnumerable<T> objects,
570+
bool waitForTasks = false,
567571
RequestOptions options = null,
568572
CancellationToken cancellationToken = default) where T : class
569573
{
570-
return await ChunkedBatchAsync(indexName, objects, Action.AddObject, false, 1000, options, cancellationToken).ConfigureAwait(false);
574+
return await ChunkedBatchAsync(indexName, objects, Action.AddObject, waitForTasks, 1000, options, cancellationToken).ConfigureAwait(false);
571575
}
572576

573577
/// <inheritdoc/>
574-
public List<BatchResponse> SaveObjects<T>(string indexName, IEnumerable<T> objects, RequestOptions options = null,
578+
public List<BatchResponse> SaveObjects<T>(string indexName, IEnumerable<T> objects, bool waitForTasks = false, RequestOptions options = null,
575579
CancellationToken cancellationToken = default) where T : class =>
576-
AsyncHelper.RunSync(() => SaveObjectsAsync(indexName, objects, options, cancellationToken));
580+
AsyncHelper.RunSync(() => SaveObjectsAsync(indexName, objects, waitForTasks, options, cancellationToken));
577581

578582
/// <inheritdoc/>
579583
public async Task<List<BatchResponse>> DeleteObjectsAsync(string indexName, IEnumerable<String> objectIDs,
584+
bool waitForTasks = false,
580585
RequestOptions options = null,
581586
CancellationToken cancellationToken = default)
582587
{
583-
return await ChunkedBatchAsync(indexName, objectIDs.Select(id => new { objectID = id }), Action.DeleteObject, false, 1000, options, cancellationToken).ConfigureAwait(false);
588+
return await ChunkedBatchAsync(indexName, objectIDs.Select(id => new { objectID = id }), Action.DeleteObject, waitForTasks, 1000, options, cancellationToken).ConfigureAwait(false);
584589
}
585590

586591
/// <inheritdoc/>
587-
public List<BatchResponse> DeleteObjects(string indexName, IEnumerable<String> objectIDs, RequestOptions options = null,
592+
public List<BatchResponse> DeleteObjects(string indexName, IEnumerable<String> objectIDs, bool waitForTasks = false, RequestOptions options = null,
588593
CancellationToken cancellationToken = default) =>
589-
AsyncHelper.RunSync(() => DeleteObjectsAsync(indexName, objectIDs, options, cancellationToken));
594+
AsyncHelper.RunSync(() => DeleteObjectsAsync(indexName, objectIDs, waitForTasks, options, cancellationToken));
590595

591596
/// <inheritdoc/>
592-
public async Task<List<BatchResponse>> PartialUpdateObjectsAsync<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists,
597+
public async Task<List<BatchResponse>> PartialUpdateObjectsAsync<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, bool waitForTasks = false,
593598
RequestOptions options = null,
594599
CancellationToken cancellationToken = default) where T : class
595600
{
596-
return await ChunkedBatchAsync(indexName, objects, createIfNotExists ? Action.PartialUpdateObject : Action.PartialUpdateObjectNoCreate, false, 1000, options, cancellationToken).ConfigureAwait(false);
601+
return await ChunkedBatchAsync(indexName, objects, createIfNotExists ? Action.PartialUpdateObject : Action.PartialUpdateObjectNoCreate, waitForTasks, 1000, options, cancellationToken).ConfigureAwait(false);
597602
}
598603

599604
/// <inheritdoc/>
600-
public List<BatchResponse> PartialUpdateObjects<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists,
605+
public List<BatchResponse> PartialUpdateObjects<T>(string indexName, IEnumerable<T> objects, bool createIfNotExists, bool waitForTasks = false,
601606
RequestOptions options = null, CancellationToken cancellationToken = default) where T : class =>
602-
AsyncHelper.RunSync(() => PartialUpdateObjectsAsync(indexName, objects, createIfNotExists, options, cancellationToken));
607+
AsyncHelper.RunSync(() => PartialUpdateObjectsAsync(indexName, objects, createIfNotExists, waitForTasks, options, cancellationToken));
603608

604609
private static async Task<List<TU>> CreateIterable<TU>(Func<TU, Task<TU>> executeQuery,
605610
Func<TU, bool> stopCondition)

Diff for: clients/algoliasearch-client-kotlin/client/src/commonMain/kotlin/com/algolia/client/extensions/SearchClient.kt

+9-3
Original file line numberDiff line numberDiff line change
@@ -369,20 +369,22 @@ public suspend fun SearchClient.chunkedBatch(
369369
*
370370
* @param indexName The index in which to perform the request.
371371
* @param objects The list of objects to index.
372+
* @param waitForTask If true, wait for the task to complete.
372373
* @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
373374
* @return The list of responses from the batch requests.
374375
*
375376
*/
376377
public suspend fun SearchClient.saveObjects(
377378
indexName: String,
378379
objects: List<JsonObject>,
380+
waitForTask: Boolean = false,
379381
requestOptions: RequestOptions? = null,
380382
): List<BatchResponse> {
381383
return this.chunkedBatch(
382384
indexName = indexName,
383385
objects = objects,
384386
action = Action.AddObject,
385-
waitForTask = false,
387+
waitForTask = waitForTask,
386388
batchSize = 1000,
387389
requestOptions = requestOptions,
388390
)
@@ -393,20 +395,22 @@ public suspend fun SearchClient.saveObjects(
393395
*
394396
* @param indexName The index in which to perform the request.
395397
* @param objectIDs The list of objectIDs to delete from the index.
398+
* @param waitForTask If true, wait for the task to complete.
396399
* @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
397400
* @return The list of responses from the batch requests.
398401
*
399402
*/
400403
public suspend fun SearchClient.deleteObjects(
401404
indexName: String,
402405
objectIDs: List<String>,
406+
waitForTask: Boolean = false,
403407
requestOptions: RequestOptions? = null,
404408
): List<BatchResponse> {
405409
return this.chunkedBatch(
406410
indexName = indexName,
407411
objects = objectIDs.map { id -> JsonObject(mapOf("objectID" to Json.encodeToJsonElement(id))) },
408412
action = Action.DeleteObject,
409-
waitForTask = false,
413+
waitForTask = waitForTask,
410414
batchSize = 1000,
411415
requestOptions = requestOptions,
412416
)
@@ -418,6 +422,7 @@ public suspend fun SearchClient.deleteObjects(
418422
* @param indexName The index in which to perform the request.
419423
* @param objects The list of objects to update in the index.
420424
* @param createIfNotExists To be provided if non-existing objects are passed, otherwise, the call will fail..
425+
* @param waitForTask If true, wait for the task to complete.
421426
* @param requestOptions The requestOptions to send along with the query, they will be merged with the transporter requestOptions.
422427
* @return The list of responses from the batch requests.
423428
*
@@ -426,13 +431,14 @@ public suspend fun SearchClient.partialUpdateObjects(
426431
indexName: String,
427432
objects: List<JsonObject>,
428433
createIfNotExists: Boolean,
434+
waitForTask: Boolean = false,
429435
requestOptions: RequestOptions? = null,
430436
): List<BatchResponse> {
431437
return this.chunkedBatch(
432438
indexName = indexName,
433439
objects = objects,
434440
action = if (createIfNotExists) Action.PartialUpdateObject else Action.PartialUpdateObjectNoCreate,
435-
waitForTask = false,
441+
waitForTask = waitForTask,
436442
batchSize = 1000,
437443
requestOptions = requestOptions,
438444
)

Diff for: clients/algoliasearch-client-scala/src/main/scala/algoliasearch/extension/package.scala

+12-3
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ package object extension {
251251
* The index in which to perform the request.
252252
* @param objects
253253
* The list of objects to save.
254+
* @param waitForTasks
255+
* Whether to wait for the tasks to complete.
254256
* @param requestOptions
255257
* Additional request configuration.
256258
* @return
@@ -259,9 +261,10 @@ package object extension {
259261
def saveObjects(
260262
indexName: String,
261263
objects: Seq[Any],
264+
waitForTasks: Boolean = false,
262265
requestOptions: Option[RequestOptions] = None
263266
)(implicit ec: ExecutionContext): Future[Seq[BatchResponse]] = {
264-
chunkedBatch(indexName, objects, Action.AddObject, false, 1000, requestOptions)
267+
chunkedBatch(indexName, objects, Action.AddObject, waitForTasks, 1000, requestOptions)
265268
}
266269

267270
/** Helper: Deletes every objects for the given objectIDs. The `chunkedBatch` helper is used under the hood, which
@@ -271,6 +274,8 @@ package object extension {
271274
* The index in which to perform the request.
272275
* @param objectIDs
273276
* The list of objectIDs to delete.
277+
* @param waitForTasks
278+
* Whether to wait for the tasks to complete.
274279
* @param requestOptions
275280
* Additional request configuration.
276281
* @return
@@ -279,13 +284,14 @@ package object extension {
279284
def deleteObjects(
280285
indexName: String,
281286
objectIDs: Seq[String],
287+
waitForTasks: Boolean = false,
282288
requestOptions: Option[RequestOptions] = None
283289
)(implicit ec: ExecutionContext): Future[Seq[BatchResponse]] = {
284290
chunkedBatch(
285291
indexName,
286292
objectIDs.map(id => new { val objectID: String = id }),
287293
Action.DeleteObject,
288-
false,
294+
waitForTasks,
289295
1000,
290296
requestOptions
291297
)
@@ -300,6 +306,8 @@ package object extension {
300306
* The list of objects to save.
301307
* @param createIfNotExists
302308
* To be provided if non-existing objects are passed, otherwise, the call will fail.
309+
* @param waitForTasks
310+
* Whether to wait for the tasks to complete.
303311
* @param requestOptions
304312
* Additional request configuration.
305313
* @return
@@ -309,13 +317,14 @@ package object extension {
309317
indexName: String,
310318
objects: Seq[Any],
311319
createIfNotExists: Boolean = false,
320+
waitForTasks: Boolean = false,
312321
requestOptions: Option[RequestOptions] = None
313322
)(implicit ec: ExecutionContext): Future[Seq[BatchResponse]] = {
314323
chunkedBatch(
315324
indexName,
316325
objects,
317326
if (createIfNotExists) Action.PartialUpdateObject else Action.PartialUpdateObjectNoCreate,
318-
false,
327+
waitForTasks,
319328
1000,
320329
requestOptions
321330
)

Diff for: clients/algoliasearch-client-swift/Sources/Search/Extra/SearchClientExtension.swift

+9-3
Original file line numberDiff line numberDiff line change
@@ -463,18 +463,20 @@ public extension SearchClient {
463463
/// which creates a `batch` requests with at most 1000 objects in it.
464464
/// - parameter indexName: The name of the index where to save the objects
465465
/// - parameter objects: The new objects
466+
/// - parameter waitForTasks: If we should wait for the batch task to be finished before processing the next one
466467
/// - parameter requestOptions: The request options
467468
/// - returns: [BatchResponse]
468469
func saveObjects(
469470
indexName: String,
470471
objects: [some Encodable],
472+
waitForTasks: Bool = false,
471473
requestOptions: RequestOptions? = nil
472474
) async throws -> [BatchResponse] {
473475
try await self.chunkedBatch(
474476
indexName: indexName,
475477
objects: objects,
476478
action: .addObject,
477-
waitForTasks: false,
479+
waitForTasks: waitForTasks,
478480
batchSize: 1000,
479481
requestOptions: requestOptions
480482
)
@@ -484,18 +486,20 @@ public extension SearchClient {
484486
/// creates a `batch` requests with at most 1000 objectIDs in it.
485487
/// - parameter indexName: The name of the index to delete objectIDs from
486488
/// - parameter objectIDs: The objectIDs to delete
489+
/// - parameter waitForTasks: If we should wait for the batch task to be finished before processing the next one
487490
/// - parameter requestOptions: The request options
488491
/// - returns: [BatchResponse]
489492
func deleteObjects(
490493
indexName: String,
491494
objectIDs: [String],
495+
waitForTasks: Bool = false,
492496
requestOptions: RequestOptions? = nil
493497
) async throws -> [BatchResponse] {
494498
try await self.chunkedBatch(
495499
indexName: indexName,
496500
objects: objectIDs.map { AnyCodable(["objectID": $0]) },
497501
action: .deleteObject,
498-
waitForTasks: false,
502+
waitForTasks: waitForTasks,
499503
batchSize: 1000,
500504
requestOptions: requestOptions
501505
)
@@ -507,19 +511,21 @@ public extension SearchClient {
507511
/// - parameter objects: The objects to update
508512
/// - parameter createIfNotExists: To be provided if non-existing objects are passed, otherwise, the call will
509513
/// fail..
514+
/// - parameter waitForTasks: If we should wait for the batch task to be finished before processing the next one
510515
/// - parameter requestOptions: The request options
511516
/// - returns: [BatchResponse]
512517
func partialUpdateObjects(
513518
indexName: String,
514519
objects: [some Encodable],
515520
createIfNotExists: Bool = false,
521+
waitForTasks: Bool = false,
516522
requestOptions: RequestOptions? = nil
517523
) async throws -> [BatchResponse] {
518524
try await self.chunkedBatch(
519525
indexName: indexName,
520526
objects: objects,
521527
action: createIfNotExists ? .partialUpdateObject : .partialUpdateObjectNoCreate,
522-
waitForTasks: false,
528+
waitForTasks: waitForTasks,
523529
batchSize: 1000,
524530
requestOptions: requestOptions
525531
)

Diff for: playground/python/app/search.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
from asyncio import run
21
from os import environ
32

4-
from algoliasearch.search.client import SearchClient
3+
from algoliasearch.search.client import SearchClientSync
54
from algoliasearch.search import __version__
65
from dotenv import load_dotenv
76

87
load_dotenv("../.env")
98

109

11-
async def main():
10+
def main():
1211
print("SearchClient version", __version__)
1312

14-
client = SearchClient(
13+
client = SearchClientSync(
1514
environ.get("ALGOLIA_APPLICATION_ID"), environ.get("ALGOLIA_ADMIN_KEY")
1615
)
1716
print("client initialized", client)
1817

1918
try:
20-
resp = await client.search(search_method_params={
21-
"requests": [{"indexName": "api-clients-automation"}]
22-
})
23-
print(resp.to_dict())
19+
resp = client.save_objects("foo", [{"foo": "bar"}])
20+
print(resp)
21+
22+
for r in resp:
23+
client.wait_for_task(index_name="foo", task_id=r.task_id)
2424
finally:
25-
await client.close()
25+
client.close()
2626

2727
print("client closed")
2828

2929

30-
run(main())
30+
main()

0 commit comments

Comments
 (0)