deimos-ruby 1.24.2 → 2.0.0.pre.alpha1

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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +0 -17
  3. data/.tool-versions +1 -0
  4. data/CHANGELOG.md +5 -0
  5. data/README.md +287 -498
  6. data/deimos-ruby.gemspec +4 -4
  7. data/docs/CONFIGURATION.md +133 -226
  8. data/docs/UPGRADING.md +237 -0
  9. data/lib/deimos/active_record_consume/batch_consumption.rb +29 -28
  10. data/lib/deimos/active_record_consume/mass_updater.rb +59 -4
  11. data/lib/deimos/active_record_consume/message_consumption.rb +15 -21
  12. data/lib/deimos/active_record_consumer.rb +36 -21
  13. data/lib/deimos/active_record_producer.rb +28 -9
  14. data/lib/deimos/backends/base.rb +4 -35
  15. data/lib/deimos/backends/kafka.rb +6 -22
  16. data/lib/deimos/backends/kafka_async.rb +6 -22
  17. data/lib/deimos/backends/{db.rb → outbox.rb} +13 -9
  18. data/lib/deimos/config/configuration.rb +116 -379
  19. data/lib/deimos/consume/batch_consumption.rb +24 -124
  20. data/lib/deimos/consume/message_consumption.rb +36 -63
  21. data/lib/deimos/consumer.rb +16 -75
  22. data/lib/deimos/ext/consumer_route.rb +35 -0
  23. data/lib/deimos/ext/producer_middleware.rb +94 -0
  24. data/lib/deimos/ext/producer_route.rb +22 -0
  25. data/lib/deimos/ext/redraw.rb +29 -0
  26. data/lib/deimos/ext/routing_defaults.rb +72 -0
  27. data/lib/deimos/ext/schema_route.rb +70 -0
  28. data/lib/deimos/kafka_message.rb +2 -2
  29. data/lib/deimos/kafka_source.rb +2 -7
  30. data/lib/deimos/kafka_topic_info.rb +1 -1
  31. data/lib/deimos/logging.rb +71 -0
  32. data/lib/deimos/message.rb +2 -11
  33. data/lib/deimos/metrics/datadog.rb +40 -1
  34. data/lib/deimos/metrics/provider.rb +4 -4
  35. data/lib/deimos/producer.rb +39 -116
  36. data/lib/deimos/railtie.rb +6 -0
  37. data/lib/deimos/schema_backends/avro_base.rb +21 -21
  38. data/lib/deimos/schema_backends/avro_schema_registry.rb +1 -2
  39. data/lib/deimos/schema_backends/avro_validation.rb +2 -2
  40. data/lib/deimos/schema_backends/base.rb +19 -12
  41. data/lib/deimos/schema_backends/mock.rb +6 -1
  42. data/lib/deimos/schema_backends/plain.rb +47 -0
  43. data/lib/deimos/schema_class/base.rb +2 -2
  44. data/lib/deimos/schema_class/enum.rb +1 -1
  45. data/lib/deimos/schema_class/record.rb +2 -2
  46. data/lib/deimos/test_helpers.rb +95 -320
  47. data/lib/deimos/tracing/provider.rb +6 -6
  48. data/lib/deimos/transcoder.rb +88 -0
  49. data/lib/deimos/utils/db_poller/base.rb +16 -14
  50. data/lib/deimos/utils/db_poller/state_based.rb +3 -3
  51. data/lib/deimos/utils/db_poller/time_based.rb +4 -4
  52. data/lib/deimos/utils/db_poller.rb +1 -1
  53. data/lib/deimos/utils/deadlock_retry.rb +1 -1
  54. data/lib/deimos/utils/{db_producer.rb → outbox_producer.rb} +16 -47
  55. data/lib/deimos/utils/schema_class.rb +0 -7
  56. data/lib/deimos/version.rb +1 -1
  57. data/lib/deimos.rb +79 -26
  58. data/lib/generators/deimos/{db_backend_generator.rb → outbox_backend_generator.rb} +4 -4
  59. data/lib/generators/deimos/schema_class_generator.rb +0 -1
  60. data/lib/generators/deimos/v2/templates/karafka.rb.tt +149 -0
  61. data/lib/generators/deimos/v2_generator.rb +193 -0
  62. data/lib/tasks/deimos.rake +5 -7
  63. data/spec/active_record_batch_consumer_association_spec.rb +22 -13
  64. data/spec/active_record_batch_consumer_spec.rb +84 -65
  65. data/spec/active_record_consume/batch_consumption_spec.rb +10 -10
  66. data/spec/active_record_consume/batch_slicer_spec.rb +12 -12
  67. data/spec/active_record_consume/mass_updater_spec.rb +137 -0
  68. data/spec/active_record_consumer_spec.rb +29 -13
  69. data/spec/active_record_producer_spec.rb +36 -26
  70. data/spec/backends/base_spec.rb +0 -23
  71. data/spec/backends/kafka_async_spec.rb +1 -3
  72. data/spec/backends/kafka_spec.rb +1 -3
  73. data/spec/backends/{db_spec.rb → outbox_spec.rb} +14 -20
  74. data/spec/batch_consumer_spec.rb +66 -116
  75. data/spec/consumer_spec.rb +53 -147
  76. data/spec/deimos_spec.rb +10 -126
  77. data/spec/kafka_source_spec.rb +19 -52
  78. data/spec/karafka/karafka.rb +69 -0
  79. data/spec/karafka_config/karafka_spec.rb +97 -0
  80. data/spec/logging_spec.rb +25 -0
  81. data/spec/message_spec.rb +9 -9
  82. data/spec/producer_spec.rb +112 -254
  83. data/spec/rake_spec.rb +1 -3
  84. data/spec/schema_backends/avro_validation_spec.rb +1 -1
  85. data/spec/schemas/com/my-namespace/MySchemaWithTitle.avsc +22 -0
  86. data/spec/snapshots/consumers-no-nest.snap +49 -0
  87. data/spec/snapshots/consumers.snap +49 -0
  88. data/spec/snapshots/consumers_and_producers-no-nest.snap +49 -0
  89. data/spec/snapshots/consumers_and_producers.snap +49 -0
  90. data/spec/snapshots/consumers_circular-no-nest.snap +49 -0
  91. data/spec/snapshots/consumers_circular.snap +49 -0
  92. data/spec/snapshots/consumers_complex_types-no-nest.snap +49 -0
  93. data/spec/snapshots/consumers_complex_types.snap +49 -0
  94. data/spec/snapshots/consumers_nested-no-nest.snap +49 -0
  95. data/spec/snapshots/consumers_nested.snap +49 -0
  96. data/spec/snapshots/namespace_folders.snap +49 -0
  97. data/spec/snapshots/namespace_map.snap +49 -0
  98. data/spec/snapshots/producers_with_key-no-nest.snap +49 -0
  99. data/spec/snapshots/producers_with_key.snap +49 -0
  100. data/spec/spec_helper.rb +61 -29
  101. data/spec/utils/db_poller_spec.rb +49 -39
  102. data/spec/utils/{db_producer_spec.rb → outbox_producer_spec.rb} +17 -184
  103. metadata +58 -67
  104. data/lib/deimos/batch_consumer.rb +0 -7
  105. data/lib/deimos/config/phobos_config.rb +0 -163
  106. data/lib/deimos/instrumentation.rb +0 -95
  107. data/lib/deimos/monkey_patches/phobos_cli.rb +0 -35
  108. data/lib/deimos/utils/inline_consumer.rb +0 -158
  109. data/lib/deimos/utils/lag_reporter.rb +0 -186
  110. data/lib/deimos/utils/schema_controller_mixin.rb +0 -129
  111. data/spec/config/configuration_spec.rb +0 -321
  112. data/spec/kafka_listener_spec.rb +0 -55
  113. data/spec/phobos.bad_db.yml +0 -73
  114. data/spec/phobos.yml +0 -77
  115. data/spec/utils/inline_consumer_spec.rb +0 -31
  116. data/spec/utils/lag_reporter_spec.rb +0 -76
  117. data/spec/utils/platform_schema_validation_spec.rb +0 -0
  118. data/spec/utils/schema_controller_mixin_spec.rb +0 -84
  119. /data/lib/generators/deimos/{db_backend → outbox_backend}/templates/migration +0 -0
  120. /data/lib/generators/deimos/{db_backend → outbox_backend}/templates/rails3_migration +0 -0
