deimos-ruby 1.24.3 → 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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +0 -17
  3. data/.tool-versions +1 -0
  4. data/CHANGELOG.md +1 -1
  5. data/README.md +287 -498
  6. data/deimos-ruby.gemspec +4 -4
  7. data/docs/CONFIGURATION.md +133 -227
  8. data/docs/UPGRADING.md +237 -0
  9. data/lib/deimos/active_record_consume/batch_consumption.rb +28 -29
  10. data/lib/deimos/active_record_consume/message_consumption.rb +15 -21
  11. data/lib/deimos/active_record_consumer.rb +36 -26
  12. data/lib/deimos/active_record_producer.rb +28 -9
  13. data/lib/deimos/backends/base.rb +4 -35
  14. data/lib/deimos/backends/kafka.rb +6 -22
  15. data/lib/deimos/backends/kafka_async.rb +6 -22
  16. data/lib/deimos/backends/{db.rb → outbox.rb} +13 -9
  17. data/lib/deimos/config/configuration.rb +116 -385
  18. data/lib/deimos/consume/batch_consumption.rb +24 -124
  19. data/lib/deimos/consume/message_consumption.rb +36 -63
  20. data/lib/deimos/consumer.rb +16 -75
  21. data/lib/deimos/ext/consumer_route.rb +35 -0
  22. data/lib/deimos/ext/producer_middleware.rb +94 -0
  23. data/lib/deimos/ext/producer_route.rb +22 -0
  24. data/lib/deimos/ext/redraw.rb +29 -0
  25. data/lib/deimos/ext/routing_defaults.rb +72 -0
  26. data/lib/deimos/ext/schema_route.rb +70 -0
  27. data/lib/deimos/kafka_message.rb +2 -2
  28. data/lib/deimos/kafka_source.rb +2 -7
  29. data/lib/deimos/kafka_topic_info.rb +1 -1
  30. data/lib/deimos/logging.rb +71 -0
  31. data/lib/deimos/message.rb +2 -11
  32. data/lib/deimos/metrics/datadog.rb +40 -1
  33. data/lib/deimos/metrics/provider.rb +4 -4
  34. data/lib/deimos/producer.rb +39 -116
  35. data/lib/deimos/railtie.rb +6 -0
  36. data/lib/deimos/schema_backends/avro_base.rb +21 -21
  37. data/lib/deimos/schema_backends/avro_schema_registry.rb +1 -2
  38. data/lib/deimos/schema_backends/avro_validation.rb +2 -2
  39. data/lib/deimos/schema_backends/base.rb +19 -12
  40. data/lib/deimos/schema_backends/mock.rb +6 -1
  41. data/lib/deimos/schema_backends/plain.rb +47 -0
  42. data/lib/deimos/schema_class/base.rb +2 -2
  43. data/lib/deimos/schema_class/enum.rb +1 -1
  44. data/lib/deimos/schema_class/record.rb +2 -2
  45. data/lib/deimos/test_helpers.rb +95 -320
  46. data/lib/deimos/tracing/provider.rb +6 -6
  47. data/lib/deimos/transcoder.rb +88 -0
  48. data/lib/deimos/utils/db_poller/base.rb +16 -14
  49. data/lib/deimos/utils/db_poller/state_based.rb +3 -3
  50. data/lib/deimos/utils/db_poller/time_based.rb +4 -4
  51. data/lib/deimos/utils/db_poller.rb +1 -1
  52. data/lib/deimos/utils/deadlock_retry.rb +1 -1
  53. data/lib/deimos/utils/{db_producer.rb → outbox_producer.rb} +16 -47
  54. data/lib/deimos/utils/schema_class.rb +0 -7
  55. data/lib/deimos/version.rb +1 -1
  56. data/lib/deimos.rb +79 -26
  57. data/lib/generators/deimos/{db_backend_generator.rb → outbox_backend_generator.rb} +4 -4
  58. data/lib/generators/deimos/schema_class_generator.rb +0 -1
  59. data/lib/generators/deimos/v2/templates/karafka.rb.tt +149 -0
  60. data/lib/generators/deimos/v2_generator.rb +193 -0
  61. data/lib/tasks/deimos.rake +5 -7
  62. data/spec/active_record_batch_consumer_association_spec.rb +22 -13
  63. data/spec/active_record_batch_consumer_spec.rb +84 -65
  64. data/spec/active_record_consume/batch_consumption_spec.rb +10 -10
  65. data/spec/active_record_consume/batch_slicer_spec.rb +12 -12
  66. data/spec/active_record_consumer_spec.rb +29 -13
  67. data/spec/active_record_producer_spec.rb +36 -26
  68. data/spec/backends/base_spec.rb +0 -23
  69. data/spec/backends/kafka_async_spec.rb +1 -3
  70. data/spec/backends/kafka_spec.rb +1 -3
  71. data/spec/backends/{db_spec.rb → outbox_spec.rb} +14 -20
  72. data/spec/batch_consumer_spec.rb +66 -116
  73. data/spec/consumer_spec.rb +53 -147
  74. data/spec/deimos_spec.rb +10 -126
  75. data/spec/kafka_source_spec.rb +19 -52
  76. data/spec/karafka/karafka.rb +69 -0
  77. data/spec/karafka_config/karafka_spec.rb +97 -0
  78. data/spec/logging_spec.rb +25 -0
  79. data/spec/message_spec.rb +9 -9
  80. data/spec/producer_spec.rb +112 -254
  81. data/spec/rake_spec.rb +1 -3
  82. data/spec/schema_backends/avro_validation_spec.rb +1 -1
  83. data/spec/schemas/com/my-namespace/MySchemaWithTitle.avsc +22 -0
  84. data/spec/snapshots/consumers-no-nest.snap +49 -0
  85. data/spec/snapshots/consumers.snap +49 -0
  86. data/spec/snapshots/consumers_and_producers-no-nest.snap +49 -0
  87. data/spec/snapshots/consumers_and_producers.snap +49 -0
  88. data/spec/snapshots/consumers_circular-no-nest.snap +49 -0
  89. data/spec/snapshots/consumers_circular.snap +49 -0
  90. data/spec/snapshots/consumers_complex_types-no-nest.snap +49 -0
  91. data/spec/snapshots/consumers_complex_types.snap +49 -0
  92. data/spec/snapshots/consumers_nested-no-nest.snap +49 -0
  93. data/spec/snapshots/consumers_nested.snap +49 -0
  94. data/spec/snapshots/namespace_folders.snap +49 -0
  95. data/spec/snapshots/namespace_map.snap +49 -0
  96. data/spec/snapshots/producers_with_key-no-nest.snap +49 -0
  97. data/spec/snapshots/producers_with_key.snap +49 -0
  98. data/spec/spec_helper.rb +61 -29
  99. data/spec/utils/db_poller_spec.rb +49 -39
  100. data/spec/utils/{db_producer_spec.rb → outbox_producer_spec.rb} +17 -184
  101. metadata +58 -67
  102. data/lib/deimos/batch_consumer.rb +0 -7
  103. data/lib/deimos/config/phobos_config.rb +0 -164
  104. data/lib/deimos/instrumentation.rb +0 -95
  105. data/lib/deimos/monkey_patches/phobos_cli.rb +0 -35
  106. data/lib/deimos/utils/inline_consumer.rb +0 -158
  107. data/lib/deimos/utils/lag_reporter.rb +0 -186
  108. data/lib/deimos/utils/schema_controller_mixin.rb +0 -129
  109. data/spec/config/configuration_spec.rb +0 -329
  110. data/spec/kafka_listener_spec.rb +0 -55
  111. data/spec/phobos.bad_db.yml +0 -73
  112. data/spec/phobos.yml +0 -77
  113. data/spec/utils/inline_consumer_spec.rb +0 -31
  114. data/spec/utils/lag_reporter_spec.rb +0 -76
  115. data/spec/utils/platform_schema_validation_spec.rb +0 -0
  116. data/spec/utils/schema_controller_mixin_spec.rb +0 -84
  117. /data/lib/generators/deimos/{db_backend → outbox_backend}/templates/migration +0 -0
  118. /data/lib/generators/deimos/{db_backend → outbox_backend}/templates/rails3_migration +0 -0
