deimos-ruby 1.7.0.pre.beta1 → 1.8.1.pre.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -4
  3. data/CHANGELOG.md +50 -0
  4. data/Gemfile.lock +109 -75
  5. data/README.md +147 -16
  6. data/deimos-ruby.gemspec +4 -2
  7. data/docs/ARCHITECTURE.md +144 -0
  8. data/docs/CONFIGURATION.md +4 -0
  9. data/lib/deimos.rb +8 -7
  10. data/lib/deimos/active_record_consume/batch_consumption.rb +159 -0
  11. data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
  12. data/lib/deimos/active_record_consume/message_consumption.rb +58 -0
  13. data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
  14. data/lib/deimos/active_record_consumer.rb +33 -75
  15. data/lib/deimos/batch_consumer.rb +2 -142
  16. data/lib/deimos/config/configuration.rb +8 -10
  17. data/lib/deimos/consume/batch_consumption.rb +150 -0
  18. data/lib/deimos/consume/message_consumption.rb +94 -0
  19. data/lib/deimos/consumer.rb +79 -72
  20. data/lib/deimos/instrumentation.rb +10 -5
  21. data/lib/deimos/kafka_message.rb +1 -1
  22. data/lib/deimos/kafka_topic_info.rb +21 -2
  23. data/lib/deimos/message.rb +6 -1
  24. data/lib/deimos/schema_backends/avro_base.rb +33 -1
  25. data/lib/deimos/schema_backends/avro_schema_coercer.rb +30 -11
  26. data/lib/deimos/schema_backends/base.rb +21 -2
  27. data/lib/deimos/utils/db_poller.rb +6 -6
  28. data/lib/deimos/utils/db_producer.rb +57 -15
  29. data/lib/deimos/utils/deadlock_retry.rb +68 -0
  30. data/lib/deimos/utils/lag_reporter.rb +19 -26
  31. data/lib/deimos/utils/schema_controller_mixin.rb +111 -0
  32. data/lib/deimos/version.rb +1 -1
  33. data/lib/generators/deimos/active_record/templates/migration.rb.tt +28 -0
  34. data/lib/generators/deimos/active_record/templates/model.rb.tt +5 -0
  35. data/lib/generators/deimos/active_record_generator.rb +79 -0
  36. data/lib/generators/deimos/db_backend/templates/migration +1 -0
  37. data/lib/generators/deimos/db_backend/templates/rails3_migration +1 -0
  38. data/spec/active_record_batch_consumer_spec.rb +481 -0
  39. data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
  40. data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
  41. data/spec/active_record_consumer_spec.rb +3 -11
  42. data/spec/batch_consumer_spec.rb +24 -7
  43. data/spec/config/configuration_spec.rb +4 -0
  44. data/spec/consumer_spec.rb +6 -6
  45. data/spec/deimos_spec.rb +57 -49
  46. data/spec/generators/active_record_generator_spec.rb +56 -0
  47. data/spec/handlers/my_batch_consumer.rb +6 -1
  48. data/spec/handlers/my_consumer.rb +6 -1
  49. data/spec/kafka_listener_spec.rb +54 -0
  50. data/spec/kafka_topic_info_spec.rb +39 -16
  51. data/spec/message_spec.rb +19 -0
  52. data/spec/producer_spec.rb +34 -0
  53. data/spec/schemas/com/my-namespace/Generated.avsc +71 -0
  54. data/spec/schemas/com/my-namespace/MyNestedSchema.avsc +55 -0
  55. data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
  56. data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
  57. data/spec/schemas/com/my-namespace/request/Index.avsc +11 -0
  58. data/spec/schemas/com/my-namespace/request/UpdateRequest.avsc +11 -0
  59. data/spec/schemas/com/my-namespace/response/Index.avsc +11 -0
  60. data/spec/schemas/com/my-namespace/response/UpdateResponse.avsc +11 -0
  61. data/spec/spec_helper.rb +24 -0
  62. data/spec/utils/db_poller_spec.rb +2 -2
  63. data/spec/utils/db_producer_spec.rb +84 -10
  64. data/spec/utils/deadlock_retry_spec.rb +74 -0
  65. data/spec/utils/lag_reporter_spec.rb +29 -22
  66. data/spec/utils/schema_controller_mixin_spec.rb +68 -0
  67. metadata +87 -30
  68. data/lib/deimos/base_consumer.rb +0 -100
  69. data/lib/deimos/utils/executor.rb +0 -124
  70. data/lib/deimos/utils/platform_schema_validation.rb +0 -0
  71. data/lib/deimos/utils/signal_handler.rb +0 -68
  72. data/spec/utils/executor_spec.rb +0 -53
  73. 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.7.0.pre.beta1