@@ -3,19 +3,34 @@
3
3
  # :nodoc:
4
4
  module ConsumerTest
5
5
  describe Deimos::Consumer, 'Batch Consumer' do
6
- prepend_before(:each) do
7
- # :nodoc:
8
- consumer_class = Class.new(described_class) do
9
- schema 'MySchema'
10
- namespace 'com.my-namespace'
11
- key_config field: 'test_id'
12
-
6
+ let(:schema) { 'MySchema' }
7
+ let(:use_schema_classes) { false }
8
+ let(:reraise_errors) { false }
9
+ let(:key_config) { { field: 'test_id' } }
10
+ let(:consumer_class) do
11
+ Class.new(described_class) do
13
12
  # :nodoc:
14
- def consume_batch(_payloads, _metadata)
15
- raise 'This should not be called unless call_original is set'
13
+ def consume_batch
16
14
  end
17
15
  end
16
+ end
17
+ before(:each) do
18
+ # :nodoc:
19
+ stub_const('MyBatchConsumer', consumer_class)
18
20
  stub_const('ConsumerTest::MyBatchConsumer', consumer_class)
21
+ klass = consumer_class
22
+ route_schema = schema
23
+ route_key = key_config
24
+ route_use_classes = use_schema_classes
25
+ Karafka::App.routes.redraw do
26
+ topic 'my-topic' do
27
+ consumer klass
28
+ schema route_schema
29
+ namespace 'com.my-namespace'
30
+ key_config route_key
31
+ use_schema_classes route_use_classes
32
+ end
33
+ end
19
34
  end