@@ -4,12 +4,12 @@ RSpec.describe Deimos::ActiveRecordConsume::BatchSlicer do
4
4
  describe '#slice' do
5
5
  let(:batch) do
6
6
  [
7
- Deimos::Message.new({ v: 1 }, nil, key: 'C'),
8
- Deimos::Message.new({ v: 123 }, nil, key: 'A'),
9
- Deimos::Message.new({ v: 999 }, nil, key: 'B'),
10
- Deimos::Message.new({ v: 456 }, nil, key: 'A'),
11
- Deimos::Message.new({ v: 2 }, nil, key: 'C'),
12
- Deimos::Message.new({ v: 3 }, nil, key: 'C')
7
+ Deimos::Message.new({ v: 1 }, key: 'C'),
8
+ Deimos::Message.new({ v: 123 }, key: 'A'),
9
+ Deimos::Message.new({ v: 999 }, key: 'B'),
10
+ Deimos::Message.new({ v: 456 }, key: 'A'),
11
+ Deimos::Message.new({ v: 2 }, key: 'C'),
12
+ Deimos::Message.new({ v: 3 }, key: 'C')
13
13
  ]
14
14
  end
15
15
 
@@ -19,16 +19,16 @@ RSpec.describe Deimos::ActiveRecordConsume::BatchSlicer do
19
19
  expect(slices).