4
+ version: 1.8.1.pre.beta3
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-05-12 00:00:00.000000000 Z
11
+ date: 2020-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro_turf
@@ -53,19 +53,19 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.7'
55
55
  - !ruby/object:Gem::Dependency
56
- name: activerecord
56
+ name: sigurd
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: '5.2'
62
- type: :development
61
+ version: 0.0.1
62
+ type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: '5.2'
68
+ version: 0.0.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activerecord-import
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: database_cleaner
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.7'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.7'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: ddtrace
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -198,20 +212,14 @@ dependencies:
198
212
  requirements:
199
213
  - - "~>"
200
214
  - !ruby/object:Gem::Version
201
- version: '5.2'
202
- - - ">="
203
- - !ruby/object:Gem::Version
204
- version: 5.2.4.2
215
+ version: '6'
205
216
  type: :development
206
217
  prerelease: false
207
218
  version_requirements: !ruby/object:Gem::Requirement
208
219
  requirements:
209
220
  - - "~>"
210
221
  - !ruby/object:Gem::Version
211
- version: '5.2'
212
- - - ">="
213
- - !ruby/object:Gem::Version
214
- version: 5.2.4.2
222
+ version: '6'
215
223
  - !ruby/object:Gem::Dependency
216
224
  name: rake
217
225
  requirement: !ruby/object:Gem::Requirement
@@ -254,6 +262,20 @@ dependencies:
254
262
  - - "~>"
255
263
  - !ruby/object:Gem::Version
256
264
  version: '0.3'
265
+ - !ruby/object:Gem::Dependency
266
+ name: rspec-rails
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '4'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '4'
257
279
  - !ruby/object:Gem::Dependency
258
280
  name: rubocop
259
281
  requirement: !ruby/object:Gem::Requirement
@@ -296,7 +318,7 @@ dependencies:
296
318
  - - "~>"
297
319
  - !ruby/object:Gem::Version
298
320
  version: '1.3'
299
- description:
321
+ description:
300
322
  email:
301
323
  - daniel.orner@wishabi.com
302
324
  executables:
@@ -323,10 +345,15 @@ files:
323
345
  - bin/deimos
324
346
  - deimos-ruby.gemspec
325
347
  - docker-compose.yml
348
+ - docs/ARCHITECTURE.md
326
349
  - docs/CONFIGURATION.md
327
350
  - docs/DATABASE_BACKEND.md
328
351
  - docs/PULL_REQUEST_TEMPLATE.md
329
352
  - lib/deimos.rb
353
+ - lib/deimos/active_record_consume/batch_consumption.rb
354
+ - lib/deimos/active_record_consume/batch_slicer.rb
355
+ - lib/deimos/active_record_consume/message_consumption.rb
356
+ - lib/deimos/active_record_consume/schema_model_converter.rb
330
357
  - lib/deimos/active_record_consumer.rb
331
358
  - lib/deimos/active_record_producer.rb
332
359
  - lib/deimos/backends/base.rb
@@ -334,11 +361,12 @@ files:
334
361
  - lib/deimos/backends/kafka.rb
335
362
  - lib/deimos/backends/kafka_async.rb
336
363
  - lib/deimos/backends/test.rb
337
- - lib/deimos/base_consumer.rb
338
364
  - lib/deimos/batch_consumer.rb
339
365
  - lib/deimos/config/configurable.rb
340
366
  - lib/deimos/config/configuration.rb
341
367
  - lib/deimos/config/phobos_config.rb
368
+ - lib/deimos/consume/batch_consumption.rb
369
+ - lib/deimos/consume/message_consumption.rb
342
370
  - lib/deimos/consumer.rb
343
371
  - lib/deimos/instrumentation.rb
344
372
  - lib/deimos/kafka_message.rb
@@ -368,12 +396,14 @@ files:
368
396
  - lib/deimos/tracing/provider.rb
369
397
  - lib/deimos/utils/db_poller.rb
370
398
  - lib/deimos/utils/db_producer.rb
371
- - lib/deimos/utils/executor.rb
399
+ - lib/deimos/utils/deadlock_retry.rb
372
400
  - lib/deimos/utils/inline_consumer.rb
373
401
  - lib/deimos/utils/lag_reporter.rb
374
- - lib/deimos/utils/platform_schema_validation.rb
375
- - lib/deimos/utils/signal_handler.rb
402
+ - lib/deimos/utils/schema_controller_mixin.rb
376
403
  - lib/deimos/version.rb
404
+ - lib/generators/deimos/active_record/templates/migration.rb.tt
405
+ - lib/generators/deimos/active_record/templates/model.rb.tt
406
+ - lib/generators/deimos/active_record_generator.rb
377
407
  - lib/generators/deimos/db_backend/templates/migration