20
35
 
21
36
  let(:batch) do
@@ -38,41 +53,23 @@ module ConsumerTest
38
53
  Deimos::Utils::SchemaClass.instance(p, 'MySchema', 'com.my-namespace')
39
54
  end
40
55
  end
56
+ let(:use_schema_classes) { true }
41
57
 
42
58
  before(:each) do
43
59
  Deimos.configure do |config|
44
- config.schema.use_schema_classes = use_schema_classes
45
60
  config.schema.use_full_namespace = true
46
61
  end
47
62
  end
48
63
 
49
- it 'should provide backwards compatibility for BatchConsumer class' do
50
- consumer_class = Class.new(Deimos::BatchConsumer) do
51
- schema 'MySchema'
52
- namespace 'com.my-namespace'
53
- key_config field: 'test_id'
54
-
55
- # :nodoc:
56
- def consume_batch(_payloads, _metadata)
57
- raise 'This should not be called unless call_original is set'
58
- end
59
- end
60
- stub_const('ConsumerTest::MyOldBatchConsumer', consumer_class)
61
-
62
- test_consume_batch(MyOldBatchConsumer, schema_class_batch) do |received, _metadata|
63
- expect(received).to eq(schema_class_batch)
64
- end
65
- end
66
-
67
64
  it 'should consume a batch of messages' do
68
- test_consume_batch(MyBatchConsumer, schema_class_batch) do |received, _metadata|
69
- expect(received).to eq(schema_class_batch)
65
+ test_consume_batch(MyBatchConsumer, schema_class_batch) do |received|
66
+ expect(received.payloads).to eq(schema_class_batch)
70
67
  end
71
68
  end
72
69
 
73
70
  it 'should consume a message on a topic' do
74
- test_consume_batch('my_batch_consume_topic', schema_class_batch) do |received, _metadata|
75
- expect(received).to eq(schema_class_batch)
71
+ test_consume_batch('my-topic', schema_class_batch) do |received|
72
+ expect(received.payloads).to eq(schema_class_batch)
76
73
  end