20
20
  to match([
21
21
  match_array([
22
- Deimos::Message.new({ v: 1 }, nil, key: 'C'),
23
- Deimos::Message.new({ v: 123 }, nil, key: 'A'),
24
- Deimos::Message.new({ v: 999 }, nil, key: 'B')
22
+ Deimos::Message.new({ v: 1 }, key: 'C'),
23
+ Deimos::Message.new({ v: 123 }, key: 'A'),
24
+ Deimos::Message.new({ v: 999 }, key: 'B')
25
25
  ]),
26
26
  match_array([
27
- Deimos::Message.new({ v: 456 }, nil, key: 'A'),
28
- Deimos::Message.new({ v: 2 }, nil, key: 'C')
27
+ Deimos::Message.new({ v: 456 }, key: 'A'),
28
+ Deimos::Message.new({ v: 2 }, key: 'C')
29
29
  ]),
30
30
  match_array([
31
- Deimos::Message.new({ v: 3 }, nil, key: 'C')
31
+ Deimos::Message.new({ v: 3 }, key: 'C')
32
32
  ])
33
33
  ])
34
34
  end
@@ -33,25 +33,16 @@ module ActiveRecordConsumerTest
33
33
  prepend_before(:each) do
34
34
 
35
35
  consumer_class = Class.new(Deimos::ActiveRecordConsumer) do
36
- schema 'MySchemaWithDateTimes'
37
- namespace 'com.my-namespace'
38
- key_config plain: true
39
36
  record_class Widget
40
37
  end
41
38
  stub_const('MyConsumer', consumer_class)
42
39
 
43
40
  consumer_class = Class.new(Deimos::ActiveRecordConsumer) do
44
- schema 'MySchemaWithDateTimes'
45
- namespace 'com.my-namespace'
46
- key_config schema: 'MySchemaId_key'
47
41
  record_class Widget
48
42
  end
49
43
  stub_const('MyConsumerWithKey', consumer_class)
50
44
 
51
45
  consumer_class = Class.new(Deimos::ActiveRecordConsumer) do
52
- schema 'MySchema'
53
- namespace 'com.my-namespace'
54
- key_config none: true
55
46
  record_class Widget
56
47
 
57
48
  # :nodoc:
@@ -135,14 +126,39 @@ module ActiveRecordConsumerTest
135
126
  end
136
127
  end
137
128
  stub_const('Schemas::MySchemaWithDateTimes', schema_datetime_class)
