algolia 3.39.1 → 3.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +1 -1
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/lib/algolia/api/ingestion_client.rb +71 -0
- data/lib/algolia/api/search_client.rb +342 -22
- data/lib/algolia/chunked_helper_options.rb +15 -0
- data/lib/algolia/configuration.rb +3 -1
- data/lib/algolia/models/abtesting/ab_test.rb +5 -0
- data/lib/algolia/models/query-suggestions/configuration.rb +1 -0
- data/lib/algolia/models/query-suggestions/configuration_response.rb +1 -0
- data/lib/algolia/models/query-suggestions/configuration_with_index.rb +1 -0
- data/lib/algolia/models/query-suggestions/source_index.rb +4 -0
- data/lib/algolia/models/recommend/fallback_params.rb +2 -1
- data/lib/algolia/models/recommend/recommend_search_params.rb +2 -1
- data/lib/algolia/models/search/browse_params_object.rb +2 -1
- data/lib/algolia/models/search/consequence_params.rb +2 -1
- data/lib/algolia/models/search/fetched_index.rb +25 -4
- data/lib/algolia/models/search/fetched_index_ab_test.rb +253 -0
- data/lib/algolia/models/search/fetched_index_ab_test_target.rb +210 -0
- data/lib/algolia/models/search/fetched_index_ab_test_variant.rb +242 -0
- data/lib/algolia/models/search/index_settings.rb +2 -1
- data/lib/algolia/models/search/search_for_facets.rb +2 -1
- data/lib/algolia/models/search/search_for_hits.rb +2 -1
- data/lib/algolia/models/search/search_params_object.rb +2 -1
- data/lib/algolia/models/search/search_response_partial.rb +587 -0
- data/lib/algolia/models/search/search_result.rb +2 -1
- data/lib/algolia/models/search/settings_response.rb +2 -1
- data/lib/algolia/version.rb +1 -1
- data/lib/algolia.rb +1 -2
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7030ad3b848a8e074b47b86a06c9b2494a1141097ce80c9e3e0a50c81e96aacb
|
|
4
|
+
data.tar.gz: 336d669b4166d8edf241d3b63c31bc51155f718282a9c91819b21625ce022091
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b4be15c6ca713800092aad40bacd12e508b048f082c08e76c8f14c7d70bea63788b52b1feddb33100dfaf2c0eba0ade284cbf46691f1a341eb15a8c06fd2d4c
|
|
7
|
+
data.tar.gz: a3ae3ff7bcbc1d78a9e0e4ae937d9a06b3ddad1520529ba722d95d6f2e43d4bb18a43c1d3c397c47bc5af9d892bdbe9815ed9349291ae060537f51ef5fabb5b2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [3.40.0](https://github.com/algolia/algoliasearch-client-ruby/compare/3.39.1...3.40.0)
|
|
2
|
+
|
|
3
|
+
BREAKING CHANGES: this minor version includes breaking changes. See below for more details.
|
|
4
|
+
|
|
5
|
+
- [84ebc480a8](https://github.com/algolia/api-clients-automation/commit/84ebc480a8) chore(deps): dependencies 2026-05-15 ([#6400](https://github.com/algolia/api-clients-automation/pull/6400)) by [@Fluf22](https://github.com/Fluf22/)
|
|
6
|
+
- [90da6bf0ae](https://github.com/algolia/api-clients-automation/commit/90da6bf0ae) chore(deps): dependencies 2026-05-18 ([#6429](https://github.com/algolia/api-clients-automation/pull/6429)) by [@Fluf22](https://github.com/Fluf22/)
|
|
7
|
+
- [77cfd0447b](https://github.com/algolia/api-clients-automation/commit/77cfd0447b) feat(ruby): add TransformationOptions for ingestion transporter configuration ([#6313](https://github.com/algolia/api-clients-automation/pull/6313)) by [@MarioAlexandruDan](https://github.com/MarioAlexandruDan/)
|
|
8
|
+
- [eddd51e349](https://github.com/algolia/api-clients-automation/commit/eddd51e349) fix(specs): document abTest field on listIndices response ([#6443](https://github.com/algolia/api-clients-automation/pull/6443)) by [@eric-zaharia](https://github.com/eric-zaharia/)
|
|
9
|
+
- [1d3f2c149b](https://github.com/algolia/api-clients-automation/commit/1d3f2c149b) fix(specs): clean up abTest schema on listIndices response ([#6448](https://github.com/algolia/api-clients-automation/pull/6448)) by [@Fluf22](https://github.com/Fluf22/)
|
|
10
|
+
- [35bf16c848](https://github.com/algolia/api-clients-automation/commit/35bf16c848) fix(specs): BREAKING CHANGE – add searchResponsePartial fallback to searchResult oneOf ([#6350](https://github.com/algolia/api-clients-automation/pull/6350)) by [@Fluf22](https://github.com/Fluf22/)
|
|
11
|
+
- For those of you who want really clean responses without hits nor facets, we added a third fallback type to the search response. It should not impact the rest of the users.
|
|
12
|
+
- [e4f6b366a1](https://github.com/algolia/api-clients-automation/commit/e4f6b366a1) feat(ruby): BREAKING CHANGE – expose maximum number of retries ([#6461](https://github.com/algolia/api-clients-automation/pull/6461)) by [@eric-zaharia](https://github.com/eric-zaharia/)
|
|
13
|
+
- We updated the default number of retries to account for customers with huge indices, and made it configurable if you prefer to fail early. The impact is that the retry time will be longer in case of issue, but it shouldn't impact most customers: those who don't have issues.
|
|
14
|
+
|
|
1
15
|
## [3.39.1](https://github.com/algolia/algoliasearch-client-ruby/compare/3.39.0...3.39.1)
|
|
2
16
|
|
|
3
17
|
- [363cc2d91b](https://github.com/algolia/api-clients-automation/commit/363cc2d91b) fix(specs): Ingestion API - update destination payload ([#6320](https://github.com/algolia/api-clients-automation/pull/6320)) by [@sbellone](https://github.com/sbellone/)
|
data/Gemfile.lock
CHANGED
|
@@ -3588,5 +3588,76 @@ module Algolia
|
|
|
3588
3588
|
@api_client.deserialize(response.body, request_options[:debug_return_type] || "Ingestion::WatchResponse")
|
|
3589
3589
|
end
|
|
3590
3590
|
|
|
3591
|
+
# Helper: Pushes objects to the given index in chunks, optionally waiting for each batch to be processed.
|
|
3592
|
+
#
|
|
3593
|
+
# @param index_name [String] the `index_name` where the operation will be performed. (required)
|
|
3594
|
+
# @param objects [Array] the array of objects to push to the given Algolia `index_name`. (required)
|
|
3595
|
+
# @param action [String] the push action to perform on the objects. (optional, default: addObject)
|
|
3596
|
+
# @param wait_for_tasks [Boolean] whether to wait until every task has been processed. (optional, default: false)
|
|
3597
|
+
# @param batch_size [Integer] the size of each chunk of objects sent in a single push call. (optional, default: 1000)
|
|
3598
|
+
# @param reference_index_name [String] the reference index name used for replace-all operations. (optional)
|
|
3599
|
+
# @param request_options [Hash] the request options to send along with the query. (optional)
|
|
3600
|
+
#
|
|
3601
|
+
# @return [Array<Ingestion::WatchResponse>]
|
|
3602
|
+
def chunked_push(
|
|
3603
|
+
index_name,
|
|
3604
|
+
objects,
|
|
3605
|
+
action = Ingestion::Action::ADD_OBJECT,
|
|
3606
|
+
wait_for_tasks = false,
|
|
3607
|
+
batch_size = 1000,
|
|
3608
|
+
reference_index_name = nil,
|
|
3609
|
+
request_options = {},
|
|
3610
|
+
chunked_options = nil
|
|
3611
|
+
)
|
|
3612
|
+
responses = []
|
|
3613
|
+
offset = 0
|
|
3614
|
+
wait_batch_size = batch_size / 10
|
|
3615
|
+
wait_batch_size = batch_size if wait_batch_size < 1
|
|
3616
|
+
total_batches = (objects.length.to_f / batch_size).ceil
|
|
3617
|
+
opts = Algolia::ChunkedHelperOptions.resolve(chunked_options)
|
|
3618
|
+
|
|
3619
|
+
objects.each_slice(batch_size).with_index do |chunk, batch_index|
|
|
3620
|
+
response = push(
|
|
3621
|
+
index_name,
|
|
3622
|
+
Ingestion::PushTaskPayload.new(action: action, records: chunk),
|
|
3623
|
+
false,
|
|
3624
|
+
reference_index_name,
|
|
3625
|
+
request_options
|
|
3626
|
+
)
|
|
3627
|
+
responses << response
|
|
3628
|
+
|
|
3629
|
+
if wait_for_tasks && (responses.length % wait_batch_size == 0 || batch_index == total_batches - 1)
|
|
3630
|
+
responses[offset, wait_batch_size].each do |watch_response|
|
|
3631
|
+
if watch_response.event_id.nil?
|
|
3632
|
+
raise ArgumentError, "received unexpected response from the push endpoint, eventID must not be nil"
|
|
3633
|
+
end
|
|
3634
|
+
|
|
3635
|
+
retries = 0
|
|
3636
|
+
loop do
|
|
3637
|
+
begin
|
|
3638
|
+
event = get_event(watch_response.run_id, watch_response.event_id, request_options)
|
|
3639
|
+
break if event
|
|
3640
|
+
rescue AlgoliaHttpError => e
|
|
3641
|
+
raise e unless e.code == 404
|
|
3642
|
+
end
|
|
3643
|
+
|
|
3644
|
+
retries += 1
|
|
3645
|
+
if retries >= opts.max_retries
|
|
3646
|
+
raise(
|
|
3647
|
+
ApiError,
|
|
3648
|
+
"Stopped waiting for the task after #{opts.max_retries} retries. This does not mean the operation failed; it may still complete. If you need to keep polling, retry with a higher max_retries."
|
|
3649
|
+
)
|
|
3650
|
+
end
|
|
3651
|
+
|
|
3652
|
+
sleep([retries * 1.5, 5].min)
|
|
3653
|
+
end
|
|
3654
|
+
end
|
|
3655
|
+
|
|
3656
|
+
offset += wait_batch_size
|
|
3657
|
+
end
|
|
3658
|
+
end
|
|
3659
|
+
|
|
3660
|
+
responses
|
|
3661
|
+
end
|
|
3591
3662
|
end
|
|
3592
3663
|
end
|
|
@@ -6,6 +6,49 @@ require "openssl"
|
|
|
6
6
|
require "base64"
|
|
7
7
|
|
|
8
8
|
module Algolia
|
|
9
|
+
# Configuration options for the ingestion transporter used by *_with_transformation helpers.
|
|
10
|
+
# When passed to SearchClient.with_transformation or set via set_transformation_options,
|
|
11
|
+
# the ingestion transporter is eagerly created using Ingestion API defaults (25s timeouts,
|
|
12
|
+
# no compression). Only fields explicitly set here override those defaults.
|
|
13
|
+
# See https://www.algolia.com/doc/libraries/ruby/v3/methods/ingestion
|
|
14
|
+
class TransformationOptions
|
|
15
|
+
attr_accessor(
|
|
16
|
+
:region,
|
|
17
|
+
:connect_timeout,
|
|
18
|
+
:read_timeout,
|
|
19
|
+
:write_timeout,
|
|
20
|
+
:hosts,
|
|
21
|
+
:compression_type,
|
|
22
|
+
:header_params
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def initialize(region, opts = {})
|
|
26
|
+
if region.nil? || region.to_s.strip.empty?
|
|
27
|
+
raise(
|
|
28
|
+
ArgumentError,
|
|
29
|
+
"`region` is required in `TransformationOptions`. See https://www.algolia.com/doc/libraries/ruby/v3/methods/ingestion"
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
valid_keys = %i[connect_timeout read_timeout write_timeout hosts compression_type header_params]
|
|
34
|
+
unknown = opts.keys - valid_keys
|
|
35
|
+
unless unknown.empty?
|
|
36
|
+
raise(
|
|
37
|
+
ArgumentError,
|
|
38
|
+
"Unknown TransformationOptions keys: #{unknown.join(", ")}. Valid keys are: #{valid_keys.join(", ")}"
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@region = region
|
|
43
|
+
@connect_timeout = opts[:connect_timeout]
|
|
44
|
+
@read_timeout = opts[:read_timeout]
|
|
45
|
+
@write_timeout = opts[:write_timeout]
|
|
46
|
+
@hosts = opts[:hosts]
|
|
47
|
+
@compression_type = opts[:compression_type]
|
|
48
|
+
@header_params = opts[:header_params]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
9
52
|
class SearchClient
|
|
10
53
|
attr_accessor :api_client
|
|
11
54
|
|
|
@@ -27,6 +70,10 @@ module Algolia
|
|
|
27
70
|
end
|
|
28
71
|
|
|
29
72
|
@api_client = Algolia::ApiClient.new(config)
|
|
73
|
+
@ingestion_transporter = nil
|
|
74
|
+
if config.transformation_options
|
|
75
|
+
@ingestion_transporter = _build_ingestion_transporter(config.transformation_options)
|
|
76
|
+
end
|
|
30
77
|
end
|
|
31
78
|
|
|
32
79
|
def self.create(app_id, api_key, opts = {})
|
|
@@ -49,6 +96,31 @@ module Algolia
|
|
|
49
96
|
new(config)
|
|
50
97
|
end
|
|
51
98
|
|
|
99
|
+
# Creates a SearchClient configured with a TransformationOptions for use with
|
|
100
|
+
# *_with_transformation helpers. The ingestion transporter is initialised eagerly using
|
|
101
|
+
# Ingestion API defaults (25s timeouts); set override fields on TransformationOptions to
|
|
102
|
+
# change specific defaults.
|
|
103
|
+
# See https://www.algolia.com/doc/libraries/ruby/v3/methods/ingestion
|
|
104
|
+
#
|
|
105
|
+
# @param app_id [String] the Algolia application ID. (required)
|
|
106
|
+
# @param api_key [String] the Algolia API key. (required)
|
|
107
|
+
# @param transformation_options [TransformationOptions] the transformation options including region and optional ingestion transporter overrides. (required)
|
|
108
|
+
# @param opts [Hash] additional configuration options passed to the search client. (optional)
|
|
109
|
+
# @return [SearchClient]
|
|
110
|
+
def self.with_transformation(app_id, api_key, transformation_options, opts = {})
|
|
111
|
+
opts = opts.dup
|
|
112
|
+
hosts = opts.delete(:hosts)
|
|
113
|
+
if hosts
|
|
114
|
+
config = Algolia::Configuration.new(app_id, api_key, hosts, "Search", opts)
|
|
115
|
+
client = new(config)
|
|
116
|
+
else
|
|
117
|
+
client = create(app_id, api_key, opts)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
client.set_transformation_options(transformation_options)
|
|
121
|
+
client
|
|
122
|
+
end
|
|
123
|
+
|
|
52
124
|
# Helper method to switch the API key used to authenticate the requests.
|
|
53
125
|
#
|
|
54
126
|
# @param api_key [String] the new API key to use.
|
|
@@ -3340,18 +3412,231 @@ module Algolia
|
|
|
3340
3412
|
@api_client.deserialize(response.body, request_options[:debug_return_type] || "Search::UpdateApiKeyResponse")
|
|
3341
3413
|
end
|
|
3342
3414
|
|
|
3415
|
+
# The parent search config MUST NOT leak into the ingestion transporter.
|
|
3416
|
+
def _build_ingestion_transporter(transformation_options)
|
|
3417
|
+
hosts = if transformation_options.hosts
|
|
3418
|
+
transformation_options.hosts
|
|
3419
|
+
else
|
|
3420
|
+
[
|
|
3421
|
+
Transport::StatefulHost.new(
|
|
3422
|
+
"data.#{transformation_options.region}.algolia.com",
|
|
3423
|
+
accept: CallType::READ | CallType::WRITE
|
|
3424
|
+
)
|
|
3425
|
+
]
|
|
3426
|
+
end
|
|
3427
|
+
|
|
3428
|
+
opts = {}
|
|
3429
|
+
unless transformation_options.connect_timeout.nil?
|
|
3430
|
+
opts[:connect_timeout] = transformation_options.connect_timeout
|
|
3431
|
+
end
|
|
3432
|
+
|
|
3433
|
+
opts[:read_timeout] = transformation_options.read_timeout unless transformation_options.read_timeout.nil?
|
|
3434
|
+
opts[:write_timeout] = transformation_options.write_timeout unless transformation_options.write_timeout.nil?
|
|
3435
|
+
unless transformation_options.compression_type.nil?
|
|
3436
|
+
opts[:compression_type] = transformation_options.compression_type
|
|
3437
|
+
end
|
|
3438
|
+
|
|
3439
|
+
config = Algolia::Configuration.new(
|
|
3440
|
+
@api_client.config.app_id,
|
|
3441
|
+
@api_client.config.api_key,
|
|
3442
|
+
hosts,
|
|
3443
|
+
"Ingestion",
|
|
3444
|
+
opts
|
|
3445
|
+
)
|
|
3446
|
+
|
|
3447
|
+
if transformation_options.header_params
|
|
3448
|
+
config.header_params = config.header_params.merge(transformation_options.header_params)
|
|
3449
|
+
end
|
|
3450
|
+
|
|
3451
|
+
Algolia::IngestionClient.create_with_config(config)
|
|
3452
|
+
end
|
|
3453
|
+
|
|
3454
|
+
# Helper: Sets (or replaces) the ingestion transporter used by *_with_transformation helpers.
|
|
3455
|
+
#
|
|
3456
|
+
# @param transformation_options [TransformationOptions] the transformation options including region and optional ingestion transporter overrides. (required)
|
|
3457
|
+
def set_transformation_options(transformation_options)
|
|
3458
|
+
raise ArgumentError, "`transformation_options` must not be nil" if transformation_options.nil?
|
|
3459
|
+
@ingestion_transporter = _build_ingestion_transporter(transformation_options)
|
|
3460
|
+
end
|
|
3461
|
+
|
|
3462
|
+
def assert_ingestion_transporter!
|
|
3463
|
+
if @ingestion_transporter.nil?
|
|
3464
|
+
raise(
|
|
3465
|
+
ArgumentError,
|
|
3466
|
+
"`transformation_options` must be set in the client config before calling this method. It defaults to the Ingestion API defaults. See https://www.algolia.com/doc/libraries/ruby/v3/methods/ingestion/"
|
|
3467
|
+
)
|
|
3468
|
+
end
|
|
3469
|
+
end
|
|
3470
|
+
|
|
3471
|
+
# Helper: Similar to the `save_objects` method but requires a Push connector to be created first,
|
|
3472
|
+
# in order to transform records before indexing them to Algolia.
|
|
3473
|
+
# `set_transformation_options` must have been called, or the client created via `SearchClient.with_transformation`.
|
|
3474
|
+
#
|
|
3475
|
+
# @param index_name [String] the `index_name` where the operation will be performed. (required)
|
|
3476
|
+
# @param objects [Array] the array of objects to store in the given Algolia `index_name`. (required)
|
|
3477
|
+
# @param wait_for_tasks [Boolean] whether to wait until every task has been processed. (optional, default: false)
|
|
3478
|
+
# @param batch_size [Integer] the size of each chunk of objects sent in a single push call. (optional, default: 1000)
|
|
3479
|
+
# @param request_options [Hash] the request options to send along with the query. (optional)
|
|
3480
|
+
#
|
|
3481
|
+
# @return [Array<Ingestion::WatchResponse>]
|
|
3482
|
+
def save_objects_with_transformation(
|
|
3483
|
+
index_name,
|
|
3484
|
+
objects,
|
|
3485
|
+
wait_for_tasks = false,
|
|
3486
|
+
batch_size = 1000,
|
|
3487
|
+
request_options = {},
|
|
3488
|
+
chunked_options = nil
|
|
3489
|
+
)
|
|
3490
|
+
assert_ingestion_transporter!
|
|
3491
|
+
|
|
3492
|
+
@ingestion_transporter.chunked_push(
|
|
3493
|
+
index_name,
|
|
3494
|
+
objects,
|
|
3495
|
+
Ingestion::Action::ADD_OBJECT,
|
|
3496
|
+
wait_for_tasks,
|
|
3497
|
+
batch_size,
|
|
3498
|
+
nil,
|
|
3499
|
+
request_options,
|
|
3500
|
+
chunked_options
|
|
3501
|
+
)
|
|
3502
|
+
end
|
|
3503
|
+
|
|
3504
|
+
# Helper: Similar to the `partial_update_objects` method but requires a Push connector to be created first,
|
|
3505
|
+
# in order to transform records before indexing them to Algolia.
|
|
3506
|
+
# `set_transformation_options` must have been called, or the client created via `SearchClient.with_transformation`.
|
|
3507
|
+
#
|
|
3508
|
+
# @param index_name [String] the `index_name` where the operation will be performed. (required)
|
|
3509
|
+
# @param objects [Array] the array of objects to update in the given Algolia `index_name`. (required)
|
|
3510
|
+
# @param create_if_not_exists [Boolean] whether to create objects that do not exist. (optional, default: false)
|
|
3511
|
+
# @param wait_for_tasks [Boolean] whether to wait until every task has been processed. (optional, default: false)
|
|
3512
|
+
# @param batch_size [Integer] the size of each chunk of objects sent in a single push call. (optional, default: 1000)
|
|
3513
|
+
# @param request_options [Hash] the request options to send along with the query. (optional)
|
|
3514
|
+
#
|
|
3515
|
+
# @return [Array<Ingestion::WatchResponse>]
|
|
3516
|
+
def partial_update_objects_with_transformation(
|
|
3517
|
+
index_name,
|
|
3518
|
+
objects,
|
|
3519
|
+
create_if_not_exists = false,
|
|
3520
|
+
wait_for_tasks = false,
|
|
3521
|
+
batch_size = 1000,
|
|
3522
|
+
request_options = {},
|
|
3523
|
+
chunked_options = nil
|
|
3524
|
+
)
|
|
3525
|
+
assert_ingestion_transporter!
|
|
3526
|
+
|
|
3527
|
+
action = create_if_not_exists ? Ingestion::Action::PARTIAL_UPDATE_OBJECT : Ingestion::Action::PARTIAL_UPDATE_OBJECT_NO_CREATE
|
|
3528
|
+
|
|
3529
|
+
@ingestion_transporter.chunked_push(
|
|
3530
|
+
index_name,
|
|
3531
|
+
objects,
|
|
3532
|
+
action,
|
|
3533
|
+
wait_for_tasks,
|
|
3534
|
+
batch_size,
|
|
3535
|
+
nil,
|
|
3536
|
+
request_options,
|
|
3537
|
+
chunked_options
|
|
3538
|
+
)
|
|
3539
|
+
end
|
|
3540
|
+
|
|
3541
|
+
# Helper: Similar to the `replace_all_objects` method but requires a Push connector to be created first,
|
|
3542
|
+
# in order to transform records before indexing them to Algolia.
|
|
3543
|
+
# `set_transformation_options` must have been called, or the client created via `SearchClient.with_transformation`.
|
|
3544
|
+
#
|
|
3545
|
+
# @param index_name [String] the `index_name` to replace objects in. (required)
|
|
3546
|
+
# @param objects [Array] the array of objects to store in the given Algolia `index_name`. (required)
|
|
3547
|
+
# @param batch_size [Integer] the size of each chunk of objects sent in a single push call. (optional, default: 1000)
|
|
3548
|
+
# @param scopes [Array] the scopes to keep from the index. (optional, default: settings, rules, synonyms)
|
|
3549
|
+
# @param request_options [Hash] the request options to send along with the query. (optional)
|
|
3550
|
+
#
|
|
3551
|
+
# @return [Search::ReplaceAllObjectsWithTransformationResponse]
|
|
3552
|
+
def replace_all_objects_with_transformation(
|
|
3553
|
+
index_name,
|
|
3554
|
+
objects,
|
|
3555
|
+
batch_size = 1000,
|
|
3556
|
+
scopes = [Search::ScopeType::SETTINGS, Search::ScopeType::RULES, Search::ScopeType::SYNONYMS],
|
|
3557
|
+
request_options = {},
|
|
3558
|
+
chunked_options = nil
|
|
3559
|
+
)
|
|
3560
|
+
assert_ingestion_transporter!
|
|
3561
|
+
|
|
3562
|
+
opts = Algolia::ChunkedHelperOptions.resolve(chunked_options)
|
|
3563
|
+
tmp_index_name = index_name + "_tmp_" + rand(10_000_000).to_s
|
|
3564
|
+
|
|
3565
|
+
begin
|
|
3566
|
+
copy_operation_response = operation_index(
|
|
3567
|
+
index_name,
|
|
3568
|
+
Search::OperationIndexParams.new(
|
|
3569
|
+
operation: Search::OperationType::COPY,
|
|
3570
|
+
destination: tmp_index_name,
|
|
3571
|
+
scope: scopes
|
|
3572
|
+
),
|
|
3573
|
+
request_options
|
|
3574
|
+
)
|
|
3575
|
+
|
|
3576
|
+
watch_responses = @ingestion_transporter.chunked_push(
|
|
3577
|
+
tmp_index_name,
|
|
3578
|
+
objects,
|
|
3579
|
+
Ingestion::Action::ADD_OBJECT,
|
|
3580
|
+
true,
|
|
3581
|
+
batch_size,
|
|
3582
|
+
index_name,
|
|
3583
|
+
request_options,
|
|
3584
|
+
opts
|
|
3585
|
+
)
|
|
3586
|
+
|
|
3587
|
+
wait_for_task(tmp_index_name, copy_operation_response.task_id, opts.max_retries)
|
|
3588
|
+
|
|
3589
|
+
copy_operation_response = operation_index(
|
|
3590
|
+
index_name,
|
|
3591
|
+
Search::OperationIndexParams.new(
|
|
3592
|
+
operation: Search::OperationType::COPY,
|
|
3593
|
+
destination: tmp_index_name,
|
|
3594
|
+
scope: scopes
|
|
3595
|
+
),
|
|
3596
|
+
request_options
|
|
3597
|
+
)
|
|
3598
|
+
|
|
3599
|
+
wait_for_task(tmp_index_name, copy_operation_response.task_id, opts.max_retries)
|
|
3600
|
+
|
|
3601
|
+
move_operation_response = operation_index(
|
|
3602
|
+
tmp_index_name,
|
|
3603
|
+
Search::OperationIndexParams.new(
|
|
3604
|
+
operation: Search::OperationType::MOVE,
|
|
3605
|
+
destination: index_name
|
|
3606
|
+
),
|
|
3607
|
+
request_options
|
|
3608
|
+
)
|
|
3609
|
+
|
|
3610
|
+
wait_for_task(tmp_index_name, move_operation_response.task_id, opts.max_retries)
|
|
3611
|
+
|
|
3612
|
+
search_watch_responses = watch_responses.map do |wr|
|
|
3613
|
+
Search::WatchResponse.build_from_hash(wr.to_hash)
|
|
3614
|
+
end
|
|
3615
|
+
|
|
3616
|
+
Search::ReplaceAllObjectsWithTransformationResponse.new(
|
|
3617
|
+
copy_operation_response: copy_operation_response,
|
|
3618
|
+
watch_responses: search_watch_responses,
|
|
3619
|
+
move_operation_response: move_operation_response
|
|
3620
|
+
)
|
|
3621
|
+
rescue Exception => e
|
|
3622
|
+
delete_index(tmp_index_name)
|
|
3623
|
+
|
|
3624
|
+
raise e
|
|
3625
|
+
end
|
|
3626
|
+
end
|
|
3627
|
+
|
|
3343
3628
|
# Helper: Wait for a task to be published (completed) for a given `index_name` and `task_id`.
|
|
3344
3629
|
#
|
|
3345
3630
|
# @param index_name [String] the `index_name` where the operation was performed. (required)
|
|
3346
3631
|
# @param task_id [Integer] the `task_id` returned in the method response. (required)
|
|
3347
|
-
# @param max_retries [Integer] the maximum number of retries. (optional, default to
|
|
3632
|
+
# @param max_retries [Integer] the maximum number of retries. (optional, default to Algolia::ChunkedHelperOptions::DEFAULT_MAX_RETRIES)
|
|
3348
3633
|
# @param timeout [Proc] the function to decide how long to wait between retries. (optional)
|
|
3349
3634
|
# @param request_options [Hash] the requestOptions to send along with the query, they will be forwarded to the `get_task` method.
|
|
3350
3635
|
# @return [Http::Response] the last get_task response
|
|
3351
3636
|
def wait_for_task(
|
|
3352
3637
|
index_name,
|
|
3353
3638
|
task_id,
|
|
3354
|
-
max_retries =
|
|
3639
|
+
max_retries = Algolia::ChunkedHelperOptions::DEFAULT_MAX_RETRIES,
|
|
3355
3640
|
timeout = -> (retry_count) { [retry_count * 200, 5000].min },
|
|
3356
3641
|
request_options = {}
|
|
3357
3642
|
)
|
|
@@ -3366,19 +3651,22 @@ module Algolia
|
|
|
3366
3651
|
sleep(timeout.call(retries) / 1000.0)
|
|
3367
3652
|
end
|
|
3368
3653
|
|
|
3369
|
-
raise
|
|
3654
|
+
raise(
|
|
3655
|
+
ApiError,
|
|
3656
|
+
"Stopped waiting for the task after #{max_retries} retries. This does not mean the operation failed; it may still complete. If you need to keep polling, retry with a higher max_retries."
|
|
3657
|
+
)
|
|
3370
3658
|
end
|
|
3371
3659
|
|
|
3372
3660
|
# Helper: Wait for an application-level task to be published (completed) for a given `task_id`.
|
|
3373
3661
|
#
|
|
3374
3662
|
# @param task_id [Integer] the `task_id` returned in the method response. (required)
|
|
3375
|
-
# @param max_retries [Integer] the maximum number of retries. (optional, default to
|
|
3663
|
+
# @param max_retries [Integer] the maximum number of retries. (optional, default to Algolia::ChunkedHelperOptions::DEFAULT_MAX_RETRIES)
|
|
3376
3664
|
# @param timeout [Proc] the function to decide how long to wait between retries. (optional)
|
|
3377
3665
|
# @param request_options [Hash] the requestOptions to send along with the query, they will be forwarded to the `get_task` method.
|
|
3378
3666
|
# @return [Http::Response] the last get_task response
|
|
3379
3667
|
def wait_for_app_task(
|
|
3380
3668
|
task_id,
|
|
3381
|
-
max_retries =
|
|
3669
|
+
max_retries = Algolia::ChunkedHelperOptions::DEFAULT_MAX_RETRIES,
|
|
3382
3670
|
timeout = -> (retry_count) { [retry_count * 200, 5000].min },
|
|
3383
3671
|
request_options = {}
|
|
3384
3672
|
)
|
|
@@ -3393,7 +3681,10 @@ module Algolia
|
|
|
3393
3681
|
sleep(timeout.call(retries) / 1000.0)
|
|
3394
3682
|
end
|
|
3395
3683
|
|
|
3396
|
-
raise
|
|
3684
|
+
raise(
|
|
3685
|
+
ApiError,
|
|
3686
|
+
"Stopped waiting for the task after #{max_retries} retries. This does not mean the operation failed; it may still complete. If you need to keep polling, retry with a higher max_retries."
|
|
3687
|
+
)
|
|
3397
3688
|
end
|
|
3398
3689
|
|
|
3399
3690
|
# Helper: Wait for an API key to be added, updated or deleted based on a given `operation`.
|
|
@@ -3409,7 +3700,7 @@ module Algolia
|
|
|
3409
3700
|
key,
|
|
3410
3701
|
operation,
|
|
3411
3702
|
api_key = Search::ApiKey.new,
|
|
3412
|
-
max_retries =
|
|
3703
|
+
max_retries = Algolia::ChunkedHelperOptions::DEFAULT_MAX_RETRIES,
|
|
3413
3704
|
timeout = -> (retry_count) { [retry_count * 200, 5000].min },
|
|
3414
3705
|
request_options = {}
|
|
3415
3706
|
)
|
|
@@ -3432,7 +3723,10 @@ module Algolia
|
|
|
3432
3723
|
sleep(timeout.call(retries) / 1000.0)
|
|
3433
3724
|
end
|
|
3434
3725
|
|
|
3435
|
-
raise
|
|
3726
|
+
raise(
|
|
3727
|
+
ApiError,
|
|
3728
|
+
"Stopped waiting for the task after #{max_retries} retries. This does not mean the operation failed; it may still complete. If you need to keep polling, retry with a higher max_retries."
|
|
3729
|
+
)
|
|
3436
3730
|
end
|
|
3437
3731
|
|
|
3438
3732
|
while retries < max_retries
|
|
@@ -3451,7 +3745,10 @@ module Algolia
|
|
|
3451
3745
|
sleep(timeout.call(retries) / 1000.0)
|
|
3452
3746
|
end
|
|
3453
3747
|
|
|
3454
|
-
raise
|
|
3748
|
+
raise(
|
|
3749
|
+
ApiError,
|
|
3750
|
+
"Stopped waiting for the task after #{max_retries} retries. This does not mean the operation failed; it may still complete. If you need to keep polling, retry with a higher max_retries."
|
|
3751
|
+
)
|
|
3455
3752
|
end
|
|
3456
3753
|
|
|
3457
3754
|
# Helper: Iterate on the `browse` method of the client to allow aggregating objects of an index.
|
|
@@ -3629,14 +3926,22 @@ module Algolia
|
|
|
3629
3926
|
#
|
|
3630
3927
|
# @return [BatchResponse]
|
|
3631
3928
|
#
|
|
3632
|
-
def save_objects(
|
|
3929
|
+
def save_objects(
|
|
3930
|
+
index_name,
|
|
3931
|
+
objects,
|
|
3932
|
+
wait_for_tasks = false,
|
|
3933
|
+
batch_size = 1000,
|
|
3934
|
+
request_options = {},
|
|
3935
|
+
chunked_options = nil
|
|
3936
|
+
)
|
|
3633
3937
|
chunked_batch(
|
|
3634
3938
|
index_name,
|
|
3635
3939
|
objects,
|
|
3636
3940
|
Search::Action::ADD_OBJECT,
|
|
3637
3941
|
wait_for_tasks,
|
|
3638
3942
|
batch_size,
|
|
3639
|
-
request_options
|
|
3943
|
+
request_options,
|
|
3944
|
+
chunked_options
|
|
3640
3945
|
)
|
|
3641
3946
|
end
|
|
3642
3947
|
|
|
@@ -3650,14 +3955,22 @@ module Algolia
|
|
|
3650
3955
|
#
|
|
3651
3956
|
# @return [BatchResponse]
|
|
3652
3957
|
#
|
|
3653
|
-
def delete_objects(
|
|
3958
|
+
def delete_objects(
|
|
3959
|
+
index_name,
|
|
3960
|
+
object_ids,
|
|
3961
|
+
wait_for_tasks = false,
|
|
3962
|
+
batch_size = 1000,
|
|
3963
|
+
request_options = {},
|
|
3964
|
+
chunked_options = nil
|
|
3965
|
+
)
|
|
3654
3966
|
chunked_batch(
|
|
3655
3967
|
index_name,
|
|
3656
3968
|
object_ids.map { |id| {"objectID" => id} },
|
|
3657
3969
|
Search::Action::DELETE_OBJECT,
|
|
3658
3970
|
wait_for_tasks,
|
|
3659
3971
|
batch_size,
|
|
3660
|
-
request_options
|
|
3972
|
+
request_options,
|
|
3973
|
+
chunked_options
|
|
3661
3974
|
)
|
|
3662
3975
|
end
|
|
3663
3976
|
|
|
@@ -3678,7 +3991,8 @@ module Algolia
|
|
|
3678
3991
|
create_if_not_exists,
|
|
3679
3992
|
wait_for_tasks = false,
|
|
3680
3993
|
batch_size = 1000,
|
|
3681
|
-
request_options = {}
|
|
3994
|
+
request_options = {},
|
|
3995
|
+
chunked_options = nil
|
|
3682
3996
|
)
|
|
3683
3997
|
chunked_batch(
|
|
3684
3998
|
index_name,
|
|
@@ -3686,7 +4000,8 @@ module Algolia
|
|
|
3686
4000
|
create_if_not_exists ? Search::Action::PARTIAL_UPDATE_OBJECT : Search::Action::PARTIAL_UPDATE_OBJECT_NO_CREATE,
|
|
3687
4001
|
wait_for_tasks,
|
|
3688
4002
|
batch_size,
|
|
3689
|
-
request_options
|
|
4003
|
+
request_options,
|
|
4004
|
+
chunked_options
|
|
3690
4005
|
)
|
|
3691
4006
|
end
|
|
3692
4007
|
|
|
@@ -3707,8 +4022,10 @@ module Algolia
|
|
|
3707
4022
|
action = Action::ADD_OBJECT,
|
|
3708
4023
|
wait_for_tasks = false,
|
|
3709
4024
|
batch_size = 1000,
|
|
3710
|
-
request_options = {}
|
|
4025
|
+
request_options = {},
|
|
4026
|
+
chunked_options = nil
|
|
3711
4027
|
)
|
|
4028
|
+
opts = Algolia::ChunkedHelperOptions.resolve(chunked_options)
|
|
3712
4029
|
responses = []
|
|
3713
4030
|
objects.each_slice(batch_size) do |chunk|
|
|
3714
4031
|
requests = chunk.map do |object|
|
|
@@ -3720,7 +4037,7 @@ module Algolia
|
|
|
3720
4037
|
|
|
3721
4038
|
if wait_for_tasks
|
|
3722
4039
|
responses.each do |response|
|
|
3723
|
-
wait_for_task(index_name, response.task_id)
|
|
4040
|
+
wait_for_task(index_name, response.task_id, opts.max_retries)
|
|
3724
4041
|
end
|
|
3725
4042
|
end
|
|
3726
4043
|
|
|
@@ -3741,8 +4058,10 @@ module Algolia
|
|
|
3741
4058
|
objects,
|
|
3742
4059
|
batch_size = 1000,
|
|
3743
4060
|
scopes = [Search::ScopeType::SETTINGS, Search::ScopeType::RULES, Search::ScopeType::SYNONYMS],
|
|
3744
|
-
request_options = {}
|
|
4061
|
+
request_options = {},
|
|
4062
|
+
chunked_options = nil
|
|
3745
4063
|
)
|
|
4064
|
+
opts = Algolia::ChunkedHelperOptions.resolve(chunked_options)
|
|
3746
4065
|
tmp_index_name = index_name + "_tmp_" + rand(10_000_000).to_s
|
|
3747
4066
|
|
|
3748
4067
|
begin
|
|
@@ -3762,10 +4081,11 @@ module Algolia
|
|
|
3762
4081
|
Search::Action::ADD_OBJECT,
|
|
3763
4082
|
true,
|
|
3764
4083
|
batch_size,
|
|
3765
|
-
request_options
|
|
4084
|
+
request_options,
|
|
4085
|
+
opts
|
|
3766
4086
|
)
|
|
3767
4087
|
|
|
3768
|
-
wait_for_task(tmp_index_name, copy_operation_response.task_id)
|
|
4088
|
+
wait_for_task(tmp_index_name, copy_operation_response.task_id, opts.max_retries)
|
|
3769
4089
|
|
|
3770
4090
|
copy_operation_response = operation_index(
|
|
3771
4091
|
index_name,
|
|
@@ -3777,7 +4097,7 @@ module Algolia
|
|
|
3777
4097
|
request_options
|
|
3778
4098
|
)
|
|
3779
4099
|
|
|
3780
|
-
wait_for_task(tmp_index_name, copy_operation_response.task_id)
|
|
4100
|
+
wait_for_task(tmp_index_name, copy_operation_response.task_id, opts.max_retries)
|
|
3781
4101
|
|
|
3782
4102
|
move_operation_response = operation_index(
|
|
3783
4103
|
tmp_index_name,
|
|
@@ -3788,7 +4108,7 @@ module Algolia
|
|
|
3788
4108
|
request_options
|
|
3789
4109
|
)
|
|
3790
4110
|
|
|
3791
|
-
wait_for_task(tmp_index_name, move_operation_response.task_id)
|
|
4111
|
+
wait_for_task(tmp_index_name, move_operation_response.task_id, opts.max_retries)
|
|
3792
4112
|
|
|
3793
4113
|
Search::ReplaceAllObjectsResponse.new(
|
|
3794
4114
|
copy_operation_response: copy_operation_response,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Algolia
|
|
2
|
+
# Optional configuration for chunked helpers that batch records and poll for task completion.
|
|
3
|
+
class ChunkedHelperOptions
|
|
4
|
+
DEFAULT_MAX_RETRIES = 100
|
|
5
|
+
attr_reader :max_retries
|
|
6
|
+
|
|
7
|
+
def initialize(max_retries: DEFAULT_MAX_RETRIES)
|
|
8
|
+
@max_retries = max_retries
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.resolve(options)
|
|
12
|
+
options || new
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|