77
74
  end
78
75
  end
@@ -80,29 +77,19 @@ module ConsumerTest
80
77
  end
81
78
 
82
79
  describe 'when reraising errors is disabled' do
83
- before(:each) do
84
- Deimos.configure { |config| config.consumers.reraise_errors = false }
85
- end
80
+ let(:reraise_errors) { false }
86
81
 
87
82
  it 'should not fail when before_consume_batch fails' do
88
83
  expect {
89
84
  test_consume_batch(
90
85
  MyBatchConsumer,
91
- batch,
92
- skip_expectation: true
93
- ) { raise 'OH NOES' }
86
+ batch
87
+ ) do
88
+ raise 'OH NOES'
89
+ end
94
90
  }.not_to raise_error
95
91
  end
96
92
 
97
- it 'should not fail when consume_batch fails' do
98
- expect {
99
- test_consume_batch(
100
- MyBatchConsumer,
101
- invalid_payloads,
102
- skip_expectation: true
103
- )
104
- }.not_to raise_error
105
- end
106
93
  end
107
94
 
108
95
  describe 'decoding' do
@@ -111,53 +98,32 @@ module ConsumerTest
111
98
  end
112
99
 
113
100
  it 'should decode payloads for all messages in the batch' do
114
- test_consume_batch('my_batch_consume_topic', batch) do |received, _metadata|
101
+ test_consume_batch('my-topic', batch) do
115
102
  # Mock decoder simply returns the payload
116
- expect(received).to eq(batch)
103
+ expect(messages.payloads).to eq(batch)
117
104
  end
118
105
  end
119
106
 
120
107
  it 'should decode keys for all messages in the batch' do
121
- expect_any_instance_of(ConsumerTest::MyBatchConsumer).
122
- to receive(:decode_key).with(keys[0]).and_call_original
123
- expect_any_instance_of(ConsumerTest::MyBatchConsumer).
124
- to receive(:decode_key).with(keys[1]).and_call_original
125
-
126
- test_consume_batch('my_batch_consume_topic', batch, keys: keys) do |_received, metadata|
127
- # Mock decode_key extracts the value of the first field as the key
128
- expect(metadata[:keys]).to eq(%w(foo bar))
129
- expect(metadata[:first_offset]).to eq(1)
108
+ test_consume_batch('my-topic', batch, keys: keys) do
109
+ expect(messages.map(&:key)).to eq([{'test_id' => 'foo'}, {'test_id' => 'bar'}])
130
110
  end
131
111
  end
132
112
 
133
- it 'should decode plain keys for all messages in the batch' do
134
- consumer_class = Class.new(described_class) do
135
- schema 'MySchema'
136
- namespace 'com.my-namespace'
137
- key_config plain: true
138
- end
139
- stub_const('ConsumerTest::MyBatchConsumer', consumer_class)
140
-
141
- test_consume_batch('my_batch_consume_topic', batch, keys: [1, 2]) do |_received, metadata|
142
- expect(metadata[:keys]).to eq([1, 2])
113
+ context 'with plain keys' do
114
+ let(:key_config) { { plain: true } }
115
+ it 'should decode plain keys for all messages in the batch' do
116
+ test_consume_batch('my-topic', batch, keys: [1, 2]) do |_received, metadata|
117
+ expect(metadata[:keys]).to eq([1, 2])
118
+ end
143
119
  end
144
120
  end
145
121
  end
146
122
 
147
123
  describe 'timestamps' do
124
+ let(:schema) { 'MySchemaWithDateTimes' }
125
+ let(:key_config) { { none: true } }
148
126
  before(:each) do
149
- # :nodoc:
150
- consumer_class = Class.new(described_class) do
151
- schema 'MySchemaWithDateTimes'
152
- namespace 'com.my-namespace'
153
- key_config plain: true
154
-
155
- # :nodoc:
156
- def consume_batch(_payloads, _metadata)
157
- raise 'This should not be called unless call_original is set'
158
- end
159
- end
160
- stub_const('ConsumerTest::MyBatchConsumer', consumer_class)
161
127
  allow(Deimos.config.metrics).to receive(:histogram)