378
408
  - lib/generators/deimos/db_backend/templates/rails3_migration
379
409
  - lib/generators/deimos/db_backend_generator.rb
@@ -381,6 +411,9 @@ files:
381
411
  - lib/generators/deimos/db_poller/templates/rails3_migration
382
412
  - lib/generators/deimos/db_poller_generator.rb
383
413
  - lib/tasks/deimos.rake
414
+ - spec/active_record_batch_consumer_spec.rb
415
+ - spec/active_record_consume/batch_slicer_spec.rb
416
+ - spec/active_record_consume/schema_model_converter_spec.rb
384
417
  - spec/active_record_consumer_spec.rb
385
418
  - spec/active_record_producer_spec.rb
386
419
  - spec/backends/base_spec.rb
@@ -392,10 +425,13 @@ files:
392
425
  - spec/config/configuration_spec.rb
393
426
  - spec/consumer_spec.rb
394
427
  - spec/deimos_spec.rb
428
+ - spec/generators/active_record_generator_spec.rb
395
429
  - spec/handlers/my_batch_consumer.rb
396
430
  - spec/handlers/my_consumer.rb
431
+ - spec/kafka_listener_spec.rb
397
432
  - spec/kafka_source_spec.rb
398
433
  - spec/kafka_topic_info_spec.rb
434
+ - spec/message_spec.rb
399
435
  - spec/phobos.bad_db.yml
400
436
  - spec/phobos.yml
401
437
  - spec/producer_spec.rb
@@ -405,21 +441,29 @@ files:
405
441
  - spec/schema_backends/avro_schema_registry_spec.rb
406
442
  - spec/schema_backends/avro_validation_spec.rb
407
443
  - spec/schema_backends/base_spec.rb
444
+ - spec/schemas/com/my-namespace/Generated.avsc
445
+ - spec/schemas/com/my-namespace/MyNestedSchema.avsc
408
446
  - spec/schemas/com/my-namespace/MySchema-key.avsc
409
447
  - spec/schemas/com/my-namespace/MySchema.avsc
448
+ - spec/schemas/com/my-namespace/MySchemaCompound-key.avsc
410
449
  - spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc
411
450
  - spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc
412
451
  - spec/schemas/com/my-namespace/MySchemaWithId.avsc
413
452
  - spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc
453
+ - spec/schemas/com/my-namespace/Wibble.avsc
414
454
  - spec/schemas/com/my-namespace/Widget.avsc
415
455
  - spec/schemas/com/my-namespace/WidgetTheSecond.avsc
456
+ - spec/schemas/com/my-namespace/request/Index.avsc
457
+ - spec/schemas/com/my-namespace/request/UpdateRequest.avsc
458
+ - spec/schemas/com/my-namespace/response/Index.avsc
459
+ - spec/schemas/com/my-namespace/response/UpdateResponse.avsc
416
460
  - spec/spec_helper.rb
417
461
  - spec/utils/db_poller_spec.rb
418
462
  - spec/utils/db_producer_spec.rb
419
- - spec/utils/executor_spec.rb
463
+ - spec/utils/deadlock_retry_spec.rb
420
464
  - spec/utils/lag_reporter_spec.rb
421
465
  - spec/utils/platform_schema_validation_spec.rb
422
- - spec/utils/signal_handler_spec.rb
466
+ - spec/utils/schema_controller_mixin_spec.rb
423
467
  - support/deimos-solo.png
424
468
  - support/deimos-with-name-next.png
425
469
  - support/deimos-with-name.png
@@ -428,7 +472,7 @@ homepage: ''
428
472
  licenses:
429
473
  - Apache-2.0
430
474
  metadata: {}
431
- post_install_message:
475
+ post_install_message:
432
476
  rdoc_options: []
433
477
  require_paths:
434
478
  - lib
@@ -443,12 +487,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
443
487
  - !ruby/object:Gem::Version
444
488
  version: 1.3.1
445
489
  requirements: []
446
- rubyforge_project:
447
- rubygems_version: 2.7.6
448
- signing_key:
490
+ rubygems_version: 3.1.3
491
+ signing_key:
449
492
  specification_version: 4
450
493
  summary: Kafka libraries for Ruby.
451
494
  test_files:
495
+ - spec/active_record_batch_consumer_spec.rb
496
+ - spec/active_record_consume/batch_slicer_spec.rb
497
+ - spec/active_record_consume/schema_model_converter_spec.rb
452
498
  - spec/active_record_consumer_spec.rb
453
499
  - spec/active_record_producer_spec.rb
454
500
  - spec/backends/base_spec.rb
@@ -460,10 +506,13 @@ test_files:
460
506
  - spec/config/configuration_spec.rb
