elasticgraph-indexer_autoscaler_lambda 0.18.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5ed020864bd849464587075ad6bd0ed677b65c55967f68a5a4db2609dfd2cc5d
4
+ data.tar.gz: 8bd8b246b28ddfb7bd78a0fd913b6d22a955f4005559ab126bc88c14399ddbc6
5
+ SHA512:
6
+ metadata.gz: 2b06675425650e6ce74bd224eaa32de5b52eef9883b286babe94143be0859af67629588af59e4c5824be0e421d7ae286cbd498163c416b8474b96ece186d8c2d
7
+ data.tar.gz: 83e1a9ce30d8e2428ed29ce3d6246b461ea17e511e98c8b75d2959f889dae2c9414fc22c9866db0d2920baeabf9dddca235696bf72166531792e64de0df13d33
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Block, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # ElasticGraph::IndexerAutoscalerLambda
@@ -0,0 +1,27 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require_relative "../gemspec_helper"
10
+
11
+ ElasticGraphGemspecHelper.define_elasticgraph_gem(gemspec_file: __FILE__, category: :lambda) do |spec, eg_version|
12
+ spec.summary = "ElasticGraph gem that monitors OpenSearch CPU utilization to autoscale indexer lambda concurrency."
13
+
14
+ spec.add_dependency "elasticgraph-datastore_core", eg_version
15
+ spec.add_dependency "elasticgraph-lambda_support", eg_version
16
+
17
+ spec.add_dependency "aws-sdk-lambda", "~> 1.125"
18
+ spec.add_dependency "aws-sdk-sqs", "~> 1.80"
19
+
20
+ # aws-sdk-sqs requires an XML library be available. On Ruby < 3 it'll use rexml from the standard library but on Ruby 3.0+
21
+ # we have to add an explicit dependency. It supports ox, oga, libxml, nokogiri or rexml, and of those, ox seems to be the
22
+ # best choice: it leads benchmarks, is well-maintained, has no dependencies, and is MIT-licensed.
23
+ spec.add_dependency "ox", "~> 2.14"
24
+
25
+ spec.add_development_dependency "elasticgraph-elasticsearch", eg_version
26
+ spec.add_development_dependency "elasticgraph-opensearch", eg_version
27
+ end
@@ -0,0 +1,140 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/indexer_autoscaler_lambda/details_logger"
10
+
11
+ module ElasticGraph
12
+ class IndexerAutoscalerLambda
13
+ class ConcurrencyScaler
14
+ def initialize(datastore_core:, sqs_client:, lambda_client:)
15
+ @logger = datastore_core.logger
16
+ @datastore_core = datastore_core
17
+ @sqs_client = sqs_client
18
+ @lambda_client = lambda_client
19
+ end
20
+
21
+ # AWS requires the value be in this range:
22
+ # https://docs.aws.amazon.com/lambda/latest/api/API_ScalingConfig.html#API_ScalingConfig_Contents
23
+ MAXIMUM_CONCURRENCY = 1000
24
+ MINIMUM_CONCURRENCY = 2
25
+
26
+ def tune_indexer_concurrency(queue_urls:, min_cpu_target:, max_cpu_target:, event_source_mapping_uuids:)
27
+ queue_attributes = get_queue_attributes(queue_urls)
28
+ queue_arns = queue_attributes.fetch(:queue_arns)
29
+ num_messages = queue_attributes.fetch(:total_messages)
30
+
31
+ details_logger = DetailsLogger.new(
32
+ logger: @logger,
33
+ queue_arns: queue_arns,
34
+ queue_urls: queue_urls,
35
+ min_cpu_target: min_cpu_target,
36
+ max_cpu_target: max_cpu_target,
37
+ num_messages: num_messages
38
+ )
39
+
40
+ new_target_concurrency =
41
+ if num_messages.positive?
42
+ cpu_utilization = get_max_cpu_utilization
43
+ cpu_midpoint = (max_cpu_target + min_cpu_target) / 2.0
44
+
45
+ current_concurrency = get_total_concurrency(event_source_mapping_uuids)
46
+
47
+ if cpu_utilization < min_cpu_target
48
+ increase_factor = (cpu_midpoint / cpu_utilization).clamp(0.0, 1.5)
49
+ (current_concurrency * increase_factor).round.tap do |new_concurrency|
50
+ details_logger.log_increase(
51
+ cpu_utilization: cpu_utilization,
52
+ current_concurrency: current_concurrency,
53
+ new_concurrency: new_concurrency
54
+ )
55
+ end
56
+ elsif cpu_utilization > max_cpu_target
57
+ decrease_factor = cpu_utilization / cpu_midpoint - 1
58
+ (current_concurrency - (current_concurrency * decrease_factor)).round.tap do |new_concurrency|
59
+ details_logger.log_decrease(
60
+ cpu_utilization: cpu_utilization,
61
+ current_concurrency: current_concurrency,
62
+ new_concurrency: new_concurrency
63
+ )
64
+ end
65
+ else
66
+ details_logger.log_no_change(
67
+ cpu_utilization: cpu_utilization,
68
+ current_concurrency: current_concurrency
69
+ )
70
+ current_concurrency
71
+ end
72
+ else
73
+ details_logger.log_reset
74
+ 0
75
+ end
76
+
77
+ if new_target_concurrency != current_concurrency
78
+ update_event_source_mapping(
79
+ event_source_mapping_uuids: event_source_mapping_uuids,
80
+ concurrency: new_target_concurrency
81
+ )
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def get_max_cpu_utilization
88
+ @datastore_core.clients_by_name.values.flat_map do |client|
89
+ client.get_node_os_stats.fetch("nodes").values.map do |node|
90
+ node.dig("os", "cpu", "percent")
91
+ end
92
+ end.max.to_f
93
+ end
94
+
95
+ def get_queue_attributes(queue_urls)
96
+ attributes_per_queue = queue_urls.map do |queue_url|
97
+ @sqs_client.get_queue_attributes(
98
+ queue_url: queue_url,
99
+ attribute_names: ["QueueArn", "ApproximateNumberOfMessages"]
100
+ ).attributes
101
+ end
102
+
103
+ total_messages = attributes_per_queue
104
+ .map { |attr| Integer(attr.fetch("ApproximateNumberOfMessages")) }
105
+ .sum
106
+
107
+ queue_arns = attributes_per_queue.map { |attr| attr.fetch("QueueArn") }
108
+
109
+ {
110
+ total_messages: total_messages,
111
+ queue_arns: queue_arns
112
+ }
113
+ end
114
+
115
+ def get_total_concurrency(event_source_mapping_uuids)
116
+ event_source_mapping_uuids.map do |event_source_mapping_uuid|
117
+ @lambda_client.get_event_source_mapping(
118
+ uuid: event_source_mapping_uuid
119
+ ).scaling_config.maximum_concurrency
120
+ end.sum
121
+ end
122
+
123
+ def update_event_source_mapping(concurrency:, event_source_mapping_uuids:)
124
+ concurrency_per_queue = concurrency / event_source_mapping_uuids.length
125
+
126
+ target_concurrency =
127
+ concurrency_per_queue.clamp(MINIMUM_CONCURRENCY, MAXIMUM_CONCURRENCY)
128
+
129
+ event_source_mapping_uuids.map do |event_source_mapping_uuid|
130
+ @lambda_client.update_event_source_mapping(
131
+ uuid: event_source_mapping_uuid,
132
+ scaling_config: {
133
+ maximum_concurrency: target_concurrency
134
+ }
135
+ )
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,69 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ module ElasticGraph
10
+ class IndexerAutoscalerLambda
11
+ class DetailsLogger
12
+ def initialize(
13
+ logger:,
14
+ queue_arns:,
15
+ queue_urls:,
16
+ min_cpu_target:,
17
+ max_cpu_target:,
18
+ num_messages:
19
+ )
20
+ @logger = logger
21
+
22
+ @log_data = {
23
+ "message_type" => "ConcurrencyScalerResult",
24
+ "queue_arns" => queue_arns,
25
+ "queue_urls" => queue_urls,
26
+ "min_cpu_target" => min_cpu_target,
27
+ "max_cpu_target" => max_cpu_target,
28
+ "num_messages" => num_messages
29
+ }
30
+ end
31
+
32
+ def log_increase(cpu_utilization:, current_concurrency:, new_concurrency:)
33
+ log_result({
34
+ "action" => "increase",
35
+ "cpu_utilization" => cpu_utilization,
36
+ "current_concurrency" => current_concurrency,
37
+ "new_concurrency" => new_concurrency
38
+ })
39
+ end
40
+
41
+ def log_decrease(cpu_utilization:, current_concurrency:, new_concurrency:)
42
+ log_result({
43
+ "action" => "decrease",
44
+ "cpu_utilization" => cpu_utilization,
45
+ "current_concurrency" => current_concurrency,
46
+ "new_concurrency" => new_concurrency
47
+ })
48
+ end
49
+
50
+ def log_no_change(cpu_utilization:, current_concurrency:)
51
+ log_result({
52
+ "action" => "no_change",
53
+ "cpu_utilization" => cpu_utilization,
54
+ "current_concurrency" => current_concurrency
55
+ })
56
+ end
57
+
58
+ def log_reset
59
+ log_result({"action" => "reset"})
60
+ end
61
+
62
+ private
63
+
64
+ def log_result(data)
65
+ @logger.info(@log_data.merge(data))
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/lambda_support/lambda_function"
10
+
11
+ module ElasticGraph
12
+ class IndexerAutoscalerLambda
13
+ class LambdaFunction
14
+ prepend LambdaSupport::LambdaFunction
15
+
16
+ def initialize
17
+ require "elastic_graph/indexer_autoscaler_lambda"
18
+
19
+ @concurrency_scaler = ElasticGraph::IndexerAutoscalerLambda.from_env.concurrency_scaler
20
+ end
21
+
22
+ def handle_request(event:, context:)
23
+ @concurrency_scaler.tune_indexer_concurrency(
24
+ queue_urls: event.fetch("queue_urls"),
25
+ min_cpu_target: event.fetch("min_cpu_target"),
26
+ max_cpu_target: event.fetch("max_cpu_target"),
27
+ event_source_mapping_uuids: event.fetch("event_source_mapping_uuids")
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # This is the constant used by the AWS Lambda function.
35
+ AutoscaleIndexer = ElasticGraph::IndexerAutoscalerLambda::LambdaFunction.new
@@ -0,0 +1,66 @@
1
+ # Copyright 2024 Block, Inc.
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+ #
7
+ # frozen_string_literal: true
8
+
9
+ require "elastic_graph/datastore_core"
10
+ require "elastic_graph/lambda_support"
11
+ require "elastic_graph/support/from_yaml_file"
12
+
13
+ module ElasticGraph
14
+ class IndexerAutoscalerLambda
15
+ extend Support::FromYamlFile
16
+
17
+ # Builds an `ElasticGraph::IndexerAutoscalerLambda` instance from our lambda ENV vars.
18
+ def self.from_env
19
+ LambdaSupport.build_from_env(self)
20
+ end
21
+
22
+ # A factory method that builds a IndexerAutoscalerLambda instance from the given parsed YAML config.
23
+ # `from_yaml_file(file_name, &block)` is also available (via `Support::FromYamlFile`).
24
+ def self.from_parsed_yaml(parsed_yaml, &datastore_client_customization_block)
25
+ new(datastore_core: DatastoreCore.from_parsed_yaml(parsed_yaml, for_context: :indexer_autoscaler_lambda, &datastore_client_customization_block))
26
+ end
27
+
28
+ # @dynamic datastore_core
29
+ attr_reader :datastore_core
30
+
31
+ def initialize(
32
+ datastore_core:,
33
+ sqs_client: nil,
34
+ lambda_client: nil
35
+ )
36
+ @datastore_core = datastore_core
37
+ @sqs_client = sqs_client
38
+ @lambda_client = lambda_client
39
+ end
40
+
41
+ def sqs_client
42
+ @sqs_client ||= begin
43
+ require "aws-sdk-sqs"
44
+ Aws::SQS::Client.new
45
+ end
46
+ end
47
+
48
+ def lambda_client
49
+ @lambda_client ||= begin
50
+ require "aws-sdk-lambda"
51
+ Aws::Lambda::Client.new
52
+ end
53
+ end
54
+
55
+ def concurrency_scaler
56
+ @concurrency_scaler ||= begin
57
+ require "elastic_graph/indexer_autoscaler_lambda/concurrency_scaler"
58
+ ConcurrencyScaler.new(
59
+ datastore_core: @datastore_core,
60
+ sqs_client: sqs_client,
61
+ lambda_client: lambda_client
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,330 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elasticgraph-indexer_autoscaler_lambda
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.18.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Myron Marston
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubocop-factory_bot
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.26'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.26'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop-rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: standard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.39.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.39.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: steep
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coderay
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: flatware-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 2.3.2
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '3.0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 2.3.2
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.13'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '3.13'
131
+ - !ruby/object:Gem::Dependency
132
+ name: super_diff
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 0.12.1
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 0.12.1
145
+ - !ruby/object:Gem::Dependency
146
+ name: simplecov
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.22'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '0.22'
159
+ - !ruby/object:Gem::Dependency
160
+ name: simplecov-console
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 0.9.1
166
+ - - "<"
167
+ - !ruby/object:Gem::Version
168
+ version: '1.0'
169
+ type: :development
170
+ prerelease: false
171
+ version_requirements: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: 0.9.1
176
+ - - "<"
177
+ - !ruby/object:Gem::Version
178
+ version: '1.0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: aws_lambda_ric
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: 2.0.0
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 2.0.0
193
+ - !ruby/object:Gem::Dependency
194
+ name: elasticgraph-datastore_core
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - '='
198
+ - !ruby/object:Gem::Version
199
+ version: 0.18.0.0
200
+ type: :runtime
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - '='
205
+ - !ruby/object:Gem::Version
206
+ version: 0.18.0.0
207
+ - !ruby/object:Gem::Dependency
208
+ name: elasticgraph-lambda_support
209
+ requirement: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - '='
212
+ - !ruby/object:Gem::Version
213
+ version: 0.18.0.0
214
+ type: :runtime
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - '='
219
+ - !ruby/object:Gem::Version
220
+ version: 0.18.0.0
221
+ - !ruby/object:Gem::Dependency
222
+ name: aws-sdk-lambda
223
+ requirement: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - "~>"
226
+ - !ruby/object:Gem::Version
227
+ version: '1.125'
228
+ type: :runtime
229
+ prerelease: false
230
+ version_requirements: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - "~>"
233
+ - !ruby/object:Gem::Version
234
+ version: '1.125'
235
+ - !ruby/object:Gem::Dependency
236
+ name: aws-sdk-sqs
237
+ requirement: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - "~>"
240
+ - !ruby/object:Gem::Version
241
+ version: '1.80'
242
+ type: :runtime
243
+ prerelease: false
244
+ version_requirements: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - "~>"
247
+ - !ruby/object:Gem::Version
248
+ version: '1.80'
249
+ - !ruby/object:Gem::Dependency
250
+ name: ox
251
+ requirement: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - "~>"
254
+ - !ruby/object:Gem::Version
255
+ version: '2.14'
256
+ type: :runtime
257
+ prerelease: false
258
+ version_requirements: !ruby/object:Gem::Requirement
259
+ requirements:
260
+ - - "~>"
261
+ - !ruby/object:Gem::Version
262
+ version: '2.14'
263
+ - !ruby/object:Gem::Dependency
264
+ name: elasticgraph-elasticsearch
265
+ requirement: !ruby/object:Gem::Requirement
266
+ requirements:
267
+ - - '='
268
+ - !ruby/object:Gem::Version
269
+ version: 0.18.0.0
270
+ type: :development
271
+ prerelease: false
272
+ version_requirements: !ruby/object:Gem::Requirement
273
+ requirements:
274
+ - - '='
275
+ - !ruby/object:Gem::Version
276
+ version: 0.18.0.0
277
+ - !ruby/object:Gem::Dependency
278
+ name: elasticgraph-opensearch
279
+ requirement: !ruby/object:Gem::Requirement
280
+ requirements:
281
+ - - '='
282
+ - !ruby/object:Gem::Version
283
+ version: 0.18.0.0
284
+ type: :development
285
+ prerelease: false
286
+ version_requirements: !ruby/object:Gem::Requirement
287
+ requirements:
288
+ - - '='
289
+ - !ruby/object:Gem::Version
290
+ version: 0.18.0.0
291
+ description:
292
+ email:
293
+ - myron@squareup.com
294
+ executables: []
295
+ extensions: []
296
+ extra_rdoc_files: []
297
+ files:
298
+ - LICENSE.txt
299
+ - README.md
300
+ - elasticgraph-indexer_autoscaler_lambda.gemspec
301
+ - lib/elastic_graph/indexer_autoscaler_lambda.rb
302
+ - lib/elastic_graph/indexer_autoscaler_lambda/concurrency_scaler.rb
303
+ - lib/elastic_graph/indexer_autoscaler_lambda/details_logger.rb
304
+ - lib/elastic_graph/indexer_autoscaler_lambda/lambda_function.rb
305
+ homepage:
306
+ licenses:
307
+ - MIT
308
+ metadata:
309
+ gem_category: lambda
310
+ post_install_message:
311
+ rdoc_options: []
312
+ require_paths:
313
+ - lib
314
+ required_ruby_version: !ruby/object:Gem::Requirement
315
+ requirements:
316
+ - - "~>"
317
+ - !ruby/object:Gem::Version
318
+ version: '3.2'
319
+ required_rubygems_version: !ruby/object:Gem::Requirement
320
+ requirements:
321
+ - - ">="
322
+ - !ruby/object:Gem::Version
323
+ version: '0'
324
+ requirements: []
325
+ rubygems_version: 3.5.9
326
+ signing_key:
327
+ specification_version: 4
328
+ summary: ElasticGraph gem that monitors OpenSearch CPU utilization to autoscale indexer
329
+ lambda concurrency.
330
+ test_files: []