162
128
  end
163
129
 
@@ -202,45 +168,36 @@ module ConsumerTest
202
168
  end
203
169
 
204
170
  it 'should consume a batch' do
205
- expect(Deimos.config.metrics).
206
- to receive(:histogram).with('handler',
207
- a_kind_of(Numeric),
208
- tags: %w(time:time_delayed topic:my-topic)).twice
171
+ # expect(Deimos.config.metrics).
172
+ # to receive(:histogram).with('handler',
173
+ # a_kind_of(Numeric),
174
+ # tags: %w(time:time_delayed topic:my-topic)).twice
209
175
 
210
- test_consume_batch('my_batch_consume_topic', batch_with_time) do |received, _metadata|
211
- expect(received).to eq(batch_with_time)
176
+ test_consume_batch('my-topic', batch_with_time) do
177
+ expect(messages.payloads).to eq(batch_with_time)
212
178
  end
213
179
  end
214
180
 
215
181
  it 'should fail nicely and ignore timestamps with the wrong format' do
216
182
  batch = invalid_times.concat(batch_with_time)
217
183
 
218
- expect(Deimos.config.metrics).
219
- to receive(:histogram).with('handler',
220
- a_kind_of(Numeric),
221
- tags: %w(time:time_delayed topic:my-topic)).twice
184
+ # expect(Deimos.config.metrics).
185
+ # to receive(:histogram).with('handler',
186
+ # a_kind_of(Numeric),
187
+ # tags: %w(time:time_delayed topic:my-topic)).twice
222
188
 
223
- test_consume_batch('my_batch_consume_topic', batch) do |received, _metadata|
224
- expect(received).to eq(batch)
189
+ test_consume_batch('my-topic', batch) do
190
+ expect(messages.payloads).to eq(batch)
225
191
  end
226
192
  end
227
193
  end
228
194
 
229
195
  describe 'logging' do
196
+ let(:schema) { 'MySchemaWithUniqueId' }
197
+ let(:key_config) { { plain: true } }
230
198
  before(:each) do
231
- # :nodoc:
232
- consumer_class = Class.new(described_class) do
233
- schema 'MySchemaWithUniqueId'
234
- namespace 'com.my-namespace'
235
- key_config plain: true
236
-
237
- # :nodoc:
238
- def consume_batch(_payloads, _metadata)
239
- raise 'This should not be called unless call_original is set'
240
- end
241
- end
242
- stub_const('ConsumerTest::MyBatchConsumer', consumer_class)
243
199
  allow(Deimos.config.metrics).to receive(:histogram)
200
+ set_karafka_config(:payload_log, :keys)
244
201
  end
245
202
 
246
203
  it 'should log message identifiers' do
@@ -251,20 +208,13 @@ module ConsumerTest
251
208
  'timestamp' => 2.minutes.ago.to_s, 'message_id' => 'two' }
252
209
  ]
253
210
 
254
- allow(Deimos.config.logger).
255
- to receive(:info)
211
+ allow(Deimos::Logging).to receive(:log_info)
256
212
 
257
- expect(Deimos.config.logger).
258
- to receive(:info).
259
- with(hash_including(
260
- message_ids: [
261
- { key: 1, message_id: 'one' },
262
- { key: 2, message_id: 'two' }
263
- ]
264
- )).
265
- twice
213
+ expect(Deimos::Logging).
214
+ to receive(:log_info).
215
+ with(hash_including(payload_keys: ["1", "2"]))
266
216
 
267
- test_consume_batch('my_batch_consume_topic', batch_with_message_id, keys: [1, 2])
217
+ test_consume_batch('my-topic', batch_with_message_id, keys: [1, 2])
268
218
  end
269
219
  end
270
220
  end
@@ -4,33 +4,44 @@
4
4
  # rubocop:disable Metrics/ModuleLength
