deimos-ruby 2.2.0.pre.beta5 → 2.2.1
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/.rubocop.yml +33 -30
- data/CHANGELOG.md +8 -0
- data/Gemfile +0 -6
- data/deimos-ruby.gemspec +15 -10
- data/karafka.rb +7 -4
- data/lib/deimos/active_record_consume/batch_consumption.rb +7 -7
- data/lib/deimos/active_record_consume/batch_record.rb +2 -2
- data/lib/deimos/active_record_consume/message_consumption.rb +6 -5
- data/lib/deimos/active_record_consume/schema_model_converter.rb +2 -2
- data/lib/deimos/active_record_consumer.rb +1 -0
- data/lib/deimos/active_record_producer.rb +4 -2
- data/lib/deimos/backends/base.rb +1 -3
- data/lib/deimos/backends/outbox.rb +1 -1
- data/lib/deimos/config/configuration.rb +88 -75
- data/lib/deimos/consume/batch_consumption.rb +7 -5
- data/lib/deimos/consume/message_consumption.rb +5 -3
- data/lib/deimos/ext/consumer_route.rb +3 -3
- data/lib/deimos/ext/producer_metrics_listener.rb +2 -2
- data/lib/deimos/ext/producer_middleware.rb +19 -15
- data/lib/deimos/ext/producer_route.rb +3 -1
- data/lib/deimos/ext/routing_defaults.rb +9 -7
- data/lib/deimos/ext/schema_route.rb +22 -15
- data/lib/deimos/kafka_message.rb +1 -1
- data/lib/deimos/kafka_source.rb +36 -31
- data/lib/deimos/kafka_topic_info.rb +1 -1
- data/lib/deimos/logging.rb +20 -19
- data/lib/deimos/message.rb +1 -1
- data/lib/deimos/metrics/minimal_datadog_listener.rb +19 -6
- data/lib/deimos/metrics/provider.rb +4 -4
- data/lib/deimos/producer.rb +3 -1
- data/lib/deimos/railtie.rb +1 -1
- data/lib/deimos/schema_backends/avro_base.rb +1 -1
- data/lib/deimos/schema_backends/avro_schema_coercer.rb +46 -27
- data/lib/deimos/schema_backends/avro_schema_registry.rb +8 -8
- data/lib/deimos/schema_backends/base.rb +9 -9
- data/lib/deimos/schema_backends/mock.rb +4 -0
- data/lib/deimos/schema_backends/plain.rb +1 -1
- data/lib/deimos/schema_backends/proto_base.rb +7 -5
- data/lib/deimos/schema_backends/proto_local.rb +0 -2
- data/lib/deimos/schema_backends/proto_schema_registry.rb +0 -2
- data/lib/deimos/schema_class/base.rb +1 -1
- data/lib/deimos/schema_class/record.rb +3 -3
- data/lib/deimos/test_helpers.rb +31 -26
- data/lib/deimos/tracing/provider.rb +5 -5
- data/lib/deimos/transcoder.rb +6 -2
- data/lib/deimos/utils/db_poller/base.rb +3 -3
- data/lib/deimos/utils/deadlock_retry.rb +2 -2
- data/lib/deimos/utils/outbox_producer.rb +14 -14
- data/lib/deimos/version.rb +1 -1
- data/lib/deimos.rb +4 -4
- data/lib/generators/deimos/active_record_generator.rb +2 -1
- data/lib/generators/deimos/db_poller_generator.rb +1 -0
- data/lib/generators/deimos/outbox_backend_generator.rb +1 -0
- data/lib/generators/deimos/schema_class_generator.rb +3 -2
- data/lib/generators/deimos/v2_generator.rb +184 -155
- data/spec/active_record_batch_consumer_association_spec.rb +6 -2
- data/spec/active_record_batch_consumer_spec.rb +83 -106
- data/spec/active_record_consume/batch_consumption_spec.rb +27 -28
- data/spec/active_record_consume/batch_slicer_spec.rb +4 -12
- data/spec/active_record_consume/mass_updater_spec.rb +42 -46
- data/spec/active_record_consume/schema_model_converter_spec.rb +1 -1
- data/spec/active_record_consumer_spec.rb +7 -5
- data/spec/active_record_producer_spec.rb +83 -73
- data/spec/backends/outbox_spec.rb +1 -1
- data/spec/batch_consumer_spec.rb +20 -20
- data/spec/consumer_spec.rb +23 -12
- data/spec/gen/sample/v1/sample_pb.rb +3 -3
- data/spec/generators/active_record_generator_spec.rb +5 -5
- data/spec/generators/schema_class/my_schema_with_circular_reference_spec.rb +2 -1
- data/spec/generators/schema_class/my_schema_with_complex_types_spec.rb +9 -2
- data/spec/generators/schema_class_generator_spec.rb +5 -5
- data/spec/kafka_source_spec.rb +13 -6
- data/spec/kafka_topic_info_spec.rb +7 -7
- data/spec/karafka/karafka.rb +6 -5
- data/spec/karafka_config/karafka_spec.rb +22 -19
- data/spec/logging_spec.rb +2 -0
- data/spec/producer_spec.rb +25 -20
- data/spec/schema_backends/avro_base_shared.rb +8 -8
- data/spec/schema_backends/avro_local_spec.rb +5 -6
- data/spec/schema_backends/avro_schema_registry_spec.rb +5 -6
- data/spec/schema_backends/proto_schema_registry_spec.rb +9 -12
- data/spec/schemas/my_namespace/generated.rb +1 -2
- data/spec/schemas/my_namespace/my_schema_with_complex_type.rb +5 -8
- data/spec/schemas/my_namespace/my_schema_with_union_type.rb +22 -23
- data/spec/spec_helper.rb +13 -17
- data/spec/utils/db_poller_spec.rb +5 -5
- data/spec/utils/deadlock_retry_spec.rb +1 -4
- data/spec/utils/outbox_producer_spec.rb +36 -24
- metadata +79 -158
- data/.ruby-version +0 -1
data/spec/kafka_source_spec.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'activerecord-import'
|
|
|
5
5
|
# Wrap in a module so our classes don't leak out afterwards
|
|
6
6
|
module KafkaSourceSpec
|
|
7
7
|
RSpec.describe Deimos::KafkaSource do
|
|
8
|
+
# rubocop:disable Lint/ConstantDefinitionInBlock
|
|
8
9
|
before(:all) do
|
|
9
10
|
ActiveRecord::Base.connection.create_table(:widgets, force: true) do |t|
|
|
10
11
|
t.integer(:widget_id)
|
|
@@ -40,8 +41,8 @@ module KafkaSourceSpec
|
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
Widget.reset_column_information
|
|
43
|
-
|
|
44
44
|
end
|
|
45
|
+
# rubocop:enable Lint/ConstantDefinitionInBlock
|
|
45
46
|
|
|
46
47
|
after(:all) do
|
|
47
48
|
ActiveRecord::Base.connection.drop_table(:widgets)
|
|
@@ -111,22 +112,24 @@ module KafkaSourceSpec
|
|
|
111
112
|
expect('my-topic-the-second').to have_sent(nil, widget.id)
|
|
112
113
|
end
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
describe 'multi-producer model using two different key fields' do
|
|
115
116
|
before(:each) do
|
|
116
|
-
|
|
117
|
+
klass = Class.new(ActiveRecord::Base) do
|
|
117
118
|
include Deimos::KafkaSource
|
|
119
|
+
|
|
118
120
|
self.table_name = 'widgets'
|
|
119
121
|
|
|
120
122
|
def self.kafka_producers
|
|
121
123
|
[WidgetProducer, WidgetStringKeyProducer]
|
|
122
124
|
end
|
|
123
125
|
end
|
|
126
|
+
stub_const('MultiKeyWidget', klass)
|
|
124
127
|
|
|
125
|
-
|
|
128
|
+
klass = Class.new(Deimos::ActiveRecordProducer) do
|
|
126
129
|
class << self
|
|
127
130
|
|
|
128
131
|
def generate_payload(attributes, record)
|
|
129
|
-
payload = super
|
|
132
|
+
payload = super
|
|
130
133
|
payload.merge('id' => record.model_id)
|
|
131
134
|
end
|
|
132
135
|
|
|
@@ -135,6 +138,7 @@ module KafkaSourceSpec
|
|
|
135
138
|
end
|
|
136
139
|
end
|
|
137
140
|
end
|
|
141
|
+
stub_const('WidgetStringKeyProducer', klass)
|
|
138
142
|
|
|
139
143
|
Karafka::App.routes.redraw do
|
|
140
144
|
topic 'my-topic' do
|
|
@@ -365,8 +369,9 @@ module KafkaSourceSpec
|
|
|
365
369
|
before(:each) do
|
|
366
370
|
# Dummy class we can include the mixin in. Has a backing table created
|
|
367
371
|
# earlier and has the import hook disabled
|
|
368
|
-
|
|
372
|
+
klass = Class.new(ActiveRecord::Base) do
|
|
369
373
|
include Deimos::KafkaSource
|
|
374
|
+
|
|
370
375
|
self.table_name = 'widgets'
|
|
371
376
|
|
|
372
377
|
# :nodoc:
|
|
@@ -385,6 +390,7 @@ module KafkaSourceSpec
|
|
|
385
390
|
end
|
|
386
391
|
end
|
|
387
392
|
|
|
393
|
+
stub_const('WidgetNoImportHook', klass)
|
|
388
394
|
WidgetNoImportHook.reset_column_information
|
|
389
395
|
end
|
|
390
396
|
|
|
@@ -451,6 +457,7 @@ module KafkaSourceSpec
|
|
|
451
457
|
# earlier and has the import hook disabled
|
|
452
458
|
buggy_class = Class.new(ActiveRecord::Base) do
|
|
453
459
|
include Deimos::KafkaSource
|
|
460
|
+
|
|
454
461
|
self.table_name = 'widgets'
|
|
455
462
|
|
|
456
463
|
# :nodoc:
|
|
@@ -33,7 +33,7 @@ each_db_config(Deimos::KafkaTopicInfo) do
|
|
|
33
33
|
locked_at: nil, error: true)
|
|
34
34
|
expect(described_class.lock('my-topic', 'abc')).to be_falsey
|
|
35
35
|
expect(described_class.count).to eq(1)
|
|
36
|
-
expect(described_class.first.locked_by).to
|
|
36
|
+
expect(described_class.first.locked_by).to be_nil
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
specify '#clear_lock' do
|
|
@@ -47,15 +47,15 @@ each_db_config(Deimos::KafkaTopicInfo) do
|
|
|
47
47
|
Deimos::KafkaTopicInfo.clear_lock('my-topic', 'abc')
|
|
48
48
|
expect(Deimos::KafkaTopicInfo.count).to eq(2)
|
|
49
49
|
record = Deimos::KafkaTopicInfo.first
|
|
50
|
-
expect(record.locked_by).to
|
|
51
|
-
expect(record.locked_at).to
|
|
52
|
-
expect(record.error).to
|
|
50
|
+
expect(record.locked_by).to be_nil
|
|
51
|
+
expect(record.locked_at).to be_nil
|
|
52
|
+
expect(record.error).to be(false)
|
|
53
53
|
expect(record.retries).to eq(0)
|
|
54
54
|
expect(record.last_processed_at.in_time_zone.to_s).to eq(Time.zone.now.to_s)
|
|
55
55
|
record = Deimos::KafkaTopicInfo.last
|
|
56
|
-
expect(record.locked_by).not_to
|
|
57
|
-
expect(record.locked_at).not_to
|
|
58
|
-
expect(record.error).not_to
|
|
56
|
+
expect(record.locked_by).not_to be_nil
|
|
57
|
+
expect(record.locked_at).not_to be_nil
|
|
58
|
+
expect(record.error).not_to be(false)
|
|
59
59
|
expect(record.retries).not_to eq(0)
|
|
60
60
|
expect(record.last_processed_at.in_time_zone.to_s).to eq(20.seconds.ago.to_s)
|
|
61
61
|
end
|
data/spec/karafka/karafka.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
class KarafkaApp < Karafka::App
|
|
3
4
|
setup do |config|
|
|
4
5
|
config.kafka = { 'bootstrap.servers': '127.0.0.1:9092' }
|
|
@@ -52,11 +53,11 @@ class KarafkaApp < Karafka::App
|
|
|
52
53
|
# You need to define the topic per each queue name you use
|
|
53
54
|
# active_job_topic :default
|
|
54
55
|
# topic :example do
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
# Uncomment this if you want Karafka to manage your topics configuration
|
|
57
|
+
# Managing topics configuration via routing will allow you to ensure config consistency
|
|
58
|
+
# across multiple environments
|
|
59
|
+
#
|
|
60
|
+
# config(partitions: 2, 'cleanup.policy': 'compact')
|
|
60
61
|
# consumer ExampleConsumer
|
|
61
62
|
# end
|
|
62
63
|
end
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Style/GlobalVars
|
|
4
|
+
RSpec.describe Karafka::Routing::Topic do
|
|
2
5
|
before(:each) do
|
|
3
6
|
KarafkaApp.routes.clear
|
|
4
7
|
$found_stuff = nil
|
|
@@ -13,8 +16,7 @@ RSpec.describe 'Karafka configs' do
|
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
let(:producer_class) do
|
|
16
|
-
Class.new(Deimos::Producer)
|
|
17
|
-
end
|
|
19
|
+
Class.new(Deimos::Producer)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
describe 'producers' do
|
|
@@ -31,8 +33,8 @@ RSpec.describe 'Karafka configs' do
|
|
|
31
33
|
key_config(none: true)
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
|
-
producer_class.publish({test_id:
|
|
35
|
-
expect('MyTopic').to have_sent({test_id:
|
|
36
|
+
producer_class.publish({ test_id: 'id1', some_int: 5 })
|
|
37
|
+
expect('MyTopic').to have_sent({ test_id: 'id1', some_int: 5 })
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
it 'should work with key plain' do
|
|
@@ -41,11 +43,11 @@ RSpec.describe 'Karafka configs' do
|
|
|
41
43
|
producer_class MyProducer
|
|
42
44
|
schema 'MySchema'
|
|
43
45
|
namespace 'com.my-namespace'
|
|
44
|
-
key_config({plain: true})
|
|
46
|
+
key_config({ plain: true })
|
|
45
47
|
end
|
|
46
48
|
end
|
|
47
|
-
producer_class.publish({test_id:
|
|
48
|
-
expect('MyTopic').to have_sent({test_id:
|
|
49
|
+
producer_class.publish({ test_id: 'id1', some_int: 5, payload_key: 'key' })
|
|
50
|
+
expect('MyTopic').to have_sent({ test_id: 'id1', some_int: 5 }, 'key')
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
it 'should work with key field' do
|
|
@@ -54,11 +56,11 @@ RSpec.describe 'Karafka configs' do
|
|
|
54
56
|
producer_class MyProducer
|
|
55
57
|
schema 'MySchema'
|
|
56
58
|
namespace 'com.my-namespace'
|
|
57
|
-
key_config({field: :test_id})
|
|
59
|
+
key_config({ field: :test_id })
|
|
58
60
|
end
|
|
59
61
|
end
|
|
60
|
-
producer_class.publish({test_id:
|
|
61
|
-
expect('MyTopic').to have_sent({test_id:
|
|
62
|
+
producer_class.publish({ test_id: 'id1', some_int: 5 })
|
|
63
|
+
expect('MyTopic').to have_sent({ test_id: 'id1', some_int: 5 }, 'id1')
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
it 'should work with key schema' do
|
|
@@ -67,11 +69,11 @@ RSpec.describe 'Karafka configs' do
|
|
|
67
69
|
producer_class MyProducer
|
|
68
70
|
schema 'MySchema'
|
|
69
71
|
namespace 'com.my-namespace'
|
|
70
|
-
key_config({schema: 'MySchema_key'})
|
|
72
|
+
key_config({ schema: 'MySchema_key' })
|
|
71
73
|
end
|
|
72
74
|
end
|
|
73
|
-
producer_class.publish({test_id:
|
|
74
|
-
expect('MyTopic').to have_sent({test_id:
|
|
75
|
+
producer_class.publish({ test_id: 'id1', some_int: 5, payload_key: { test_id: 'id3' } })
|
|
76
|
+
expect('MyTopic').to have_sent({ test_id: 'id1', some_int: 5 }, { test_id: 'id3' })
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
end
|
|
@@ -83,15 +85,16 @@ RSpec.describe 'Karafka configs' do
|
|
|
83
85
|
consumer MyConsumer
|
|
84
86
|
schema 'MySchema'
|
|
85
87
|
namespace 'com.my-namespace'
|
|
86
|
-
key_config({field: :test_id})
|
|
88
|
+
key_config({ field: :test_id })
|
|
87
89
|
end
|
|
88
90
|
end
|
|
89
91
|
|
|
90
|
-
test_consume_message('MyTopic', {test_id:
|
|
91
|
-
expect($found_stuff).to eq({'test_id' =>
|
|
92
|
+
test_consume_message('MyTopic', { test_id: 'id1', some_int: 5 }, key: 'id1')
|
|
93
|
+
expect($found_stuff).to eq({ 'test_id' => 'id1', 'some_int' => 5 })
|
|
92
94
|
$found_stuff = nil
|
|
93
|
-
test_consume_message(MyConsumer, {test_id:
|
|
94
|
-
expect($found_stuff).to eq({'test_id' =>
|
|
95
|
+
test_consume_message(MyConsumer, { test_id: 'id1', some_int: 5 }, key: 'id1')
|
|
96
|
+
expect($found_stuff).to eq({ 'test_id' => 'id1', 'some_int' => 5 })
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
end
|
|
100
|
+
# rubocop:enable Style/GlobalVars
|
data/spec/logging_spec.rb
CHANGED
data/spec/producer_spec.rb
CHANGED
|
@@ -5,10 +5,10 @@ module ProducerTest
|
|
|
5
5
|
describe Deimos::Producer do
|
|
6
6
|
|
|
7
7
|
prepend_before(:each) do
|
|
8
|
-
producer_class = Class.new(
|
|
8
|
+
producer_class = Class.new(described_class)
|
|
9
9
|
stub_const('MyProducer', producer_class)
|
|
10
10
|
|
|
11
|
-
producer_class = Class.new(
|
|
11
|
+
producer_class = Class.new(described_class)
|
|
12
12
|
stub_const('MyProducerWithID', producer_class)
|
|
13
13
|
|
|
14
14
|
producer_class = Class.new(Deimos::Producer) do
|
|
@@ -19,16 +19,16 @@ module ProducerTest
|
|
|
19
19
|
end
|
|
20
20
|
stub_const('MyNonEncodedProducer', producer_class)
|
|
21
21
|
|
|
22
|
-
producer_class = Class.new(
|
|
22
|
+
producer_class = Class.new(described_class)
|
|
23
23
|
stub_const('MyNoKeyProducer', producer_class)
|
|
24
24
|
|
|
25
|
-
producer_class = Class.new(
|
|
25
|
+
producer_class = Class.new(described_class)
|
|
26
26
|
stub_const('MyNestedSchemaProducer', producer_class)
|
|
27
27
|
|
|
28
|
-
producer_class = Class.new(
|
|
28
|
+
producer_class = Class.new(described_class)
|
|
29
29
|
stub_const('MySchemaProducer', producer_class)
|
|
30
30
|
|
|
31
|
-
producer_class = Class.new(
|
|
31
|
+
producer_class = Class.new(described_class)
|
|
32
32
|
stub_const('MyErrorProducer', producer_class)
|
|
33
33
|
|
|
34
34
|
Karafka::App.routes.redraw do
|
|
@@ -84,7 +84,7 @@ module ProducerTest
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
it 'should fail on invalid message' do
|
|
87
|
-
|
|
87
|
+
allow(Deimos::ProducerMiddleware).to receive(:call).and_raise('OH NOES')
|
|
88
88
|
expect { MyProducer.publish({ 'invalid' => 'key', :payload_key => 'key' }) }.
|
|
89
89
|
to raise_error('OH NOES')
|
|
90
90
|
end
|
|
@@ -110,7 +110,7 @@ module ProducerTest
|
|
|
110
110
|
[{ 'test_id' => 'foo', 'some_int' => 123 },
|
|
111
111
|
{ 'test_id' => 'bar', 'some_int' => 124 }]
|
|
112
112
|
)
|
|
113
|
-
expect('my-topic').to have_sent({'test_id' => 'foo', 'some_int' => 123}, 'foo', 'foo')
|
|
113
|
+
expect('my-topic').to have_sent({ 'test_id' => 'foo', 'some_int' => 123 }, 'foo', 'foo')
|
|
114
114
|
expect('your-topic').not_to have_sent('test_id' => 'foo', 'some_int' => 123)
|
|
115
115
|
expect('my-topic').not_to have_sent('test_id' => 'foo2', 'some_int' => 123)
|
|
116
116
|
end
|
|
@@ -277,12 +277,13 @@ module ProducerTest
|
|
|
277
277
|
allow(Karafka.logger).to receive(:info)
|
|
278
278
|
allow(Karafka.logger).to receive(:tagged).and_yield(Karafka.logger)
|
|
279
279
|
end
|
|
280
|
+
|
|
280
281
|
context 'with default / full' do
|
|
281
282
|
it 'should log full payload' do
|
|
282
283
|
MyProducerWithID.publish_list(
|
|
283
284
|
[
|
|
284
285
|
{ 'test_id' => 'foo', 'some_int' => 123, :payload_key => 'key' },
|
|
285
|
-
{ 'test_id' => 'foo2', 'some_int' => 123, :payload_key => 'key2' }
|
|
286
|
+
{ 'test_id' => 'foo2', 'some_int' => 123, :payload_key => 'key2' }
|
|
286
287
|
]
|
|
287
288
|
)
|
|
288
289
|
expect(Karafka.logger).to have_received(:info).with(match_message({
|
|
@@ -303,7 +304,7 @@ module ProducerTest
|
|
|
303
304
|
|
|
304
305
|
context 'with count' do
|
|
305
306
|
it 'should log only count' do
|
|
306
|
-
Deimos.karafka_config_for(topic: 'my-topic-with-id').payload_log
|
|
307
|
+
Deimos.karafka_config_for(topic: 'my-topic-with-id').payload_log(:count)
|
|
307
308
|
MyProducerWithID.publish_list(
|
|
308
309
|
[
|
|
309
310
|
{ 'test_id' => 'foo', 'some_int' => 123, :payload_key => 'key' },
|
|
@@ -320,7 +321,7 @@ module ProducerTest
|
|
|
320
321
|
|
|
321
322
|
context 'with Schema Class payloads' do
|
|
322
323
|
it 'should fail on invalid message with error handler' do
|
|
323
|
-
|
|
324
|
+
allow(Deimos::ProducerMiddleware).to receive(:call).and_raise('OH NOES')
|
|
324
325
|
expect { MyProducer.publish(Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 'invalid')) }.
|
|
325
326
|
to raise_error('OH NOES')
|
|
326
327
|
end
|
|
@@ -332,7 +333,7 @@ module ProducerTest
|
|
|
332
333
|
hash_including({
|
|
333
334
|
payload: { 'test_id' => 'foo', 'some_int' => 123, 'payload_key' => nil },
|
|
334
335
|
topic: 'my-topic',
|
|
335
|
-
partition_key: nil
|
|
336
|
+
partition_key: nil
|
|
336
337
|
}),
|
|
337
338
|
hash_including({
|
|
338
339
|
payload: { 'test_id' => 'bar', 'some_int' => 124, 'payload_key' => nil },
|
|
@@ -364,17 +365,21 @@ module ProducerTest
|
|
|
364
365
|
it 'should encode the key' do
|
|
365
366
|
Deimos.configure { |c| c.producers.topic_prefix = nil }
|
|
366
367
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
expect {
|
|
369
|
+
MyProducer.publish_list(
|
|
370
|
+
[Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123),
|
|
371
|
+
Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124)]
|
|
372
|
+
)
|
|
373
|
+
}.not_to raise_error
|
|
371
374
|
end
|
|
372
375
|
|
|
373
376
|
it 'should encode with a schema' do
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
377
|
+
expect {
|
|
378
|
+
MySchemaProducer.publish_list(
|
|
379
|
+
[Schemas::MyNamespace::MySchema.new(test_id: 'foo', some_int: 123, payload_key: { 'test_id' => 'foo_key' }),
|
|
380
|
+
Schemas::MyNamespace::MySchema.new(test_id: 'bar', some_int: 124, payload_key: { 'test_id' => 'bar_key' })]
|
|
381
|
+
)
|
|
382
|
+
}.not_to raise_error
|
|
378
383
|
end
|
|
379
384
|
|
|
380
385
|
it 'should properly encode and coerce values with a nested record' do
|
|
@@ -62,9 +62,10 @@ RSpec.shared_examples_for('an Avro backend') do
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
specify('#encode_key') do
|
|
65
|
-
|
|
66
|
-
with({ 'test_id' => 1 }, { schema: 'MySchema_key', topic: 'topic' }).and_return('itsme')
|
|
65
|
+
allow(backend).to receive(:encode).and_return('itsme')
|
|
67
66
|
expect(backend.encode_key('test_id', 1, topic: 'topic')).to eq('itsme')
|
|
67
|
+
expect(backend).to have_received(:encode).
|
|
68
|
+
with({ 'test_id' => 1 }, { schema: 'MySchema_key', topic: 'topic' })
|
|
68
69
|
expect(backend.schema_store.find('MySchema_key', 'com.my-namespace').to_avro).
|
|
69
70
|
to eq(
|
|
70
71
|
'doc' => 'Key for com.my-namespace.MySchema - autogenerated by Deimos',
|
|
@@ -78,10 +79,9 @@ RSpec.shared_examples_for('an Avro backend') do
|
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
specify('#decode_key') do
|
|
81
|
-
|
|
82
|
-
with('payload', schema: 'MySchema_key').
|
|
83
|
-
and_return('test_id' => 1)
|
|
82
|
+
allow(backend).to receive(:decode).and_return('test_id' => 1)
|
|
84
83
|
expect(backend.decode_key('payload', 'test_id')).to eq(1)
|
|
84
|
+
expect(backend).to have_received(:decode).with('payload', schema: 'MySchema_key')
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
describe('#validate') do
|
|
@@ -126,8 +126,8 @@ RSpec.shared_examples_for('an Avro backend') do
|
|
|
126
126
|
expect(result['long-field']).to eq(11_111_111_111_111_111_111)
|
|
127
127
|
expect(result['float-field']).to eq(1.0)
|
|
128
128
|
expect(result['double-field']).to eq(2.0)
|
|
129
|
-
expect(result['boolean-field']).to
|
|
130
|
-
expect(result['union-field']).to
|
|
129
|
+
expect(result['boolean-field']).to be(true)
|
|
130
|
+
expect(result['union-field']).to be_nil
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
it 'should coerce strings to numbers' do
|
|
@@ -177,7 +177,7 @@ RSpec.shared_examples_for('an Avro backend') do
|
|
|
177
177
|
|
|
178
178
|
it 'should convert null to false' do
|
|
179
179
|
result = backend.coerce(payload.merge('boolean-field' => nil))
|
|
180
|
-
expect(result['boolean-field']).to
|
|
180
|
+
expect(result['boolean-field']).to be(false)
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
it 'should convert unions' do
|
|
@@ -16,17 +16,16 @@ RSpec.describe Deimos::SchemaBackends::AvroLocal do
|
|
|
16
16
|
|
|
17
17
|
it 'should encode and decode correctly' do
|
|
18
18
|
avro_turf = instance_double(AvroTurf)
|
|
19
|
-
|
|
20
|
-
with(payload, schema_name: 'MySchema', namespace: 'com.my-namespace').
|
|
21
|
-
and_return('encoded-payload')
|
|
22
|
-
expect(avro_turf).to receive(:decode).
|
|
23
|
-
with('encoded-payload', schema_name: 'MySchema', namespace: 'com.my-namespace').
|
|
24
|
-
and_return(payload)
|
|
19
|
+
allow(avro_turf).to receive_messages(encode: 'encoded-payload', decode: payload)
|
|
25
20
|
allow(backend).to receive(:avro_turf).and_return(avro_turf)
|
|
26
21
|
results = backend.encode(payload)
|
|
27
22
|
expect(results).to eq('encoded-payload')
|
|
28
23
|
results = backend.decode(results)
|
|
29
24
|
expect(results).to eq(payload)
|
|
25
|
+
expect(avro_turf).to have_received(:encode).
|
|
26
|
+
with(payload, schema_name: 'MySchema', namespace: 'com.my-namespace')
|
|
27
|
+
expect(avro_turf).to have_received(:decode).
|
|
28
|
+
with('encoded-payload', schema_name: 'MySchema', namespace: 'com.my-namespace')
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
end
|
|
@@ -16,17 +16,16 @@ RSpec.describe Deimos::SchemaBackends::AvroSchemaRegistry do
|
|
|
16
16
|
|
|
17
17
|
it 'should encode and decode correctly' do
|
|
18
18
|
avro_turf = instance_double(AvroTurf::Messaging)
|
|
19
|
-
|
|
20
|
-
with(payload, schema_name: 'MySchema', subject: 'topic').
|
|
21
|
-
and_return('encoded-payload')
|
|
22
|
-
expect(avro_turf).to receive(:decode).
|
|
23
|
-
with('encoded-payload', schema_name: 'MySchema').
|
|
24
|
-
and_return(payload)
|
|
19
|
+
allow(avro_turf).to receive_messages(encode: 'encoded-payload', decode: payload)
|
|
25
20
|
allow(backend).to receive(:avro_turf_messaging).and_return(avro_turf)
|
|
26
21
|
results = backend.encode(payload, topic: 'topic')
|
|
27
22
|
expect(results).to eq('encoded-payload')
|
|
28
23
|
results = backend.decode(results)
|
|
29
24
|
expect(results).to eq(payload)
|
|
25
|
+
expect(avro_turf).to have_received(:encode).
|
|
26
|
+
with(payload, schema_name: 'MySchema', subject: 'topic')
|
|
27
|
+
expect(avro_turf).to have_received(:decode).
|
|
28
|
+
with('encoded-payload', schema_name: 'MySchema')
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
end
|
|
@@ -6,14 +6,14 @@ require_relative "#{__dir__}/../gen/sample/v1/sample_pb"
|
|
|
6
6
|
RSpec.describe Deimos::SchemaBackends::ProtoSchemaRegistry do
|
|
7
7
|
let(:payload) do
|
|
8
8
|
Sample::V1::SampleMessage.new(
|
|
9
|
-
str:
|
|
9
|
+
str: 'string',
|
|
10
10
|
num: 123,
|
|
11
|
-
str_arr: %w
|
|
11
|
+
str_arr: %w(one two),
|
|
12
12
|
flag: true,
|
|
13
13
|
timestamp: Time.utc(2017, 1, 1),
|
|
14
|
-
nested: Sample::V1::NestedMessage.new(nested_str:
|
|
14
|
+
nested: Sample::V1::NestedMessage.new(nested_str: 'string'),
|
|
15
15
|
non_union_nested: Sample::V1::NestedMessage.new(nested_num: 456),
|
|
16
|
-
str_map: {'foo' => 'bar'}
|
|
16
|
+
str_map: { 'foo' => 'bar' }
|
|
17
17
|
)
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -22,29 +22,26 @@ RSpec.describe Deimos::SchemaBackends::ProtoSchemaRegistry do
|
|
|
22
22
|
specify('#encode_key') do
|
|
23
23
|
expect(backend.encode_key(nil, 789)).to eq('789')
|
|
24
24
|
expect(backend.encode_key(nil, 'string')).to eq('string')
|
|
25
|
-
expect(backend.encode_key(nil, {foo: 'bar'})).to eq('{"foo":"bar"}')
|
|
25
|
+
expect(backend.encode_key(nil, { foo: 'bar' })).to eq('{"foo":"bar"}')
|
|
26
26
|
expect(backend.encode_key(:foo, 'bar')).to eq('bar')
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
specify('#decode_key') do
|
|
30
30
|
expect(backend.decode_key('789', nil)).to eq(789)
|
|
31
31
|
expect(backend.decode_key('{"foo":"bar"}', :foo)).to eq('bar')
|
|
32
|
-
expect(backend.decode_key('{"foo":"bar"}', nil)).to eq({
|
|
32
|
+
expect(backend.decode_key('{"foo":"bar"}', nil)).to eq({ 'foo' => 'bar' })
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
it 'should encode and decode correctly' do
|
|
36
36
|
proto_turf = instance_double(ProtoTurf)
|
|
37
|
-
|
|
38
|
-
with(payload, subject: 'topic').
|
|
39
|
-
and_return('encoded-payload')
|
|
40
|
-
expect(proto_turf).to receive(:decode).
|
|
41
|
-
with('encoded-payload').
|
|
42
|
-
and_return(payload)
|
|
37
|
+
allow(proto_turf).to receive_messages(encode: 'encoded-payload', decode: payload)
|
|
43
38
|
allow(described_class).to receive(:proto_turf).and_return(proto_turf)
|
|
44
39
|
results = backend.encode(payload, topic: 'topic')
|
|
45
40
|
expect(results).to eq('encoded-payload')
|
|
46
41
|
results = backend.decode(results)
|
|
47
42
|
expect(results).to eq(payload)
|
|
43
|
+
expect(proto_turf).to have_received(:encode).with(payload, subject: 'topic')
|
|
44
|
+
expect(proto_turf).to have_received(:decode).with('encoded-payload')
|
|
48
45
|
end
|
|
49
46
|
|
|
50
47
|
end
|
|
@@ -44,8 +44,7 @@ module Schemas; module MyNamespace
|
|
|
44
44
|
# @override
|
|
45
45
|
def symbols
|
|
46
46
|
%w(sym1 sym2)
|
|
47
|
-
end
|
|
48
|
-
|
|
47
|
+
end
|
|
49
48
|
|
|
50
49
|
def sym1?
|
|
51
50
|
@value == 'sym1'
|
|
@@ -62,8 +61,7 @@ module Schemas; module MyNamespace
|
|
|
62
61
|
# @override
|
|
63
62
|
def symbols
|
|
64
63
|
%w(sym3 sym4)
|
|
65
|
-
end
|
|
66
|
-
|
|
64
|
+
end
|
|
67
65
|
|
|
68
66
|
def sym3?
|
|
69
67
|
@value == 'sym3'
|
|
@@ -80,8 +78,7 @@ module Schemas; module MyNamespace
|
|
|
80
78
|
# @override
|
|
81
79
|
def symbols
|
|
82
80
|
%w(sym5 sym6)
|
|
83
|
-
end
|
|
84
|
-
|
|
81
|
+
end
|
|
85
82
|
|
|
86
83
|
def sym5?
|
|
87
84
|
@value == 'sym5'
|
|
@@ -175,8 +172,8 @@ module Schemas; module MyNamespace
|
|
|
175
172
|
test_string_array: ["test"],
|
|
176
173
|
test_int_array: [123],
|
|
177
174
|
test_optional_int: 123,
|
|
178
|
-
some_integer_map: {"abc"=>123},
|
|
179
|
-
some_record: {"a_record_field"=>"Test String"},
|
|
175
|
+
some_integer_map: { "abc"=>123 },
|
|
176
|
+
some_record: { "a_record_field"=>"Test String" },
|
|
180
177
|
some_optional_record: nil,
|
|
181
178
|
some_record_array: nil,
|
|
182
179
|
some_record_map: nil,
|