deimos-ruby 1.6.1 → 1.8.0.pre.beta1
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/.circleci/config.yml +9 -0
- data/.rubocop.yml +15 -13
- data/.ruby-version +1 -1
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +87 -80
- data/README.md +139 -15
- data/Rakefile +1 -1
- data/deimos-ruby.gemspec +3 -2
- data/docs/ARCHITECTURE.md +144 -0
- data/docs/CONFIGURATION.md +27 -0
- data/lib/deimos.rb +7 -6
- data/lib/deimos/active_record_consume/batch_consumption.rb +159 -0
- data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
- data/lib/deimos/active_record_consume/message_consumption.rb +58 -0
- data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
- data/lib/deimos/active_record_consumer.rb +33 -75
- data/lib/deimos/active_record_producer.rb +23 -0
- data/lib/deimos/batch_consumer.rb +2 -140
- data/lib/deimos/config/configuration.rb +28 -10
- data/lib/deimos/consume/batch_consumption.rb +148 -0
- data/lib/deimos/consume/message_consumption.rb +93 -0
- data/lib/deimos/consumer.rb +79 -69
- data/lib/deimos/kafka_message.rb +1 -1
- data/lib/deimos/kafka_source.rb +29 -23
- data/lib/deimos/kafka_topic_info.rb +1 -1
- data/lib/deimos/message.rb +6 -1
- data/lib/deimos/metrics/provider.rb +0 -2
- data/lib/deimos/poll_info.rb +9 -0
- data/lib/deimos/tracing/provider.rb +0 -2
- data/lib/deimos/utils/db_poller.rb +149 -0
- data/lib/deimos/utils/db_producer.rb +8 -3
- data/lib/deimos/utils/deadlock_retry.rb +68 -0
- data/lib/deimos/utils/lag_reporter.rb +19 -26
- data/lib/deimos/version.rb +1 -1
- data/lib/generators/deimos/db_poller/templates/migration +11 -0
- data/lib/generators/deimos/db_poller/templates/rails3_migration +16 -0
- data/lib/generators/deimos/db_poller_generator.rb +48 -0
- data/lib/tasks/deimos.rake +7 -0
- data/spec/active_record_batch_consumer_spec.rb +481 -0
- data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
- data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
- data/spec/active_record_consumer_spec.rb +22 -11
- data/spec/active_record_producer_spec.rb +66 -88
- data/spec/batch_consumer_spec.rb +23 -7
- data/spec/config/configuration_spec.rb +4 -0
- data/spec/consumer_spec.rb +8 -8
- data/spec/deimos_spec.rb +57 -49
- data/spec/handlers/my_batch_consumer.rb +6 -1
- data/spec/handlers/my_consumer.rb +6 -1
- data/spec/kafka_source_spec.rb +53 -0
- data/spec/message_spec.rb +19 -0
- data/spec/producer_spec.rb +3 -3
- data/spec/rake_spec.rb +1 -1
- data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
- data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
- data/spec/spec_helper.rb +61 -6
- data/spec/utils/db_poller_spec.rb +320 -0
- data/spec/utils/deadlock_retry_spec.rb +74 -0
- data/spec/utils/lag_reporter_spec.rb +29 -22
- metadata +61 -20
- data/lib/deimos/base_consumer.rb +0 -104
- data/lib/deimos/utils/executor.rb +0 -124
- data/lib/deimos/utils/platform_schema_validation.rb +0 -0
- data/lib/deimos/utils/signal_handler.rb +0 -68
- data/spec/utils/executor_spec.rb +0 -53
- data/spec/utils/signal_handler_spec.rb +0 -16
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deimos-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0.pre.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro_turf
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sigurd
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.0.1
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: activerecord
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,19 +109,19 @@ dependencies:
|
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '1.9'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: database_cleaner
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '1'
|
117
|
+
version: '1.7'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '1'
|
124
|
+
version: '1.7'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: ddtrace
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -213,6 +227,9 @@ dependencies:
|
|
213
227
|
- - "~>"
|
214
228
|
- !ruby/object:Gem::Version
|
215
229
|
version: '5.2'
|
230
|
+
- - ">="
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: 5.2.4.2
|
216
233
|
type: :development
|
217
234
|
prerelease: false
|
218
235
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -220,6 +237,9 @@ dependencies:
|
|
220
237
|
- - "~>"
|
221
238
|
- !ruby/object:Gem::Version
|
222
239
|
version: '5.2'
|
240
|
+
- - ">="
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: 5.2.4.2
|
223
243
|
- !ruby/object:Gem::Dependency
|
224
244
|
name: rake
|
225
245
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,7 +324,7 @@ dependencies:
|
|
304
324
|
- - "~>"
|
305
325
|
- !ruby/object:Gem::Version
|
306
326
|
version: '1.3'
|
307
|
-
description:
|
327
|
+
description:
|
308
328
|
email:
|
309
329
|
- daniel.orner@wishabi.com
|
310
330
|
executables:
|
@@ -331,10 +351,15 @@ files:
|
|
331
351
|
- bin/deimos
|
332
352
|
- deimos-ruby.gemspec
|
333
353
|
- docker-compose.yml
|
354
|
+
- docs/ARCHITECTURE.md
|
334
355
|
- docs/CONFIGURATION.md
|
335
356
|
- docs/DATABASE_BACKEND.md
|
336
357
|
- docs/PULL_REQUEST_TEMPLATE.md
|
337
358
|
- lib/deimos.rb
|
359
|
+
- lib/deimos/active_record_consume/batch_consumption.rb
|
360
|
+
- lib/deimos/active_record_consume/batch_slicer.rb
|
361
|
+
- lib/deimos/active_record_consume/message_consumption.rb
|
362
|
+
- lib/deimos/active_record_consume/schema_model_converter.rb
|
338
363
|
- lib/deimos/active_record_consumer.rb
|
339
364
|
- lib/deimos/active_record_producer.rb
|
340
365
|
- lib/deimos/backends/base.rb
|
@@ -342,11 +367,12 @@ files:
|
|
342
367
|
- lib/deimos/backends/kafka.rb
|
343
368
|
- lib/deimos/backends/kafka_async.rb
|
344
369
|
- lib/deimos/backends/test.rb
|
345
|
-
- lib/deimos/base_consumer.rb
|
346
370
|
- lib/deimos/batch_consumer.rb
|
347
371
|
- lib/deimos/config/configurable.rb
|
348
372
|
- lib/deimos/config/configuration.rb
|
349
373
|
- lib/deimos/config/phobos_config.rb
|
374
|
+
- lib/deimos/consume/batch_consumption.rb
|
375
|
+
- lib/deimos/consume/message_consumption.rb
|
350
376
|
- lib/deimos/consumer.rb
|
351
377
|
- lib/deimos/instrumentation.rb
|
352
378
|
- lib/deimos/kafka_message.rb
|
@@ -359,6 +385,7 @@ files:
|
|
359
385
|
- lib/deimos/monkey_patches/phobos_cli.rb
|
360
386
|
- lib/deimos/monkey_patches/phobos_producer.rb
|
361
387
|
- lib/deimos/monkey_patches/ruby_kafka_heartbeat.rb
|
388
|
+
- lib/deimos/poll_info.rb
|
362
389
|
- lib/deimos/producer.rb
|
363
390
|
- lib/deimos/railtie.rb
|
364
391
|
- lib/deimos/schema_backends/avro_base.rb
|
@@ -373,17 +400,22 @@ files:
|
|
373
400
|
- lib/deimos/tracing/datadog.rb
|
374
401
|
- lib/deimos/tracing/mock.rb
|
375
402
|
- lib/deimos/tracing/provider.rb
|
403
|
+
- lib/deimos/utils/db_poller.rb
|
376
404
|
- lib/deimos/utils/db_producer.rb
|
377
|
-
- lib/deimos/utils/
|
405
|
+
- lib/deimos/utils/deadlock_retry.rb
|
378
406
|
- lib/deimos/utils/inline_consumer.rb
|
379
407
|
- lib/deimos/utils/lag_reporter.rb
|
380
|
-
- lib/deimos/utils/platform_schema_validation.rb
|
381
|
-
- lib/deimos/utils/signal_handler.rb
|
382
408
|
- lib/deimos/version.rb
|
383
409
|
- lib/generators/deimos/db_backend/templates/migration
|
384
410
|
- lib/generators/deimos/db_backend/templates/rails3_migration
|
385
411
|
- lib/generators/deimos/db_backend_generator.rb
|
412
|
+
- lib/generators/deimos/db_poller/templates/migration
|
413
|
+
- lib/generators/deimos/db_poller/templates/rails3_migration
|
414
|
+
- lib/generators/deimos/db_poller_generator.rb
|
386
415
|
- lib/tasks/deimos.rake
|
416
|
+
- spec/active_record_batch_consumer_spec.rb
|
417
|
+
- spec/active_record_consume/batch_slicer_spec.rb
|
418
|
+
- spec/active_record_consume/schema_model_converter_spec.rb
|
387
419
|
- spec/active_record_consumer_spec.rb
|
388
420
|
- spec/active_record_producer_spec.rb
|
389
421
|
- spec/backends/base_spec.rb
|
@@ -399,6 +431,7 @@ files:
|
|
399
431
|
- spec/handlers/my_consumer.rb
|
400
432
|
- spec/kafka_source_spec.rb
|
401
433
|
- spec/kafka_topic_info_spec.rb
|
434
|
+
- spec/message_spec.rb
|
402
435
|
- spec/phobos.bad_db.yml
|
403
436
|
- spec/phobos.yml
|
404
437
|
- spec/producer_spec.rb
|
@@ -410,18 +443,20 @@ files:
|
|
410
443
|
- spec/schema_backends/base_spec.rb
|
411
444
|
- spec/schemas/com/my-namespace/MySchema-key.avsc
|
412
445
|
- spec/schemas/com/my-namespace/MySchema.avsc
|
446
|
+
- spec/schemas/com/my-namespace/MySchemaCompound-key.avsc
|
413
447
|
- spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc
|
414
448
|
- spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc
|
415
449
|
- spec/schemas/com/my-namespace/MySchemaWithId.avsc
|
416
450
|
- spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc
|
451
|
+
- spec/schemas/com/my-namespace/Wibble.avsc
|
417
452
|
- spec/schemas/com/my-namespace/Widget.avsc
|
418
453
|
- spec/schemas/com/my-namespace/WidgetTheSecond.avsc
|
419
454
|
- spec/spec_helper.rb
|
455
|
+
- spec/utils/db_poller_spec.rb
|
420
456
|
- spec/utils/db_producer_spec.rb
|
421
|
-
- spec/utils/
|
457
|
+
- spec/utils/deadlock_retry_spec.rb
|
422
458
|
- spec/utils/lag_reporter_spec.rb
|
423
459
|
- spec/utils/platform_schema_validation_spec.rb
|
424
|
-
- spec/utils/signal_handler_spec.rb
|
425
460
|
- support/deimos-solo.png
|
426
461
|
- support/deimos-with-name-next.png
|
427
462
|
- support/deimos-with-name.png
|
@@ -430,7 +465,7 @@ homepage: ''
|
|
430
465
|
licenses:
|
431
466
|
- Apache-2.0
|
432
467
|
metadata: {}
|
433
|
-
post_install_message:
|
468
|
+
post_install_message:
|
434
469
|
rdoc_options: []
|
435
470
|
require_paths:
|
436
471
|
- lib
|
@@ -441,15 +476,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
441
476
|
version: '0'
|
442
477
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
443
478
|
requirements:
|
444
|
-
- - "
|
479
|
+
- - ">"
|
445
480
|
- !ruby/object:Gem::Version
|
446
|
-
version:
|
481
|
+
version: 1.3.1
|
447
482
|
requirements: []
|
448
|
-
rubygems_version: 3.1.
|
449
|
-
signing_key:
|
483
|
+
rubygems_version: 3.1.3
|
484
|
+
signing_key:
|
450
485
|
specification_version: 4
|
451
486
|
summary: Kafka libraries for Ruby.
|
452
487
|
test_files:
|
488
|
+
- spec/active_record_batch_consumer_spec.rb
|
489
|
+
- spec/active_record_consume/batch_slicer_spec.rb
|
490
|
+
- spec/active_record_consume/schema_model_converter_spec.rb
|
453
491
|
- spec/active_record_consumer_spec.rb
|
454
492
|
- spec/active_record_producer_spec.rb
|
455
493
|
- spec/backends/base_spec.rb
|
@@ -465,6 +503,7 @@ test_files:
|
|
465
503
|
- spec/handlers/my_consumer.rb
|
466
504
|
- spec/kafka_source_spec.rb
|
467
505
|
- spec/kafka_topic_info_spec.rb
|
506
|
+
- spec/message_spec.rb
|
468
507
|
- spec/phobos.bad_db.yml
|
469
508
|
- spec/phobos.yml
|
470
509
|
- spec/producer_spec.rb
|
@@ -476,15 +515,17 @@ test_files:
|
|
476
515
|
- spec/schema_backends/base_spec.rb
|
477
516
|
- spec/schemas/com/my-namespace/MySchema-key.avsc
|
478
517
|
- spec/schemas/com/my-namespace/MySchema.avsc
|
518
|
+
- spec/schemas/com/my-namespace/MySchemaCompound-key.avsc
|
479
519
|
- spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc
|
480
520
|
- spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc
|
481
521
|
- spec/schemas/com/my-namespace/MySchemaWithId.avsc
|
482
522
|
- spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc
|
523
|
+
- spec/schemas/com/my-namespace/Wibble.avsc
|
483
524
|
- spec/schemas/com/my-namespace/Widget.avsc
|
484
525
|
- spec/schemas/com/my-namespace/WidgetTheSecond.avsc
|
485
526
|
- spec/spec_helper.rb
|
527
|
+
- spec/utils/db_poller_spec.rb
|
486
528
|
- spec/utils/db_producer_spec.rb
|
487
|
-
- spec/utils/
|
529
|
+
- spec/utils/deadlock_retry_spec.rb
|
488
530
|
- spec/utils/lag_reporter_spec.rb
|
489
531
|
- spec/utils/platform_schema_validation_spec.rb
|
490
|
-
- spec/utils/signal_handler_spec.rb
|
data/lib/deimos/base_consumer.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Deimos
|
4
|
-
# Shared methods for Kafka Consumers
|
5
|
-
class BaseConsumer
|
6
|
-
include SharedConfig
|
7
|
-
|
8
|
-
class << self
|
9
|
-
# @return [Deimos::SchemaBackends::Base]
|
10
|
-
def decoder
|
11
|
-
@decoder ||= Deimos.schema_backend(schema: config[:schema],
|
12
|
-
namespace: config[:namespace])
|
13
|
-
end
|
14
|
-
|
15
|
-
# @return [Deimos::SchemaBackends::Base]
|
16
|
-
def key_decoder
|
17
|
-
@key_decoder ||= Deimos.schema_backend(schema: config[:key_schema],
|
18
|
-
namespace: config[:namespace])
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Helper method to decode an encoded key.
|
23
|
-
# @param key [String]
|
24
|
-
# @return [Object] the decoded key.
|
25
|
-
def decode_key(key)
|
26
|
-
return nil if key.nil?
|
27
|
-
|
28
|
-
config = self.class.config
|
29
|
-
unless config[:key_configured]
|
30
|
-
raise 'No key config given - if you are not decoding keys, please use '\
|
31
|
-
'`key_config plain: true`'
|
32
|
-
end
|
33
|
-
|
34
|
-
if config[:key_field]
|
35
|
-
self.class.decoder.decode_key(key, config[:key_field])
|
36
|
-
elsif config[:key_schema]
|
37
|
-
self.class.key_decoder.decode(key, schema: config[:key_schema])
|
38
|
-
else # no encoding
|
39
|
-
key
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
protected
|
44
|
-
|
45
|
-
# @param payload [Hash|String]
|
46
|
-
# @param metadata [Hash]
|
47
|
-
def _with_error_span(payload, metadata)
|
48
|
-
@span = Deimos.config.tracer&.start(
|
49
|
-
'deimos-consumer',
|
50
|
-
resource: self.class.name.gsub('::', '-')
|
51
|
-
)
|
52
|
-
yield
|
53
|
-
rescue StandardError => e
|
54
|
-
_handle_error(e, payload, metadata)
|
55
|
-
ensure
|
56
|
-
Deimos.config.tracer&.finish(@span)
|
57
|
-
end
|
58
|
-
|
59
|
-
def _report_time_delayed(payload, metadata)
|
60
|
-
return if payload.nil? || payload['timestamp'].blank?
|
61
|
-
|
62
|
-
begin
|
63
|
-
time_delayed = Time.now.in_time_zone - payload['timestamp'].to_datetime
|
64
|
-
rescue ArgumentError
|
65
|
-
Deimos.config.logger.info(
|
66
|
-
message: "Error parsing timestamp! #{payload['timestamp']}"
|
67
|
-
)
|
68
|
-
return
|
69
|
-
end
|
70
|
-
Deimos.config.metrics&.histogram('handler', time_delayed, tags: %W(
|
71
|
-
time:time_delayed
|
72
|
-
topic:#{metadata[:topic]}
|
73
|
-
))
|
74
|
-
end
|
75
|
-
|
76
|
-
# Overrideable method to determine if a given error should be considered
|
77
|
-
# "fatal" and always be reraised.
|
78
|
-
# @param error [Exception]
|
79
|
-
# @param payload [Hash]
|
80
|
-
# @param metadata [Hash]
|
81
|
-
# @return [Boolean]
|
82
|
-
def fatal_error?(_error, _payload, _metadata)
|
83
|
-
false
|
84
|
-
end
|
85
|
-
|
86
|
-
# @param exception [Exception]
|
87
|
-
# @param payload [Hash]
|
88
|
-
# @param metadata [Hash]
|
89
|
-
def _handle_error(exception, payload, metadata)
|
90
|
-
Deimos.config.tracer&.set_error(@span, exception)
|
91
|
-
|
92
|
-
raise if Deimos.config.consumers.reraise_errors ||
|
93
|
-
Deimos.config.consumers.fatal_error&.call(exception, payload, metadata) ||
|
94
|
-
fatal_error?(exception, payload, metadata)
|
95
|
-
end
|
96
|
-
|
97
|
-
# @param _time_taken [Float]
|
98
|
-
# @param _payload [Hash]
|
99
|
-
# @param _metadata [Hash]
|
100
|
-
def _handle_success(_time_taken, _payload, _metadata)
|
101
|
-
raise NotImplementedError
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
@@ -1,124 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Lint/RescueException
|
4
|
-
module Deimos
|
5
|
-
module Utils
|
6
|
-
# Mostly copied from Phobos::Executor. We should DRY this up by putting in a
|
7
|
-
# PR to make it more generic. Might even make sense to move to a separate
|
8
|
-
# gem.
|
9
|
-
class Executor
|
10
|
-
# @return [Array<#start, #stop, #id>]
|
11
|
-
attr_accessor :runners
|
12
|
-
|
13
|
-
# @param runners [Array<#start, #stop, #id>] A list of objects that can be
|
14
|
-
# started or stopped.
|
15
|
-
# @param logger [Logger]
|
16
|
-
# @param sleep_seconds [Integer] Use a fixed time to sleep between
|
17
|
-
# failed runs instead of using an exponential backoff.
|
18
|
-
def initialize(runners, sleep_seconds: nil, logger: Logger.new(STDOUT))
|
19
|
-
@threads = Concurrent::Array.new
|
20
|
-
@runners = runners
|
21
|
-
@logger = logger
|
22
|
-
@sleep_seconds = sleep_seconds
|
23
|
-
end
|
24
|
-
|
25
|
-
# Start the executor.
|
26
|
-
def start
|
27
|
-
@logger.info('Starting executor')
|
28
|
-
@signal_to_stop = false
|
29
|
-
@threads.clear
|
30
|
-
@thread_pool = Concurrent::FixedThreadPool.new(@runners.size)
|
31
|
-
|
32
|
-
@runners.each do |runner|
|
33
|
-
@thread_pool.post do
|
34
|
-
thread = Thread.current
|
35
|
-
thread.abort_on_exception = true
|
36
|
-
@threads << thread
|
37
|
-
run_object(runner)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
true
|
42
|
-
end
|
43
|
-
|
44
|
-
# Stop the executor.
|
45
|
-
def stop
|
46
|
-
return if @signal_to_stop
|
47
|
-
|
48
|
-
@logger.info('Stopping executor')
|
49
|
-
@signal_to_stop = true
|
50
|
-
@runners.each(&:stop)
|
51
|
-
@threads.select(&:alive?).each do |thread|
|
52
|
-
begin
|
53
|
-
thread.wakeup
|
54
|
-
rescue StandardError
|
55
|
-
nil
|
56
|
-
end
|
57
|
-
end
|
58
|
-
@thread_pool&.shutdown
|
59
|
-
@thread_pool&.wait_for_termination
|
60
|
-
@logger.info('Executor stopped')
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
# @param exception [Throwable]
|
66
|
-
# @return [Hash]
|
67
|
-
def error_metadata(exception)
|
68
|
-
{
|
69
|
-
exception_class: exception.class.name,
|
70
|
-
exception_message: exception.message,
|
71
|
-
backtrace: exception.backtrace
|
72
|
-
}
|
73
|
-
end
|
74
|
-
|
75
|
-
def run_object(runner)
|
76
|
-
retry_count = 0
|
77
|
-
|
78
|
-
begin
|
79
|
-
@logger.info("Running #{runner.id}")
|
80
|
-
runner.start
|
81
|
-
retry_count = 0 # success - reset retry count
|
82
|
-
rescue Exception => e
|
83
|
-
handle_crashed_runner(runner, e, retry_count)
|
84
|
-
retry_count += 1
|
85
|
-
retry unless @signal_to_stop
|
86
|
-
end
|
87
|
-
rescue Exception => e
|
88
|
-
@logger.error("Failed to run listener (#{e.message}) #{error_metadata(e)}")
|
89
|
-
raise e
|
90
|
-
end
|
91
|
-
|
92
|
-
# @return [ExponentialBackoff]
|
93
|
-
def create_exponential_backoff
|
94
|
-
min = 1
|
95
|
-
max = 60
|
96
|
-
ExponentialBackoff.new(min, max).tap do |backoff|
|
97
|
-
backoff.randomize_factor = rand
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# When "runner#start" is interrupted / crashes we assume it's
|
102
|
-
# safe to be called again
|
103
|
-
def handle_crashed_runner(runner, error, retry_count)
|
104
|
-
interval = if @sleep_seconds
|
105
|
-
@sleep_seconds
|
106
|
-
else
|
107
|
-
backoff = create_exponential_backoff
|
108
|
-
backoff.interval_at(retry_count).round(2)
|
109
|
-
end
|
110
|
-
|
111
|
-
metadata = {
|
112
|
-
listener_id: runner.id,
|
113
|
-
retry_count: retry_count,
|
114
|
-
waiting_time: interval
|
115
|
-
}.merge(error_metadata(error))
|
116
|
-
|
117
|
-
@logger.error("Runner crashed, waiting #{interval}s (#{error.message}) #{metadata}")
|
118
|
-
sleep(interval)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# rubocop:enable Lint/RescueException
|