5
5
  module ConsumerTest
6
6
  describe Deimos::Consumer, 'Message Consumer' do
7
+ let(:use_schema_classes) { false }
8
+ let(:reraise_errors) { false }
7
9
  prepend_before(:each) do
8
10
  # :nodoc:
9
11
  consumer_class = Class.new(described_class) do
10
- schema 'MySchema'
11
- namespace 'com.my-namespace'
12
- key_config field: 'test_id'
13
12
 
14
13
  # :nodoc:
15
- def fatal_error?(_exception, payload, _metadata)
16
- payload.to_s == 'fatal'
14
+ def fatal_error?(_exception, messages)
15
+ messages.payloads.first&.dig(:test_id) == ['fatal']
17
16
  end
18
17
 
19
18
  # :nodoc:
20
- def consume(_payload, _metadata)
21
- raise 'This should not be called unless call_original is set'
19
+ def consume_message(message)
20
+ message.payload
22
21
  end
23
22
  end
24
23
  stub_const('ConsumerTest::MyConsumer', consumer_class)
24
+ route_usc = use_schema_classes
25
+ route_rre = reraise_errors
26
+ Karafka::App.routes.redraw do
27
+ topic 'my_consume_topic' do
28
+ schema 'MySchema'
29
+ namespace 'com.my-namespace'
30
+ key_config field: 'test_id'
31
+ consumer consumer_class
32
+ use_schema_classes route_usc
33
+ reraise_errors route_rre
34
+ end
35
+ end
25
36
  end
26
37
 
27
38
  describe 'consume' do
28
39
  SCHEMA_CLASS_SETTINGS.each do |setting, use_schema_classes|
40
+ let(:use_schema_classes) { use_schema_classes }
29
41
  context "with Schema Class consumption #{setting}" do
30
42
 
31
43
  before(:each) do
32
44
  Deimos.configure do |config|
33
- config.schema.use_schema_classes = use_schema_classes
34
45
  config.schema.use_full_namespace = true
35
46
  end
36
47
  end
@@ -45,26 +56,9 @@ module ConsumerTest
45
56
  end
46
57
 
47
58
  it 'should consume a nil message' do
48
- test_consume_message(MyConsumer, nil) do |payload, _metadata|
49
- expect(payload).to be_nil
50
- end
51
- end
52
-
53
- it 'should consume a message idempotently' do
54
- # testing for a crash and re-consuming the same message/metadata
55
- key = { 'test_id' => 'foo' }
56
- test_metadata = { key: key }
57
- allow_any_instance_of(MyConsumer).to(receive(:decode_key)) do |_instance, k|
58
- k['test_id']
59
+ test_consume_message(MyConsumer, nil, key: 'foo') do
60
+ expect(messages).to be_empty
59
61
  end
60
- MyConsumer.new.around_consume({ 'test_id' => 'foo',
61
- 'some_int' => 123 }, test_metadata) do |_payload, metadata|
62
- expect(metadata[:key]).to eq('foo')
63
- end
64
- MyConsumer.new.around_consume({ 'test_id' => 'foo',
65
- 'some_int' => 123 }, test_metadata) do |_payload, metadata|
66
- expect(metadata[:key]).to eq('foo')
67
- end
68
62
  end
69
63
 
70
64
  it 'should consume a message on a topic' do
@@ -77,83 +71,82 @@ module ConsumerTest
77
71
  end
78
72
 
79
73
  it 'should fail on invalid message' do
80
- test_consume_invalid_message(MyConsumer, { 'invalid' => 'key' })
74
+ expect { test_consume_message(MyConsumer, { 'invalid' => 'key' }) }.
75
+ to raise_error(Avro::SchemaValidator::ValidationError)
81
76
  end
82
77
 
83
78
  it 'should fail if reraise is false but fatal_error is true' do
84
- Deimos.configure { |config| config.consumers.reraise_errors = false }
85
- test_consume_invalid_message(MyConsumer, 'fatal')
79
+ expect { test_consume_message(MyConsumer, {test_id: 'fatal'}) }.
80
+ to raise_error(Avro::SchemaValidator::ValidationError)
86
81
  end