129
+
130
+ Karafka::App.routes.redraw do
131
+ topic "my-topic" do
132
+ consumer MyConsumer
133
+ schema 'MySchemaWithDateTimes'
134
+ namespace 'com.my-namespace'
135
+ key_config plain: true
136
+ end
137
+ topic "my-topic2" do
138
+ consumer MyConsumerWithKey
139
+ schema 'MySchemaWithDateTimes'
140
+ namespace 'com.my-namespace'
141
+ key_config schema: 'MySchemaId_key'
142
+ end
143
+ topic "my-topic3" do
144
+ consumer MyCustomFetchConsumer
145
+ schema 'MySchema'
146
+ namespace 'com.my-namespace'
147
+ key_config none: true
148
+ end
149
+ end
138
150
  end
139
151
 
140
152
  describe 'consume' do
141
153
  SCHEMA_CLASS_SETTINGS.each do |setting, use_schema_classes|
142
154
  context "with Schema Class consumption #{setting}" do
143
155
  before(:each) do
156
+ Karafka::App.routes.draw do
157
+ defaults do
158
+ use_schema_classes use_schema_classes
159
+ end
160
+ end
144
161
  Deimos.configure do |config|
145
- config.schema.use_schema_classes = use_schema_classes
146
162
  config.schema.use_full_namespace = true
147
163
  end
148
164
  end
@@ -200,7 +216,7 @@ module ActiveRecordConsumerTest
200
216
  test_consume_message(MyCustomFetchConsumer, {
201
217
  test_id: 'id1',
202
218
  some_int: 3
203
- }, call_original: true)
219
+ })
204
220
  expect(widget1.reload.updated_at.in_time_zone).
205
221
  to eq(Time.local(2020, 5, 6, 5, 5, 5))
206
222
  travel_back
@@ -225,13 +241,13 @@ module ActiveRecordConsumerTest
225
241
  test_consume_message(MyCustomFetchConsumer, {
226
242
  test_id: 'id1',
227
243
  some_int: 3
228
- }, call_original: true)
244
+ })
229
245
  expect(widget1.reload.some_int).to eq(3)
230
246
  expect(Widget.count).to eq(1)
231
247
  test_consume_message(MyCustomFetchConsumer, {
232
248
  test_id: 'id2',
233
249
  some_int: 4
234
- }, call_original: true)
250
+ })
235
251
  expect(Widget.count).to eq(2)
236
252
  expect(Widget.find_by_test_id('id1').some_int).to eq(3)
237
253
  expect(Widget.find_by_test_id('id2').some_int).to eq(4)
@@ -5,28 +5,13 @@ describe Deimos::ActiveRecordProducer do
5
5
  include_context 'with widgets'
6
6
 
7
7
  prepend_before(:each) do
8
-
9
- producer_class = Class.new(Deimos::ActiveRecordProducer) do
10
- schema 'MySchema'
11
- namespace 'com.my-namespace'
12
- topic 'my-topic'
13
- key_config none: true
14
- end
8
+ producer_class = Class.new(Deimos::ActiveRecordProducer)
15
9
  stub_const('MyProducer', producer_class)
16
10
 
17
- producer_class = Class.new(Deimos::ActiveRecordProducer) do
18
- schema 'MySchemaWithBooleans'
19
- namespace 'com.my-namespace'
20
- topic 'my-topic-with-boolean'
21
- key_config none: true
22
- end
11
+ producer_class = Class.new(Deimos::ActiveRecordProducer)
23
12
  stub_const('MyBooleanProducer', producer_class)
24
13
 
25
14
  producer_class = Class.new(Deimos::ActiveRecordProducer) do
26
- schema 'MySchemaWithId'
27
- namespace 'com.my-namespace'
28
- topic 'my-topic-with-id'
29
- key_config none: true
30
15
  record_class Widget
31
16
 
32
17
  # :nodoc:
@@ -38,19 +23,11 @@ describe Deimos::ActiveRecordProducer do
38
23
  stub_const('MyProducerWithID', producer_class)
39
24
 
40
25
  producer_class = Class.new(Deimos::ActiveRecordProducer) do