461
507
  - spec/consumer_spec.rb
462
508
  - spec/deimos_spec.rb
509
+ - spec/generators/active_record_generator_spec.rb
463
510
  - spec/handlers/my_batch_consumer.rb
464
511
  - spec/handlers/my_consumer.rb
512
+ - spec/kafka_listener_spec.rb
465
513
  - spec/kafka_source_spec.rb
466
514
  - spec/kafka_topic_info_spec.rb
515
+ - spec/message_spec.rb
467
516
  - spec/phobos.bad_db.yml
468
517
  - spec/phobos.yml
469
518
  - spec/producer_spec.rb
@@ -473,18 +522,26 @@ test_files:
473
522
  - spec/schema_backends/avro_schema_registry_spec.rb
474
523
  - spec/schema_backends/avro_validation_spec.rb
475
524
  - spec/schema_backends/base_spec.rb
525
+ - spec/schemas/com/my-namespace/Generated.avsc
526
+ - spec/schemas/com/my-namespace/MyNestedSchema.avsc
476
527
  - spec/schemas/com/my-namespace/MySchema-key.avsc
477
528
  - spec/schemas/com/my-namespace/MySchema.avsc
529
+ - spec/schemas/com/my-namespace/MySchemaCompound-key.avsc
478
530
  - spec/schemas/com/my-namespace/MySchemaWithBooleans.avsc
479
531
  - spec/schemas/com/my-namespace/MySchemaWithDateTimes.avsc
480
532
  - spec/schemas/com/my-namespace/MySchemaWithId.avsc
481
533
  - spec/schemas/com/my-namespace/MySchemaWithUniqueId.avsc
534
+ - spec/schemas/com/my-namespace/Wibble.avsc
482
535
  - spec/schemas/com/my-namespace/Widget.avsc
483
536
  - spec/schemas/com/my-namespace/WidgetTheSecond.avsc
537
+ - spec/schemas/com/my-namespace/request/Index.avsc
538
+ - spec/schemas/com/my-namespace/request/UpdateRequest.avsc
539
+ - spec/schemas/com/my-namespace/response/Index.avsc
540
+ - spec/schemas/com/my-namespace/response/UpdateResponse.avsc
484
541
  - spec/spec_helper.rb
485
542
  - spec/utils/db_poller_spec.rb
486
543
  - spec/utils/db_producer_spec.rb
487
- - spec/utils/executor_spec.rb
544
+ - spec/utils/deadlock_retry_spec.rb
488
545
  - spec/utils/lag_reporter_spec.rb
489
546
  - spec/utils/platform_schema_validation_spec.rb
490
- - spec/utils/signal_handler_spec.rb
547
+ - spec/utils/schema_controller_mixin_spec.rb
@@ -1,100 +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
- def _with_span
46
- @span = Deimos.config.tracer&.start(
47
- 'deimos-consumer',
48
- resource: self.class.name.gsub('::', '-')
49
- )
50
- yield
51
- ensure
52
- Deimos.config.tracer&.finish(@span)
53
- end
54
-
55
- def _report_time_delayed(payload, metadata)
56
- return if payload.nil? || payload['timestamp'].blank?
57
-
58
- begin
59
- time_delayed = Time.now.in_time_zone - payload['timestamp'].to_datetime
60
- rescue ArgumentError
61
- Deimos.config.logger.info(
62
- message: "Error parsing timestamp! #{payload['timestamp']}"
63
- )
64
- return
65
- end
66
- Deimos.config.metrics&.histogram('handler', time_delayed, tags: %W(
67
- time:time_delayed
68
- topic:#{metadata[:topic]}
69
- ))
70
- end
71
-
72
- # Overrideable method to determine if a given error should be considered
73
- # "fatal" and always be reraised.
74
- # @param error [Exception]
75
- # @param payload [Hash]
76
- # @param metadata [Hash]
77
- # @return [Boolean]
78
- def fatal_error?(_error, _payload, _metadata)
79
- false
80
- end
81
-
82
- # @param exception [Exception]
83
- # @param payload [Hash]
84
- # @param metadata [Hash]
85
- def _handle_error(exception, payload, metadata)
86
- Deimos.config.tracer&.set_error(@span, exception)
87
-
88
- raise if Deimos.config.consumers.reraise_errors ||
89
- Deimos.config.consumers.fatal_error&.call(exception, payload, metadata) ||
90
- fatal_error?(exception, payload, metadata)
91
- end
92
-
93
- # @param _time_taken [Float]
94
- # @param _payload [Hash]
95
- # @param _metadata [Hash]
96
- def _handle_success(_time_taken, _payload, _metadata)
97
- raise NotImplementedError
98
- end
99
- end
100
- 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 executor (#{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