87
82
 
88
83
  it 'should fail if fatal_error is true globally' do
89
- Deimos.configure do |config|
90
- config.consumers.fatal_error = proc { true }
91
- config.consumers.reraise_errors = false
92
- end
93
- test_consume_invalid_message(MyConsumer, { 'invalid' => 'key' })
84
+ set_karafka_config(:fatal_error, proc { true })
85
+ expect { test_consume_message(MyConsumer, { 'invalid' => 'key' }) }.
86
+ to raise_error(Avro::SchemaValidator::ValidationError)
94
87
  end
95
88
 
96
89
  it 'should fail on message with extra fields' do
97
- test_consume_invalid_message(MyConsumer,
90
+ allow_any_instance_of(Deimos::SchemaBackends::AvroValidation).
91
+ to receive(:coerce) { |_, m| m.with_indifferent_access }
92
+ expect { test_consume_message(MyConsumer,
98
93
  { 'test_id' => 'foo',
99
94
  'some_int' => 123,
100
- 'extra_field' => 'field name' })
95
+ 'extra_field' => 'field name' }) }.
96
+ to raise_error(Avro::SchemaValidator::ValidationError)
101
97
  end
102
98
 
103
99
  it 'should not fail when before_consume fails without reraising errors' do
104
- Deimos.configure { |config| config.consumers.reraise_errors = false }
100
+ set_karafka_config(:reraise_errors, false)
105
101
  expect {
106
102
  test_consume_message(
107
103
  MyConsumer,
108
104
  { 'test_id' => 'foo',
109
- 'some_int' => 123 },
110
- skip_expectation: true
111
- ) { raise 'OH NOES' }
105
+ 'some_int' => 123 }) { raise 'OH NOES' }
112
106
  }.not_to raise_error
113
107
  end
114
108
 
115
109
  it 'should not fail when consume fails without reraising errors' do
116
- Deimos.configure { |config| config.consumers.reraise_errors = false }
110
+ set_karafka_config(:reraise_errors, false)
111
+ allow(Deimos::ProducerMiddleware).to receive(:call) { |m| m[:payload] = m[:payload].to_json; m }
117
112
  expect {
118
113
  test_consume_message(
119
114
  MyConsumer,
120
- { 'invalid' => 'key' },
121
- skip_expectation: true
122
- )
115
+ { 'invalid' => 'key' })
123
116
  }.not_to raise_error
124
117
  end
125
-
126
- it 'should call original' do
127
- expect {
128
- test_consume_message(MyConsumer,
129
- { 'test_id' => 'foo', 'some_int' => 123 },
130
- call_original: true)
131
- }.to raise_error('This should not be called unless call_original is set')
132
- end
133
118
  end
134
119
  end
135
120
 
136
121
  context 'with overriden schema classes' do
137
122
 
138
123
  before(:each) do
124
+ set_karafka_config(:use_schema_classes, true)
139
125
  Deimos.configure do |config|
140
- config.schema.use_schema_classes = true
141
126
  config.schema.use_full_namespace = true
142
127
  end
143
128
  end
144
129
 
145
130
  prepend_before(:each) do
146
131
  consumer_class = Class.new(described_class) do
147
- schema 'MyUpdatedSchema'
148
- namespace 'com.my-namespace'
149
- key_config field: 'test_id'
150
-
151
132
  # :nodoc:
152
- def consume(_payload, _metadata)
153
- raise 'This should not be called unless call_original is set'
133
+ def consume_message(message)
134
+ message.payload
154
135
  end
155
136
  end
156
137
  stub_const('ConsumerTest::MyConsumer', consumer_class)
138
+ Deimos.config.schema.use_schema_classes = true
139
+ Karafka::App.routes.redraw do
140
+ topic 'my_consume_topic' do
141
+ schema 'MyUpdatedSchema'
142
+ namespace 'com.my-namespace'
143
+ key_config field: 'test_id'
144
+ consumer consumer_class
145
+ end
146
+ end
147
+ end
148
+ after(:each) do
149
+ Karafka::App.routes.clear
157
150
  end