41
- schema 'MySchemaWithUniqueId'
42
- namespace 'com.my-namespace'
43
- topic 'my-topic-with-unique-id'
44
- key_config field: :id
45
26
  record_class Widget
46
27
  end
47
28
  stub_const('MyProducerWithUniqueID', producer_class)
48
29
 
49
30
  producer_class = Class.new(Deimos::ActiveRecordProducer) do
50
- schema 'MySchemaWithUniqueId'
51
- namespace 'com.my-namespace'
52
- topic 'my-topic-with-unique-id'
53
- key_config field: :id
54
31
  record_class Widget
55
32
 
56
33
  # :nodoc:
@@ -63,6 +40,39 @@ describe Deimos::ActiveRecordProducer do
63
40
  end
64
41
 
65
42
  stub_const('MyProducerWithPostProcess', producer_class)
43
+ Karafka::App.routes.redraw do
44
+ topic 'my-topic' do
45
+ schema 'MySchema'
46
+ namespace 'com.my-namespace'
47
+ key_config none: true
48
+ producer_class MyProducer
49
+ end
50
+ topic 'my-topic-with-boolean' do
51
+ producer_class MyBooleanProducer
52
+ schema 'MySchemaWithBooleans'
53
+ namespace 'com.my-namespace'
54
+ key_config none: true
55
+ end
56
+ topic 'my-topic-with-id' do
57
+ schema 'MySchemaWithId'
58
+ namespace 'com.my-namespace'
59
+ key_config none: true
60
+ producer_class MyProducerWithID
61
+ end
62
+ topic 'my-topic-with-unique-id' do
63
+ schema 'MySchemaWithUniqueId'
64
+ namespace 'com.my-namespace'
65
+ key_config field: :id
66
+ producer_class MyProducerWithUniqueID
67
+ end
68
+ topic 'my-topic-with-post-process' do
69
+ schema 'MySchemaWithUniqueId'
70
+ namespace 'com.my-namespace'
71
+ key_config none: true
72
+ producer_class MyProducerWithPostProcess
73
+ end
74
+ end
75
+
66
76
  end
67
77
 
68
78
  describe 'produce' do
@@ -117,7 +127,7 @@ describe Deimos::ActiveRecordProducer do
117
127
  end
118
128
 
119
129
  specify '#watched_attributes' do
120
- expect(MyProducer.watched_attributes).to eq(%w(test_id some_int))
130
+ expect(MyProducer.watched_attributes(nil)).to eq(%w(test_id some_int))
121
131
  end
122
132
 
123
133
  end
@@ -8,27 +8,4 @@ RSpec.describe Deimos::Backends::Base do
8
8
  described_class.publish(producer_class: MyProducer, messages: messages)
9
9
  end
10
10
 
11
- describe 'payload_log method' do
12
- it 'should return whole payload (default behavior)' do
13
- log_message = described_class.send(:log_message, messages)
14
- expect(log_message[:payloads].count).to eq(3)
15
- expect(log_message[:payloads].first[:payload]).to eq({ 'foo' => 1 })
16
- expect(log_message[:payloads].first[:key]).to eq('foo1')
17
- end
18
-
19
- it 'should return only keys of messages' do
20
- Deimos.config.payload_log = :keys
21
- log_message = described_class.send(:log_message, messages)
22
- expect(log_message[:payload_keys].count).to eq(3)
23
- expect(log_message[:payload_keys]).to be_a(Array)
24
- expect(log_message[:payload_keys].first).to eq('foo1')
25
- end
26
-
27
- it 'should return only messages count' do
28
- Deimos.config.payload_log = :count
29
- log_message = described_class.send(:log_message, messages)
30
- expect(log_message[:payloads_count]).to be_a(Integer)
31
- expect(log_message[:payloads_count]).to eq(3)
32
- end
33
- end
34
11
  end
@@ -3,9 +3,7 @@
3
3
  RSpec.describe Deimos::Backends::KafkaAsync do
4
4
  include_context 'with publish_backend'
5
5
  it 'should publish to Kafka asynchronously' do
