jay_api 29.4.0 → 29.6.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/CHANGELOG.md +40 -0
- data/lib/jay_api/elasticsearch/client.rb +11 -28
- data/lib/jay_api/elasticsearch/errors/writable_index_error.rb +13 -0
- data/lib/jay_api/elasticsearch/errors.rb +1 -0
- data/lib/jay_api/elasticsearch/index.rb +32 -0
- data/lib/jay_api/elasticsearch/indexable.rb +16 -4
- data/lib/jay_api/elasticsearch/indices/settings/blocks.rb +59 -0
- data/lib/jay_api/elasticsearch/indices/settings.rb +51 -0
- data/lib/jay_api/elasticsearch/indices.rb +10 -0
- data/lib/jay_api/elasticsearch/mixins/retriable_requests.rb +79 -0
- data/lib/jay_api/elasticsearch/mixins.rb +10 -0
- data/lib/jay_api/elasticsearch/stats/index/totals.rb +57 -0
- data/lib/jay_api/elasticsearch/stats/index.rb +13 -0
- data/lib/jay_api/elasticsearch/stats/indices.rb +1 -1
- data/lib/jay_api/elasticsearch/tasks.rb +42 -2
- data/lib/jay_api/elasticsearch.rb +2 -0
- data/lib/jay_api/rspec/test_data_collector.rb +9 -1
- data/lib/jay_api/version.rb +1 -1
- metadata +10 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a1cec24f42607c2e94f600045f41f8c5db2593ebd478f391f9c97786d139b819
|
|
4
|
+
data.tar.gz: f35ecb6ce96aa5215d3a97229e4ee497697b57daa2ffa36b607d5d4d88a7bb3d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: afe9866d1912c2323ed2ff5e4c19d72928a1403a406cfbbca11e479a8c61dd4e877c68f0ad5ed9f9b25e002f84f510852161316d1c7fc669c9935c5262742e55
|
|
7
|
+
data.tar.gz: 9487900e069641c26048da4f4979f3d07ea6873f258e8e8025d0033bf441d4a6c98ee1941060273a6f621e1709fda60c73cd7745c63dba7f0dc0531406e4fa98
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,46 @@ Please mark backwards incompatible changes with an exclamation mark at the start
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [29.6.0] - 2026-03-16
|
|
12
|
+
|
|
13
|
+
### Deprecated
|
|
14
|
+
- The `#task_by_id` method of the `Elasticsearch::Client` class.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- The `#all` method to `JayAPI::Elasticsearch::Tasks`. The method returns the
|
|
18
|
+
status of all running tasks on the Elasticsearch cluster.
|
|
19
|
+
- The `#tasks` method to `JayAPI::Elasticsearch::Client`. The method returns an
|
|
20
|
+
instance of `JayAPI::Elasticsearch::Tasks`, which gives the user access to the
|
|
21
|
+
status of the tasks running on the Elasticsearch cluster.
|
|
22
|
+
|
|
23
|
+
## [29.5.0] - 2026-02-23
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- A `NameError` that was being raised when `jay_api/elasticsearch/client` was
|
|
27
|
+
required without requiring `elasticsearch`.
|
|
28
|
+
- A `NoMethodError` that was being raised by `Elasticsearch::Stats::Indices`
|
|
29
|
+
when `active_support/core_ext/string` hadn't been loaded.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- The `#force_merge` method to the `Elasticsearch::Index` class. This method
|
|
33
|
+
starts a Forced Segment Merge on the index.
|
|
34
|
+
- The `#totals` method to `Elasticsearch::Stats::Index`, this gives the caller
|
|
35
|
+
access to the index's total metrics.
|
|
36
|
+
- The `Elasticsearch::Stats::Index::Totals` class. The class contains information
|
|
37
|
+
about an index's total metrics, for example, total number of documents, total
|
|
38
|
+
size, etc.
|
|
39
|
+
- The `#settings` method to the `Elasticsearch::Index` class. This gives the
|
|
40
|
+
caller access to the index's settings.
|
|
41
|
+
- The `Elasticsearch::Indices::Settings::Blocks` class. The class encapsulates
|
|
42
|
+
an index's blocks settings (for example, whether the index is read-only).
|
|
43
|
+
- The `Elasticsearch::Indices::Settings` class. The class encapsulates an
|
|
44
|
+
index's settings.
|
|
45
|
+
- It is now possible to configure the type used by the `RSpec::TestDataCollector`
|
|
46
|
+
class when pushing documents to Elasticsearch. If no type is specified in the
|
|
47
|
+
configuration the default type will be used.
|
|
48
|
+
- Allow the `Elasticsearch::Index` and `Elasticsearch::Indexes`'s `#push` method
|
|
49
|
+
to receive a `type` parameter, just like `#index` does.
|
|
50
|
+
|
|
11
51
|
## [29.4.0] - 2026-01-28
|
|
12
52
|
|
|
13
53
|
### Added
|
|
@@ -1,39 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require '
|
|
4
|
-
require 'elasticsearch/transport/transport/errors'
|
|
3
|
+
require 'timeout'
|
|
5
4
|
require 'faraday/error'
|
|
6
5
|
require 'forwardable'
|
|
7
6
|
|
|
8
|
-
require_relative '
|
|
7
|
+
require_relative 'mixins/retriable_requests'
|
|
9
8
|
require_relative 'stats'
|
|
9
|
+
require_relative 'tasks'
|
|
10
10
|
|
|
11
11
|
module JayAPI
|
|
12
12
|
module Elasticsearch
|
|
13
|
-
# The JayAPI wrapper class over the
|
|
13
|
+
# The JayAPI wrapper class over the +Elasticsearch::Client+ object. It mirrors
|
|
14
14
|
# the object's API, but if one of the ERRORS is raised, this Wrapper class will
|
|
15
15
|
# rescue the error up to a few times and re-try the connection. This way the
|
|
16
16
|
# connection to Elasticsearch will be more robust.
|
|
17
17
|
class Client
|
|
18
18
|
extend Forwardable
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
ERRORS = [
|
|
22
|
-
::Elasticsearch::Transport::Transport::ServerError,
|
|
23
|
-
Faraday::TimeoutError
|
|
24
|
-
].freeze
|
|
25
|
-
|
|
26
|
-
# Subclasses of the +Elasticsearch::Transport::Transport::ServerError+
|
|
27
|
-
# for which a retry doesn't make sense.
|
|
28
|
-
NON_RETRIABLE_ERRORS = [
|
|
29
|
-
::Elasticsearch::Transport::Transport::Errors::BadRequest,
|
|
30
|
-
::Elasticsearch::Transport::Transport::Errors::Unauthorized,
|
|
31
|
-
::Elasticsearch::Transport::Transport::Errors::Forbidden,
|
|
32
|
-
::Elasticsearch::Transport::Transport::Errors::NotFound,
|
|
33
|
-
::Elasticsearch::Transport::Transport::Errors::MethodNotAllowed,
|
|
34
|
-
::Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge,
|
|
35
|
-
::Elasticsearch::Transport::Transport::Errors::NotImplemented
|
|
36
|
-
].freeze
|
|
20
|
+
include JayAPI::Elasticsearch::Mixins::RetriableRequests
|
|
37
21
|
|
|
38
22
|
attr_reader :transport_client, :logger, :max_attempts, :wait_strategy
|
|
39
23
|
|
|
@@ -88,6 +72,7 @@ module JayAPI
|
|
|
88
72
|
# parameters. If the request fails, additional retries will be performed.
|
|
89
73
|
# @see Elasticsearch::Client#tasks for more info about the arguments and
|
|
90
74
|
# the return value.
|
|
75
|
+
# @deprecated Use Tasks#by_id instead.
|
|
91
76
|
def task_by_id(**args)
|
|
92
77
|
retry_request { transport_client.tasks.get(**args) }
|
|
93
78
|
end
|
|
@@ -98,13 +83,11 @@ module JayAPI
|
|
|
98
83
|
@stats ||= ::JayAPI::Elasticsearch::Stats.new(transport_client)
|
|
99
84
|
end
|
|
100
85
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Abstract::Connection.new(max_attempts: max_attempts, wait_strategy: wait_strategy.dup, logger: logger)
|
|
107
|
-
.retry(errors: ERRORS, except: NON_RETRIABLE_ERRORS, &block)
|
|
86
|
+
# @return [JayAPI::Elasticsearch::Tasks] An instance of the +Tasks+ class,
|
|
87
|
+
# which can be used to retrieve the status of the tasks running on the
|
|
88
|
+
# Elasticsearch cluster.
|
|
89
|
+
def tasks
|
|
90
|
+
@tasks ||= ::JayAPI::Elasticsearch::Tasks.new(client: self)
|
|
108
91
|
end
|
|
109
92
|
end
|
|
110
93
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../errors/error'
|
|
4
|
+
|
|
5
|
+
module JayAPI
|
|
6
|
+
module Elasticsearch
|
|
7
|
+
module Errors
|
|
8
|
+
# An error to be raised when an attempt is made to perform force_merge
|
|
9
|
+
# over an index which hasn't been set to be read-only.
|
|
10
|
+
class WritableIndexError < ::JayAPI::Errors::Error; end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -6,6 +6,7 @@ require_relative 'errors/query_execution_error'
|
|
|
6
6
|
require_relative 'errors/query_execution_failure'
|
|
7
7
|
require_relative 'errors/query_execution_timeout'
|
|
8
8
|
require_relative 'errors/search_after_error'
|
|
9
|
+
require_relative 'errors/writable_index_error'
|
|
9
10
|
|
|
10
11
|
module JayAPI
|
|
11
12
|
module Elasticsearch
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'indexable'
|
|
4
|
+
require_relative 'indices/settings'
|
|
5
|
+
require_relative 'errors/writable_index_error'
|
|
4
6
|
|
|
5
7
|
module JayAPI
|
|
6
8
|
module Elasticsearch
|
|
@@ -49,6 +51,36 @@ module JayAPI
|
|
|
49
51
|
def index(data, type: DEFAULT_DOC_TYPE)
|
|
50
52
|
super.first
|
|
51
53
|
end
|
|
54
|
+
|
|
55
|
+
# @return [JayAPI::Elasticsearch::Indices::Settings] The settings for the
|
|
56
|
+
# index.
|
|
57
|
+
def settings
|
|
58
|
+
# DO NOT MEMOIZE! Leave it to the caller.
|
|
59
|
+
::JayAPI::Elasticsearch::Indices::Settings.new(client.transport_client, index_name)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Starts a Forced Segment Merge process on the index.
|
|
63
|
+
#
|
|
64
|
+
# ⚠️ For big indexes this process can take a very long time, make sure to
|
|
65
|
+
# adjust the timeout when creating the client.
|
|
66
|
+
# @param [Boolean] only_expunge_deletes Specifies whether the operation
|
|
67
|
+
# should only remove deleted documents.
|
|
68
|
+
# @raise [JayAPI::Elasticsearch::Errors::WritableIndexError] If the index
|
|
69
|
+
# is writable (hasn't been set to read-only).
|
|
70
|
+
# @return [Hash] A +Hash+ with the result of the index merging process,
|
|
71
|
+
# it looks like this:
|
|
72
|
+
#
|
|
73
|
+
# { "_shards" => { "total" => 10, "successful" => 10, "failed" => 0 } }
|
|
74
|
+
def force_merge(only_expunge_deletes: nil)
|
|
75
|
+
unless settings.blocks.write_blocked?
|
|
76
|
+
raise ::JayAPI::Elasticsearch::Errors::WritableIndexError,
|
|
77
|
+
"Write block for '#{index_name}' has not been enabled. " \
|
|
78
|
+
"Please enable the index's write block before performing a segment merge"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
params = { index: index_name, only_expunge_deletes: }.compact
|
|
82
|
+
client.transport_client.indices.forcemerge(**params)
|
|
83
|
+
end
|
|
52
84
|
end
|
|
53
85
|
end
|
|
54
86
|
end
|
|
@@ -48,9 +48,13 @@ module JayAPI
|
|
|
48
48
|
# Pushes a record into the index. (This does not send the record to the
|
|
49
49
|
# Elasticsearch instance, only puts it into the send queue).
|
|
50
50
|
# @param [Hash] data The data to be pushed to the index.
|
|
51
|
-
|
|
51
|
+
# @param [String, nil] type The type of the document. When set to +nil+
|
|
52
|
+
# the decision is left to Elasticsearch's API. Which will normally
|
|
53
|
+
# default to +_doc+.
|
|
54
|
+
def push(data, type: DEFAULT_DOC_TYPE)
|
|
55
|
+
validate_type(type)
|
|
52
56
|
index_names.each do |index_name|
|
|
53
|
-
batch << { index: { _index: index_name, _type:
|
|
57
|
+
batch << { index: { _index: index_name, _type: type, data: data }.compact }
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
flush! if batch.size >= batch_size
|
|
@@ -78,8 +82,7 @@ module JayAPI
|
|
|
78
82
|
# For information on the contents of this Hash please see:
|
|
79
83
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#docs-index-api-response-body
|
|
80
84
|
def index(data, type: DEFAULT_DOC_TYPE)
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
validate_type(type)
|
|
83
86
|
index_names.map { |index_name| client.index index: index_name, type: type, body: data }
|
|
84
87
|
end
|
|
85
88
|
|
|
@@ -220,6 +223,15 @@ module JayAPI
|
|
|
220
223
|
def async
|
|
221
224
|
@async ||= JayAPI::Elasticsearch::Async.new(self)
|
|
222
225
|
end
|
|
226
|
+
|
|
227
|
+
# @param [String, nil] type The type of the document. When set to +nil+
|
|
228
|
+
# the decision is left to Elasticsearch's API. Which will normally
|
|
229
|
+
# default to +_doc+.
|
|
230
|
+
# @raise [ArgumentError] When the given +type+ is not one of the
|
|
231
|
+
# +SUPPORTED_TYPES+
|
|
232
|
+
def validate_type(type)
|
|
233
|
+
raise ArgumentError, "Unsupported type: '#{type}'" unless SUPPORTED_TYPES.include?(type)
|
|
234
|
+
end
|
|
223
235
|
end
|
|
224
236
|
end
|
|
225
237
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JayAPI
|
|
4
|
+
module Elasticsearch
|
|
5
|
+
module Indices
|
|
6
|
+
class Settings
|
|
7
|
+
# Represents the block settings of an Elasticsearch index.
|
|
8
|
+
class Blocks
|
|
9
|
+
attr_reader :settings
|
|
10
|
+
|
|
11
|
+
# @param [JayAPI::Elasticsearch::Indices::Settings] settings The
|
|
12
|
+
# parent +Settings+ object.
|
|
13
|
+
def initialize(settings)
|
|
14
|
+
@settings = settings
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @return [Boolean] True if the Index's write block has been set to
|
|
18
|
+
# true, false otherwise.
|
|
19
|
+
def write_blocked?
|
|
20
|
+
blocks_settings.fetch('write') == 'true'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Sets the index's +write+ block to the given value. When the +write+
|
|
24
|
+
# block is set to +true+ the index's data is read-only, but the
|
|
25
|
+
# index's settings can still be changed. This allows maintenance tasks
|
|
26
|
+
# to still be performed on the index.
|
|
27
|
+
# @param [Boolean] value The new value for the +write+ block of the
|
|
28
|
+
# index.
|
|
29
|
+
# @raise [Elasticsearch::Transport::Transport::Errors::ServerError] If
|
|
30
|
+
# an error occurs when trying to set the value of the block.
|
|
31
|
+
def write=(value)
|
|
32
|
+
unless [true, false].include?(value)
|
|
33
|
+
raise ArgumentError, "Expected 'value' to be true or false, #{value.class} given"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
return if write_blocked? == value
|
|
37
|
+
|
|
38
|
+
settings.transport_client.indices.put_settings(
|
|
39
|
+
index: settings.index_name,
|
|
40
|
+
body: { 'blocks.write' => value }
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
# @return [Hash] The block settings of the index. Something like this:
|
|
47
|
+
#
|
|
48
|
+
# { 'read_only_allow_delete' => 'false', 'write' => 'false' }
|
|
49
|
+
#
|
|
50
|
+
# @raise [KeyError] If the index's settings do not contain a "blocks"
|
|
51
|
+
# section.
|
|
52
|
+
def blocks_settings
|
|
53
|
+
settings.all.fetch('blocks')
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'settings/blocks'
|
|
4
|
+
|
|
5
|
+
module JayAPI
|
|
6
|
+
module Elasticsearch
|
|
7
|
+
module Indices
|
|
8
|
+
# Represents the settings of an Elasticsearch Index.
|
|
9
|
+
class Settings
|
|
10
|
+
attr_reader :transport_client, :index_name
|
|
11
|
+
|
|
12
|
+
# @param [Elasticsearch::Transport::Client] transport_client Elasticsearch's
|
|
13
|
+
# transport client.
|
|
14
|
+
# @param [String] index_name The name of the index this class will be
|
|
15
|
+
# handling settings for.
|
|
16
|
+
def initialize(transport_client, index_name)
|
|
17
|
+
@transport_client = transport_client
|
|
18
|
+
@index_name = index_name
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Hash] A Hash with all the settings for the index. It looks
|
|
22
|
+
# like this:
|
|
23
|
+
#
|
|
24
|
+
# {
|
|
25
|
+
# "number_of_shards" => "5",
|
|
26
|
+
# "blocks" => { "read_only_allow_delete" => "false", "write" => "false" },
|
|
27
|
+
# "provided_name" => "xyz01_tests",
|
|
28
|
+
# "creation_date" => "1588701800423",
|
|
29
|
+
# "number_of_replicas" => "1",
|
|
30
|
+
# "uuid" => "VFx2e5t0Qgi-1zc2PUkYEg",
|
|
31
|
+
# "version" => { "created" => "7010199", "upgraded" => "7100299"}
|
|
32
|
+
# }
|
|
33
|
+
#
|
|
34
|
+
# @raise [Elasticsearch::Transport::Transport::Errors::ServerError] If
|
|
35
|
+
# an error occurs when trying to get the index's settings.
|
|
36
|
+
# @raise [KeyError] If any of the expected hierarchical elements in the
|
|
37
|
+
# response are missing.
|
|
38
|
+
def all
|
|
39
|
+
transport_client.indices.get_settings(index: index_name)
|
|
40
|
+
.fetch(index_name).fetch('settings').fetch('index')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [JayAPI::Elasticsearch::Indices::Settings::Blocks] The blocks
|
|
44
|
+
# settings for the given index.
|
|
45
|
+
def blocks
|
|
46
|
+
@blocks ||= ::JayAPI::Elasticsearch::Indices::Settings::Blocks.new(self)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'elasticsearch/transport/transport/errors'
|
|
4
|
+
|
|
5
|
+
require_relative '../../abstract/connection'
|
|
6
|
+
|
|
7
|
+
module JayAPI
|
|
8
|
+
module Elasticsearch
|
|
9
|
+
module Mixins
|
|
10
|
+
# A mixin that allows the including class to retry requests to
|
|
11
|
+
# Elasticsearch by leveraging the +Abstract::Connection+ class'
|
|
12
|
+
# capabilities.
|
|
13
|
+
module RetriableRequests
|
|
14
|
+
# The errors that, if raised, must cause a retry of the connection.
|
|
15
|
+
RETRIABLE_ERRORS = [
|
|
16
|
+
::Elasticsearch::Transport::Transport::ServerError,
|
|
17
|
+
Faraday::TimeoutError
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
20
|
+
# Subclasses of the +Elasticsearch::Transport::Transport::ServerError+
|
|
21
|
+
# for which a retry doesn't make sense.
|
|
22
|
+
NON_RETRIABLE_ERRORS = [
|
|
23
|
+
::Elasticsearch::Transport::Transport::Errors::BadRequest,
|
|
24
|
+
::Elasticsearch::Transport::Transport::Errors::Unauthorized,
|
|
25
|
+
::Elasticsearch::Transport::Transport::Errors::Forbidden,
|
|
26
|
+
::Elasticsearch::Transport::Transport::Errors::NotFound,
|
|
27
|
+
::Elasticsearch::Transport::Transport::Errors::MethodNotAllowed,
|
|
28
|
+
::Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge,
|
|
29
|
+
::Elasticsearch::Transport::Transport::Errors::NotImplemented
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
# @return [Integer] The maximum number of times a request should be
|
|
33
|
+
# retried before giving up.
|
|
34
|
+
def max_attempts
|
|
35
|
+
raise_not_implemented(__method__)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [JayAPI::Elasticsearch::WaitStrategy] The waiting strategy for
|
|
39
|
+
# retries.
|
|
40
|
+
def wait_strategy
|
|
41
|
+
raise_not_implemented(__method__)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Logging::Logger] A logger to log messages.
|
|
45
|
+
def logger
|
|
46
|
+
raise_not_implemented(__method__)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [Array<Class>] The array of errors that, if raised, must cause
|
|
50
|
+
# a retry of the request.
|
|
51
|
+
def retriable_errors
|
|
52
|
+
RETRIABLE_ERRORS
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [Array<Class>] An array of subclasses of the
|
|
56
|
+
# +Elasticsearch::Transport::Transport::ServerError+ for which a retry
|
|
57
|
+
# doesn't make sense.
|
|
58
|
+
def non_retriable_errors
|
|
59
|
+
NON_RETRIABLE_ERRORS
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# Uses the +Abstract::Connection+ class to retry the request enclosed in
|
|
65
|
+
# the given block.
|
|
66
|
+
def retry_request(&)
|
|
67
|
+
Abstract::Connection.new(max_attempts:, wait_strategy: wait_strategy.dup, logger:)
|
|
68
|
+
.retry(errors: retriable_errors, except: non_retriable_errors, &)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @raise [NotImplementedError] Is always raised with the appropriate
|
|
72
|
+
# error message.
|
|
73
|
+
def raise_not_implemented(method)
|
|
74
|
+
raise NotImplementedError, "Please implement the method ##{method} in #{self.class}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JayAPI
|
|
4
|
+
module Elasticsearch
|
|
5
|
+
class Stats
|
|
6
|
+
class Index
|
|
7
|
+
# Contains information about an index's totals (docs, used space, etc).
|
|
8
|
+
class Totals
|
|
9
|
+
# @param [Hash] data The data under the index's +total+ key.
|
|
10
|
+
def initialize(data)
|
|
11
|
+
@data = data
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [Integer] The total number of documents in the index.
|
|
15
|
+
def docs_count
|
|
16
|
+
@docs_count ||= docs.fetch('count')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Integer] The total number of deleted documents in the index.
|
|
20
|
+
def deleted_docs
|
|
21
|
+
@deleted_docs ||= docs.fetch('deleted')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Float] A number between 0 and 1 that represents the ratio
|
|
25
|
+
# of between deleted documents and total documents in the index.
|
|
26
|
+
def deleted_ratio
|
|
27
|
+
@deleted_ratio ||= calculate_deleted_ratio
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
attr_reader :data
|
|
33
|
+
|
|
34
|
+
# @return [Hash] The information about the documents in the index.
|
|
35
|
+
# Looks something like this:
|
|
36
|
+
#
|
|
37
|
+
# { "count" => 530626, "deleted" => 11 }
|
|
38
|
+
#
|
|
39
|
+
# @raise [KeyError] If the given data doesn't have a +docs+ key.
|
|
40
|
+
def docs
|
|
41
|
+
@docs ||= data.fetch('docs')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Float] A number between 0 and 1 that represents the ratio
|
|
45
|
+
# of between deleted documents and total documents in the index.
|
|
46
|
+
def calculate_deleted_ratio
|
|
47
|
+
if docs_count.zero?
|
|
48
|
+
return deleted_docs.zero? ? 0.0 : 1.0
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
deleted_docs / docs_count.to_f
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'index/totals'
|
|
4
|
+
|
|
3
5
|
module JayAPI
|
|
4
6
|
module Elasticsearch
|
|
5
7
|
class Stats
|
|
@@ -13,6 +15,17 @@ module JayAPI
|
|
|
13
15
|
@name = name
|
|
14
16
|
@data = data
|
|
15
17
|
end
|
|
18
|
+
|
|
19
|
+
# @return [JayAPI::Elasticsearch::Stats::Index::Totals] Information
|
|
20
|
+
# about the index's total metrics.
|
|
21
|
+
# @raise [KeyError] If the given data doesn't have a +total+ key.
|
|
22
|
+
def totals
|
|
23
|
+
@totals ||= ::JayAPI::Elasticsearch::Stats::Index::Totals.new(data.fetch('total'))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
attr_reader :data
|
|
16
29
|
end
|
|
17
30
|
end
|
|
18
31
|
end
|
|
@@ -10,7 +10,7 @@ module JayAPI
|
|
|
10
10
|
class Indices
|
|
11
11
|
# A lambda used to select / reject system indices (indices whose name
|
|
12
12
|
# starts with dot).
|
|
13
|
-
SYSTEM_SELECTOR = ->(name, _data) { name.
|
|
13
|
+
SYSTEM_SELECTOR = ->(name, _data) { name.start_with?('.') }
|
|
14
14
|
|
|
15
15
|
# @param [Hash{String=>Hash}] indices A +Hash+ with the information
|
|
16
16
|
# about the indices. Its keys are the names of the indices, its values
|
|
@@ -1,22 +1,52 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'active_support'
|
|
4
|
+
require 'active_support/core_ext/enumerable'
|
|
4
5
|
require 'active_support/core_ext/hash/indifferent_access'
|
|
6
|
+
require 'forwardable'
|
|
7
|
+
|
|
8
|
+
require_relative 'mixins/retriable_requests'
|
|
5
9
|
|
|
6
10
|
module JayAPI
|
|
7
11
|
module Elasticsearch
|
|
8
12
|
# Represents Elasticsearch tasks. Returns information about the tasks
|
|
9
13
|
# currently executing in the cluster.
|
|
10
|
-
# TODO: Add #all [JAY-593]
|
|
11
14
|
class Tasks
|
|
15
|
+
extend Forwardable
|
|
16
|
+
include ::JayAPI::Elasticsearch::Mixins::RetriableRequests
|
|
17
|
+
|
|
12
18
|
attr_reader :client
|
|
13
19
|
|
|
20
|
+
def_delegators :client, :transport_client, :max_attempts, :wait_strategy, :logger
|
|
21
|
+
|
|
14
22
|
# @param [JayAPI::Elasticsearch::Client] client The Elasticsearch Client
|
|
15
23
|
# object
|
|
16
24
|
def initialize(client:)
|
|
17
25
|
@client = client
|
|
18
26
|
end
|
|
19
27
|
|
|
28
|
+
# Gets the list of tasks running on the Elasticsearch cluster.
|
|
29
|
+
# For more information about this endpoint and the parameters please see:
|
|
30
|
+
# https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-tasks-list
|
|
31
|
+
# @param [Array<String>] actions A list of actions. Only tasks matching
|
|
32
|
+
# these actions will be returned, if no task matches the result will be
|
|
33
|
+
# empty.
|
|
34
|
+
# @param [Boolean] detailed Whether or not the result should include task
|
|
35
|
+
# details or not.
|
|
36
|
+
# @return [Hash] A hash with the list of tasks running on the
|
|
37
|
+
# Elasticsearch cluster.
|
|
38
|
+
def all(actions: nil, detailed: false)
|
|
39
|
+
# Needed because unlike many Elasticsearch methods Tasks#list doesn't
|
|
40
|
+
# call #listify over +actions+.
|
|
41
|
+
actions = actions&.then do |value|
|
|
42
|
+
value.is_a?(Array) ? value.join(',') : value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
retry_request do
|
|
46
|
+
tasks_client.list({ actions:, detailed: }.compact_blank)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
20
50
|
# Retrieves info about the task with the passed +task_id+
|
|
21
51
|
# For more information on how to build the query please refer to the
|
|
22
52
|
# Elasticsearch DSL documentation:
|
|
@@ -29,7 +59,17 @@ module JayAPI
|
|
|
29
59
|
# @raise [Elasticsearch::Transport::Transport::ServerError] If the
|
|
30
60
|
# query fails.
|
|
31
61
|
def by_id(task_id)
|
|
32
|
-
|
|
62
|
+
retry_request do
|
|
63
|
+
tasks_client.get(task_id:, wait_for_completion: true).deep_symbolize_keys
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# @return [Elasticsearch::API::Tasks::TasksClient] The client used to
|
|
70
|
+
# access tasks-related information.
|
|
71
|
+
def tasks_client
|
|
72
|
+
@tasks_client ||= transport_client.tasks
|
|
33
73
|
end
|
|
34
74
|
end
|
|
35
75
|
end
|
|
@@ -7,6 +7,8 @@ require_relative 'elasticsearch/client_factory'
|
|
|
7
7
|
require_relative 'elasticsearch/errors'
|
|
8
8
|
require_relative 'elasticsearch/index'
|
|
9
9
|
require_relative 'elasticsearch/indexes'
|
|
10
|
+
require_relative 'elasticsearch/indices'
|
|
11
|
+
require_relative 'elasticsearch/mixins'
|
|
10
12
|
require_relative 'elasticsearch/query_builder'
|
|
11
13
|
require_relative 'elasticsearch/query_results'
|
|
12
14
|
require_relative 'elasticsearch/response'
|
|
@@ -79,7 +79,7 @@ module JayAPI
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
elasticsearch_index.push(data)
|
|
82
|
+
elasticsearch_index.push(data, **push_params)
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
# Executed by RSpec at the end of the test run. If the push is enabled,
|
|
@@ -94,6 +94,14 @@ module JayAPI
|
|
|
94
94
|
|
|
95
95
|
attr_reader :push_enabled
|
|
96
96
|
|
|
97
|
+
# @return [Hash] Additional parameters for the Elasticsearch::Index#push.
|
|
98
|
+
def push_params
|
|
99
|
+
# The extraction of the parameters is done with a #slice to be able to
|
|
100
|
+
# differentiate between when the parameter is not specified (completely
|
|
101
|
+
# absent) or when the parameter has been specified as +nil+.
|
|
102
|
+
@push_params ||= configuration.to_h.slice(:type)
|
|
103
|
+
end
|
|
104
|
+
|
|
97
105
|
# @return [Hash] The configuration set for Elasticsearch as a hash. If no
|
|
98
106
|
# value has been set for the batch size a reasonable default is set.
|
|
99
107
|
# @raise [JayAPI::Errors::ConfigurationError] If no configuration for
|
data/lib/jay_api/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jay_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 29.
|
|
4
|
+
version: 29.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Accenture-Industry X
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2026-
|
|
12
|
+
date: 2026-03-16 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -128,9 +128,15 @@ files:
|
|
|
128
128
|
- lib/jay_api/elasticsearch/errors/query_execution_failure.rb
|
|
129
129
|
- lib/jay_api/elasticsearch/errors/query_execution_timeout.rb
|
|
130
130
|
- lib/jay_api/elasticsearch/errors/search_after_error.rb
|
|
131
|
+
- lib/jay_api/elasticsearch/errors/writable_index_error.rb
|
|
131
132
|
- lib/jay_api/elasticsearch/index.rb
|
|
132
133
|
- lib/jay_api/elasticsearch/indexable.rb
|
|
133
134
|
- lib/jay_api/elasticsearch/indexes.rb
|
|
135
|
+
- lib/jay_api/elasticsearch/indices.rb
|
|
136
|
+
- lib/jay_api/elasticsearch/indices/settings.rb
|
|
137
|
+
- lib/jay_api/elasticsearch/indices/settings/blocks.rb
|
|
138
|
+
- lib/jay_api/elasticsearch/mixins.rb
|
|
139
|
+
- lib/jay_api/elasticsearch/mixins/retriable_requests.rb
|
|
134
140
|
- lib/jay_api/elasticsearch/query_builder.rb
|
|
135
141
|
- lib/jay_api/elasticsearch/query_builder/aggregations.rb
|
|
136
142
|
- lib/jay_api/elasticsearch/query_builder/aggregations/aggregation.rb
|
|
@@ -174,6 +180,7 @@ files:
|
|
|
174
180
|
- lib/jay_api/elasticsearch/stats.rb
|
|
175
181
|
- lib/jay_api/elasticsearch/stats/errors/stats_data_not_available.rb
|
|
176
182
|
- lib/jay_api/elasticsearch/stats/index.rb
|
|
183
|
+
- lib/jay_api/elasticsearch/stats/index/totals.rb
|
|
177
184
|
- lib/jay_api/elasticsearch/stats/indices.rb
|
|
178
185
|
- lib/jay_api/elasticsearch/stats/node.rb
|
|
179
186
|
- lib/jay_api/elasticsearch/stats/node/storage.rb
|
|
@@ -220,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
220
227
|
- !ruby/object:Gem::Version
|
|
221
228
|
version: '0'
|
|
222
229
|
requirements: []
|
|
223
|
-
rubygems_version: 3.
|
|
230
|
+
rubygems_version: 3.4.19
|
|
224
231
|
signing_key:
|
|
225
232
|
specification_version: 4
|
|
226
233
|
summary: A collection of classes and modules to access JAY's functionality
|