158
151
 
159
152
  it 'should consume messages' do
@@ -169,93 +162,6 @@ module ConsumerTest
169
162
  end
170
163
  end
171
164
 
172
- describe 'decode_key' do
173
-
174
- it 'should use the key field in the value if set' do
175
- # actual decoding is disabled in test
176
- expect(MyConsumer.new.decode_key('test_id' => '123')).to eq('123')
177
- expect { MyConsumer.new.decode_key(123) }.to raise_error(NoMethodError)
178
- end
179
-
180
- it 'should use the key schema if set' do
181
- consumer_class = Class.new(described_class) do
182
- schema 'MySchema'
183
- namespace 'com.my-namespace'
184
- key_config schema: 'MySchema_key'
185
- end
186
- stub_const('ConsumerTest::MySchemaConsumer', consumer_class)
187
- expect(MyConsumer.new.decode_key('test_id' => '123')).to eq('123')
188
- expect { MyConsumer.new.decode_key(123) }.to raise_error(NoMethodError)
189
- end
190
-
191
- it 'should not decode if plain is set' do
192
- consumer_class = Class.new(described_class) do
193
- schema 'MySchema'
194
- namespace 'com.my-namespace'
195
- key_config plain: true
196
- end
197
- stub_const('ConsumerTest::MyNonEncodedConsumer', consumer_class)
198
- expect(MyNonEncodedConsumer.new.decode_key('123')).to eq('123')
199
- end
200
-
201
- it 'should error with nothing set' do
202
- consumer_class = Class.new(described_class) do
203
- schema 'MySchema'
204
- namespace 'com.my-namespace'
205
- end
206
- stub_const('ConsumerTest::MyErrorConsumer', consumer_class)
207
- expect { MyErrorConsumer.new.decode_key('123') }.
208
- to raise_error('No key config given - if you are not decoding keys, please use `key_config plain: true`')
209
- end
210
-
211
- end
212
-
213
- describe 'timestamps' do
214
- before(:each) do
215
- # :nodoc:
216
- consumer_class = Class.new(described_class) do
217
- schema 'MySchemaWithDateTimes'
218
- namespace 'com.my-namespace'
219
- key_config plain: true
220
-
221
- # :nodoc:
222
- def consume(_payload, _metadata)
223
- raise 'This should not be called unless call_original is set'
224
- end
225
- end
226
- stub_const('ConsumerTest::MyConsumer', consumer_class)
227
- end
228
-
229
- it 'should consume a message' do
230
- expect(Deimos.config.metrics).to receive(:histogram).twice
231
- test_consume_message('my_consume_topic',
232
- { 'test_id' => 'foo',
233
- 'some_int' => 123,
234
- 'updated_at' => Time.now.to_i,
235
- 'timestamp' => 2.minutes.ago.to_s }) do |payload, _metadata|
236
- expect(payload['test_id']).to eq('foo')
237
- end
238
- end
239
-
240
- it 'should fail nicely when timestamp wrong format' do
241
- expect(Deimos.config.metrics).to receive(:histogram).twice
242
- test_consume_message('my_consume_topic',
243
- { 'test_id' => 'foo',
244
- 'some_int' => 123,
245
- 'updated_at' => Time.now.to_i,
246
- 'timestamp' => 'dffdf' }) do |payload, _metadata|
247
- expect(payload['test_id']).to eq('foo')
248
- end
249
- test_consume_message('my_consume_topic',
250
- { 'test_id' => 'foo',
251
- 'some_int' => 123,
252
- 'updated_at' => Time.now.to_i,
253
- 'timestamp' => '' }) do |payload, _metadata|
254
- expect(payload['test_id']).to eq('foo')
255
- end
256
- end
257
-
258
- end
259
165
  end
260
166
  end
261
167
  # rubocop:enable Metrics/ModuleLength