deimos-ruby 1.23.2 → 1.23.3
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 +3 -0
- data/lib/deimos/config/configuration.rb +3 -0
- data/lib/deimos/instrumentation.rb +27 -22
- data/lib/deimos/utils/db_poller/base.rb +23 -0
- data/lib/deimos/version.rb +1 -1
- data/spec/utils/db_poller_spec.rb +42 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42d51126a6bf86b0aa338798c9b9a4b479154eda722394940df0bbc8a23e3947
|
4
|
+
data.tar.gz: 8d6c27244277078ea3b5d2a23440071aba43db3938c43cbbfe4fef27db207556
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86d98c4e4cc84a380b69196c4d04c51a6a8aaaa05601e2d7deac536495d7c689c987555e23e1bcafb895dc78e24492c9c0b174ee273c0859c9d76795a510d154
|
7
|
+
data.tar.gz: 8e7875b92bb043c95721a9a12747f6f6727bc225f1802f5d6a6ba34ee4757884347aaa42b3050d9b77f668b7ebd2654aa322cd46dea3c426d140a191c19f7fb0
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## UNRELEASED
|
9
9
|
|
10
|
+
# 1.23.3 - 2024-01-25
|
11
|
+
- Feature: Add configuration to skip messages that are too large to publish via DB poller.
|
12
|
+
|
10
13
|
# 1.23.2 - 2024-01-22
|
11
14
|
- Fix: Send a `publish_error` metric for errors other than `DeliveryFailed`.
|
12
15
|
|
@@ -500,6 +500,9 @@ module Deimos # rubocop:disable Metrics/ModuleLength
|
|
500
500
|
# The number of times to retry production when encountering a *non-Kafka* error. Set to nil
|
501
501
|
# for infinite retries.
|
502
502
|
setting :retries, 1
|
503
|
+
# If true, rather than shutting down when finding a message that is too large, log an
|
504
|
+
# error and skip it.
|
505
|
+
setting :skip_too_large_messages, false
|
503
506
|
# Amount of time, in seconds, to wait before catching updates, to allow transactions
|
504
507
|
# to complete but still pick up the right records. Should only be set for time-based mode.
|
505
508
|
setting :delay_time, 2
|
@@ -43,6 +43,32 @@ module Deimos
|
|
43
43
|
|
44
44
|
# This module listens to events published by RubyKafka.
|
45
45
|
module KafkaListener
|
46
|
+
# @param exception [Exception]
|
47
|
+
def self.handle_exception_with_messages(exception)
|
48
|
+
messages = exception.failed_messages
|
49
|
+
messages.group_by(&:topic).each do |topic, batch|
|
50
|
+
producer = Deimos::Producer.descendants.find { |c| c.topic == topic }
|
51
|
+
next if batch.empty? || !producer
|
52
|
+
|
53
|
+
decoder = Deimos.schema_backend(schema: producer.config[:schema],
|
54
|
+
namespace: producer.config[:namespace])
|
55
|
+
payloads = batch.map { |m| decoder.decode(m.value) }
|
56
|
+
|
57
|
+
Deimos.config.metrics&.increment(
|
58
|
+
'publish_error',
|
59
|
+
tags: %W(topic:#{topic}),
|
60
|
+
by: payloads.size
|
61
|
+
)
|
62
|
+
Deimos.instrument(
|
63
|
+
'produce_error',
|
64
|
+
producer: producer,
|
65
|
+
topic: topic,
|
66
|
+
exception_object: exception,
|
67
|
+
payloads: payloads
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
46
72
|
# Listens for any exceptions that happen during publishing and re-publishes
|
47
73
|
# as a Deimos event.
|
48
74
|
# @param event [ActiveSupport::Notifications::Event]
|
@@ -52,28 +78,7 @@ module Deimos
|
|
52
78
|
return unless exception
|
53
79
|
|
54
80
|
if exception.respond_to?(:failed_messages)
|
55
|
-
|
56
|
-
messages.group_by(&:topic).each do |topic, batch|
|
57
|
-
producer = Deimos::Producer.descendants.find { |c| c.topic == topic }
|
58
|
-
next if batch.empty? || !producer
|
59
|
-
|
60
|
-
decoder = Deimos.schema_backend(schema: producer.config[:schema],
|
61
|
-
namespace: producer.config[:namespace])
|
62
|
-
payloads = batch.map { |m| decoder.decode(m.value) }
|
63
|
-
|
64
|
-
Deimos.config.metrics&.increment(
|
65
|
-
'publish_error',
|
66
|
-
tags: %W(topic:#{topic}),
|
67
|
-
by: payloads.size
|
68
|
-
)
|
69
|
-
Deimos.instrument(
|
70
|
-
'produce_error',
|
71
|
-
producer: producer,
|
72
|
-
topic: topic,
|
73
|
-
exception_object: exception,
|
74
|
-
payloads: payloads
|
75
|
-
)
|
76
|
-
end
|
81
|
+
handle_exception_with_messages(exception)
|
77
82
|
else
|
78
83
|
Deimos.config.metrics&.increment(
|
79
84
|
'publish_error',
|
@@ -105,6 +105,25 @@ module Deimos
|
|
105
105
|
raise Deimos::MissingImplementationError
|
106
106
|
end
|
107
107
|
|
108
|
+
# @param exception [Exception]
|
109
|
+
# @param batch [Array<ActiveRecord::Base>]
|
110
|
+
# @param status [PollStatus]
|
111
|
+
# @param span [Object]
|
112
|
+
# @return [Boolean]
|
113
|
+
def handle_message_too_large(exception, batch, status, span)
|
114
|
+
Deimos.config.logger.error("Error publishing through DB Poller: #{exception.message}")
|
115
|
+
if @config.skip_too_large_messages
|
116
|
+
Deimos.config.logger.error("Skipping messages #{batch.map(&:id).join(', ')} since they are too large")
|
117
|
+
Deimos.config.tracer&.set_error(span, exception)
|
118
|
+
status.batches_errored += 1
|
119
|
+
true
|
120
|
+
else # do the same thing as regular Kafka::Error
|
121
|
+
sleep(0.5)
|
122
|
+
false
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# rubocop:disable Metrics/AbcSize
|
108
127
|
# @param batch [Array<ActiveRecord::Base>]
|
109
128
|
# @param status [PollStatus]
|
110
129
|
# @return [Boolean]
|
@@ -118,6 +137,9 @@ module Deimos
|
|
118
137
|
process_batch(batch)
|
119
138
|
Deimos.config.tracer&.finish(span)
|
120
139
|
status.batches_processed += 1
|
140
|
+
rescue Kafka::BufferOverflow, Kafka::MessageSizeTooLarge,
|
141
|
+
Kafka::RecordListTooLarge => e
|
142
|
+
retry unless handle_message_too_large(e, batch, status, span)
|
121
143
|
rescue Kafka::Error => e # keep trying till it fixes itself
|
122
144
|
Deimos.config.logger.error("Error publishing through DB Poller: #{e.message}")
|
123
145
|
sleep(0.5)
|
@@ -139,6 +161,7 @@ module Deimos
|
|
139
161
|
end
|
140
162
|
true
|
141
163
|
end
|
164
|
+
# rubocop:enable Metrics/AbcSize
|
142
165
|
|
143
166
|
# Publish batch using the configured producers
|
144
167
|
# @param batch [Array<ActiveRecord::Base>]
|
data/lib/deimos/version.rb
CHANGED
@@ -191,6 +191,48 @@ each_db_config(Deimos::Utils::DbPoller::Base) do
|
|
191
191
|
expect(Deimos.config.tracer).to have_received(:finish).with('a span')
|
192
192
|
end
|
193
193
|
|
194
|
+
context 'with skip_too_large_messages on' do
|
195
|
+
before(:each) { config.skip_too_large_messages = true }
|
196
|
+
|
197
|
+
it 'should skip and move on' do
|
198
|
+
error = Kafka::MessageSizeTooLarge.new('OH NOES')
|
199
|
+
allow(poller).to receive(:sleep)
|
200
|
+
allow(poller).to receive(:process_batch) do
|
201
|
+
raise error
|
202
|
+
end
|
203
|
+
poller.retrieve_poll_info
|
204
|
+
poller.process_batch_with_span(widgets, status)
|
205
|
+
expect(poller).not_to have_received(:sleep)
|
206
|
+
expect(Deimos.config.tracer).to have_received(:set_error).with('a span', error)
|
207
|
+
expect(status.batches_errored).to eq(1)
|
208
|
+
expect(status.batches_processed).to eq(0)
|
209
|
+
expect(status.messages_processed).to eq(3)
|
210
|
+
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context 'with skip_too_large_messages off' do
|
215
|
+
it 'should retry forever' do
|
216
|
+
called_once = false
|
217
|
+
allow(poller).to receive(:sleep)
|
218
|
+
allow(poller).to receive(:process_batch) do
|
219
|
+
unless called_once
|
220
|
+
called_once = true
|
221
|
+
raise Kafka::MessageSizeTooLarge, 'OH NOES'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
poller.retrieve_poll_info
|
225
|
+
poller.process_batch_with_span(widgets, status)
|
226
|
+
expect(poller).to have_received(:sleep).once.with(0.5)
|
227
|
+
expect(Deimos.config.tracer).to have_received(:finish).with('a span')
|
228
|
+
expect(status.batches_errored).to eq(0)
|
229
|
+
expect(status.batches_processed).to eq(1)
|
230
|
+
expect(status.messages_processed).to eq(3)
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
194
236
|
it 'should retry on Kafka error' do
|
195
237
|
called_once = false
|
196
238
|
allow(poller).to receive(:sleep)
|
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.23.
|
4
|
+
version: 1.23.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-01-
|
11
|
+
date: 2024-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro_turf
|