6
- producer = instance_double(Phobos::Producer::ClassMethods::PublicAPI)
7
- expect(producer).to receive(:async_publish_list).with(messages.map(&:encoded_hash))
8
- expect(described_class).to receive(:producer).and_return(producer)
6
+ expect(Karafka.producer).to receive(:produce_many_async).with(messages)
9
7
  described_class.publish(producer_class: MyProducer, messages: messages)
10
8
  end
11
9
  end
@@ -3,9 +3,7 @@
3
3
  RSpec.describe Deimos::Backends::Kafka do
4
4
  include_context 'with publish_backend'
5
5
  it 'should publish to Kafka synchronously' do
6
- producer = instance_double(Phobos::Producer::ClassMethods::PublicAPI)
7
- expect(producer).to receive(:publish_list).with(messages.map(&:encoded_hash))
8
- expect(described_class).to receive(:producer).and_return(producer)
6
+ expect(Karafka.producer).to receive(:produce_many_sync).with(messages)
9
7
  described_class.publish(producer_class: MyProducer, messages: messages)
10
8
  end
11
9
  end
@@ -1,31 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- each_db_config(Deimos::Backends::Db) do
3
+ each_db_config(Deimos::Backends::Outbox) do
4
4
  include_context 'with publish_backend'
5
5
 
6
6
  it 'should save to the database' do
7
- expect(Deimos.config.metrics).to receive(:increment).with(
8
- 'db_producer.insert',
9
- tags: %w(topic:my-topic),
10
- by: 3
11
- )
7
+ # expect(Deimos.config.metrics).to receive(:increment).with(
8
+ # 'outbox.insert',
9
+ # tags: %w(topic:my-topic),
10
+ # by: 3
11
+ # )
12
12
  described_class.publish(producer_class: MyProducer, messages: messages)
13
13
  records = Deimos::KafkaMessage.all
14
14
  expect(records.size).to eq(3)
15
15
  expect(records[0].attributes.to_h).to include(
16
- 'message' => '{"foo"=>1}',
16
+ 'message' => '{"test_id":"foo1","some_int":1}',
17
17
  'topic' => 'my-topic',
18
- 'key' => 'foo1'
18
+ 'key' => '{"test_id":"foo1"}'
19
19
  )
20
20
  expect(records[1].attributes.to_h).to include(
21
- 'message' => '{"foo"=>2}',
21
+ 'message' => '{"test_id":"foo2","some_int":2}',
22
22
  'topic' => 'my-topic',
23
- 'key' => 'foo2'
23
+ 'key' => '{"test_id":"foo2"}'
24
24
  )
25
25
  expect(records[2].attributes.to_h).to include(
26
- 'message' => '{"foo"=>3}',
26
+ 'message' => '{"test_id":"foo3","some_int":3}',
27
27
  'topic' => 'my-topic',
28
- 'key' => 'foo3'
28
+ 'key' => '{"test_id":"foo3"}'
29
29
  )
30
30
  end
31
31
 
@@ -37,18 +37,12 @@ each_db_config(Deimos::Backends::Db) do
37
37
  end
38
38
 
39
39
  it 'should add to non-keyed messages' do
40
+ orig_messages = messages.deep_dup
40
41
  described_class.publish(producer_class: MyNoKeyProducer,
41
42
  messages: messages)
42
43
  expect(Deimos::KafkaMessage.count).to eq(3)
43
44
  described_class.publish(producer_class: MyNoKeyProducer,
44
- messages: [messages.first])
45
+ messages: [orig_messages.first])
45
46
  expect(Deimos::KafkaMessage.count).to eq(4)
46
47
  end
47
-
48
- it 'should add messages with Hash keys with JSON encoding' do
49
- described_class.publish(producer_class: MyProducer,
50
- messages: [build_message({ foo: 0 }, 'my-topic', { 'test_id' => 0 })])
51
- expect(Deimos::KafkaMessage.count).to eq(1)
52
- expect(Deimos::KafkaMessage.last.partition_key).to eq(%(---\ntest_id: 0\n))
53
- end
54
48
  end
@@ -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