deimos-ruby 1.6.1 → 1.8.0.pre.beta1
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/.circleci/config.yml +9 -0
- data/.rubocop.yml +15 -13
- data/.ruby-version +1 -1
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +87 -80
- data/README.md +139 -15
- data/Rakefile +1 -1
- data/deimos-ruby.gemspec +3 -2
- data/docs/ARCHITECTURE.md +144 -0
- data/docs/CONFIGURATION.md +27 -0
- data/lib/deimos.rb +7 -6
- data/lib/deimos/active_record_consume/batch_consumption.rb +159 -0
- data/lib/deimos/active_record_consume/batch_slicer.rb +27 -0
- data/lib/deimos/active_record_consume/message_consumption.rb +58 -0
- data/lib/deimos/active_record_consume/schema_model_converter.rb +52 -0
- data/lib/deimos/active_record_consumer.rb +33 -75
- data/lib/deimos/active_record_producer.rb +23 -0
- data/lib/deimos/batch_consumer.rb +2 -140
- data/lib/deimos/config/configuration.rb +28 -10
- data/lib/deimos/consume/batch_consumption.rb +148 -0
- data/lib/deimos/consume/message_consumption.rb +93 -0
- data/lib/deimos/consumer.rb +79 -69
- data/lib/deimos/kafka_message.rb +1 -1
- data/lib/deimos/kafka_source.rb +29 -23
- data/lib/deimos/kafka_topic_info.rb +1 -1
- data/lib/deimos/message.rb +6 -1
- data/lib/deimos/metrics/provider.rb +0 -2
- data/lib/deimos/poll_info.rb +9 -0
- data/lib/deimos/tracing/provider.rb +0 -2
- data/lib/deimos/utils/db_poller.rb +149 -0
- data/lib/deimos/utils/db_producer.rb +8 -3
- data/lib/deimos/utils/deadlock_retry.rb +68 -0
- data/lib/deimos/utils/lag_reporter.rb +19 -26
- data/lib/deimos/version.rb +1 -1
- data/lib/generators/deimos/db_poller/templates/migration +11 -0
- data/lib/generators/deimos/db_poller/templates/rails3_migration +16 -0
- data/lib/generators/deimos/db_poller_generator.rb +48 -0
- data/lib/tasks/deimos.rake +7 -0
- data/spec/active_record_batch_consumer_spec.rb +481 -0
- data/spec/active_record_consume/batch_slicer_spec.rb +42 -0
- data/spec/active_record_consume/schema_model_converter_spec.rb +105 -0
- data/spec/active_record_consumer_spec.rb +22 -11
- data/spec/active_record_producer_spec.rb +66 -88
- data/spec/batch_consumer_spec.rb +23 -7
- data/spec/config/configuration_spec.rb +4 -0
- data/spec/consumer_spec.rb +8 -8
- data/spec/deimos_spec.rb +57 -49
- data/spec/handlers/my_batch_consumer.rb +6 -1
- data/spec/handlers/my_consumer.rb +6 -1
- data/spec/kafka_source_spec.rb +53 -0
- data/spec/message_spec.rb +19 -0
- data/spec/producer_spec.rb +3 -3
- data/spec/rake_spec.rb +1 -1
- data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
- data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
- data/spec/spec_helper.rb +61 -6
- data/spec/utils/db_poller_spec.rb +320 -0
- data/spec/utils/deadlock_retry_spec.rb +74 -0
- data/spec/utils/lag_reporter_spec.rb +29 -22
- metadata +61 -20
- data/lib/deimos/base_consumer.rb +0 -104
- data/lib/deimos/utils/executor.rb +0 -124
- data/lib/deimos/utils/platform_schema_validation.rb +0 -0
- data/lib/deimos/utils/signal_handler.rb +0 -68
- data/spec/utils/executor_spec.rb +0 -53
- data/spec/utils/signal_handler_spec.rb +0 -16
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Deimos::ActiveRecordConsume::BatchSlicer do
|
4
|
+
describe '#slice' do
|
5
|
+
let(:batch) do
|
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')
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should slice a batch by key' do
|
17
|
+
slices = described_class.slice(batch)
|
18
|
+
|
19
|
+
expect(slices).
|
20
|
+
to match([
|
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')
|
25
|
+
]),
|
26
|
+
match_array([
|
27
|
+
Deimos::Message.new({ v: 456 }, nil, key: 'A'),
|
28
|
+
Deimos::Message.new({ v: 2 }, nil, key: 'C')
|
29
|
+
]),
|
30
|
+
match_array([
|
31
|
+
Deimos::Message.new({ v: 3 }, nil, key: 'C')
|
32
|
+
])
|
33
|
+
])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should handle empty batches' do
|
37
|
+
slices = described_class.slice([])
|
38
|
+
|
39
|
+
expect(slices).to be_empty
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'deimos/active_record_consume/schema_model_converter'
|
4
|
+
require 'deimos/schema_backends/avro_local'
|
5
|
+
|
6
|
+
# Wrapped in a module to prevent class leakage
|
7
|
+
module SchemaModelConverterTest
|
8
|
+
describe Deimos::ActiveRecordConsume::SchemaModelConverter do
|
9
|
+
# Create ActiveRecord table and model
|
10
|
+
before(:all) do
|
11
|
+
ActiveRecord::Base.connection.create_table(:wibbles, force: true) do |t|
|
12
|
+
t.integer(:wibble_id)
|
13
|
+
t.string(:name)
|
14
|
+
t.integer(:bar)
|
15
|
+
t.datetime(:birthday_int)
|
16
|
+
t.datetime(:birthday_long)
|
17
|
+
t.datetime(:birthday_optional)
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
|
21
|
+
# :nodoc:
|
22
|
+
class Wibble < ActiveRecord::Base
|
23
|
+
end
|
24
|
+
Wibble.reset_column_information
|
25
|
+
end
|
26
|
+
|
27
|
+
after(:all) do
|
28
|
+
ActiveRecord::Base.connection.drop_table(:wibbles)
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:schema) { Deimos::SchemaBackends::AvroLocal.new(schema: 'Wibble', namespace: 'com.my-namespace') }
|
32
|
+
let(:inst) { described_class.new(schema, Wibble) }
|
33
|
+
|
34
|
+
describe '#convert' do
|
35
|
+
it 'should extract attributes from the payload' do
|
36
|
+
payload = { 'id' => 123, 'wibble_id' => 456, 'name' => 'wibble' }
|
37
|
+
|
38
|
+
expect(inst.convert(payload)).to include('id' => 123, 'wibble_id' => 456, 'name' => 'wibble')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should ignore payload fields that don\'t exist' do
|
42
|
+
payload = { 'foo' => 'abc' }
|
43
|
+
|
44
|
+
expect(inst.convert(payload)).not_to include('foo')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should ignore fields in the schema but not in the model' do
|
48
|
+
payload = { 'floop' => 'def' }
|
49
|
+
|
50
|
+
expect(inst.convert(payload)).not_to include('floop')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should ignore model fields not in the schema' do
|
54
|
+
payload = { 'bar' => 'xyz' }
|
55
|
+
|
56
|
+
expect(inst.convert(payload)).not_to include('bar')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should handle nils' do
|
60
|
+
payload = { 'name' => nil }
|
61
|
+
|
62
|
+
expect(inst.convert(payload)['name']).to be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'timestamps' do
|
66
|
+
it 'should ignore AR timestamp fields' do
|
67
|
+
payload = { 'updated_at' => '1234567890', 'created_at' => '2345678901' }
|
68
|
+
|
69
|
+
expect(inst.convert(payload)).not_to include('updated_at', 'created_at')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should parse timestamps' do
|
73
|
+
first = Time.zone.local(2019, 1, 1, 11, 12, 13)
|
74
|
+
second = Time.zone.local(2019, 2, 2, 12, 13, 14)
|
75
|
+
|
76
|
+
payload = { 'birthday_int' => first.to_i, 'birthday_long' => second.to_i }
|
77
|
+
|
78
|
+
expect(inst.convert(payload)).to include('birthday_int' => first, 'birthday_long' => second)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should parse integer-string timestamps' do
|
82
|
+
date = Time.zone.local(2019, 1, 1, 11, 12, 13)
|
83
|
+
|
84
|
+
payload = { 'birthday_int' => '1546359133' }
|
85
|
+
|
86
|
+
expect(inst.convert(payload)).to include('birthday_int' => date)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should ignore other strings for timestamps' do
|
90
|
+
payload = { 'birthday_int' => 'some-other-val' }
|
91
|
+
|
92
|
+
expect(inst.convert(payload)).to include('birthday_int' => 'some-other-val')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should coerce nullable unions' do
|
97
|
+
date = Time.zone.local(2019, 1, 1, 11, 12, 13)
|
98
|
+
|
99
|
+
payload = { 'birthday_optional' => date.to_i }
|
100
|
+
|
101
|
+
expect(inst.convert(payload)).to include('birthday_optional' => date)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'date'
|
4
4
|
|
5
|
-
#
|
6
|
-
module
|
7
|
-
describe Deimos::ActiveRecordConsumer do
|
5
|
+
# Wrapped in a module to prevent class leakage
|
6
|
+
module ActiveRecordConsumerTest
|
7
|
+
describe Deimos::ActiveRecordConsumer, 'Message Consumer' do
|
8
8
|
|
9
9
|
before(:all) do
|
10
10
|
ActiveRecord::Base.connection.create_table(:widgets, force: true) do |t|
|
@@ -22,6 +22,10 @@ module ActiveRecordProducerTest
|
|
22
22
|
Widget.reset_column_information
|
23
23
|
end
|
24
24
|
|
25
|
+
before(:each) do
|
26
|
+
Widget.delete_all
|
27
|
+
end
|
28
|
+
|
25
29
|
after(:all) do
|
26
30
|
ActiveRecord::Base.connection.drop_table(:widgets)
|
27
31
|
end
|
@@ -101,6 +105,21 @@ module ActiveRecordProducerTest
|
|
101
105
|
|
102
106
|
end
|
103
107
|
|
108
|
+
it 'should update only updated_at' do
|
109
|
+
travel_to Time.local(2020, 5, 5, 5, 5, 5)
|
110
|
+
widget1 = Widget.create!(test_id: 'id1', some_int: 3)
|
111
|
+
expect(widget1.updated_at.in_time_zone).to eq(Time.local(2020, 5, 5, 5, 5, 5))
|
112
|
+
|
113
|
+
travel 1.day
|
114
|
+
test_consume_message(MyCustomFetchConsumer, {
|
115
|
+
test_id: 'id1',
|
116
|
+
some_int: 3
|
117
|
+
}, { call_original: true })
|
118
|
+
expect(widget1.reload.updated_at.in_time_zone).
|
119
|
+
to eq(Time.local(2020, 5, 6, 5, 5, 5))
|
120
|
+
travel_back
|
121
|
+
end
|
122
|
+
|
104
123
|
it 'should find widgets by custom logic' do
|
105
124
|
widget1 = Widget.create!(test_id: 'id1')
|
106
125
|
expect(widget1.some_int).to be_nil
|
@@ -118,13 +137,5 @@ module ActiveRecordProducerTest
|
|
118
137
|
expect(Widget.find_by_test_id('id1').some_int).to eq(3)
|
119
138
|
expect(Widget.find_by_test_id('id2').some_int).to eq(4)
|
120
139
|
end
|
121
|
-
|
122
|
-
it 'should coerce int values to datetimes' do
|
123
|
-
column = Widget.columns.find { |c| c.name == 'some_datetime_int' }
|
124
|
-
expect(MyConsumer.new.send(:_coerce_field, column, 1_579_046_400)).to eq('2020-01-14 19:00:00 -0500')
|
125
|
-
expect(MyConsumer.new.send(:_coerce_field, column, '1579046400')).to eq('2020-01-14 19:00:00 -0500')
|
126
|
-
expect(MyConsumer.new.send(:_coerce_field, column, 'some-other-val')).to eq('some-other-val')
|
127
|
-
end
|
128
|
-
|
129
140
|
end
|
130
141
|
end
|
@@ -1,107 +1,85 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
module ActiveRecordProducerTest
|
5
|
-
describe Deimos::ActiveRecordProducer do
|
3
|
+
describe Deimos::ActiveRecordProducer do
|
6
4
|
|
7
|
-
|
8
|
-
ActiveRecord::Base.connection.create_table(:widgets) do |t|
|
9
|
-
t.string(:test_id)
|
10
|
-
t.integer(:some_int)
|
11
|
-
t.boolean(:some_bool)
|
12
|
-
t.timestamps
|
13
|
-
end
|
5
|
+
include_context 'with widgets'
|
14
6
|
|
15
|
-
|
16
|
-
class Widget < ActiveRecord::Base
|
17
|
-
# @return [String]
|
18
|
-
def generated_id
|
19
|
-
'generated_id'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
7
|
+
prepend_before(:each) do
|
23
8
|
|
24
|
-
|
25
|
-
|
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
|
26
14
|
end
|
15
|
+
stub_const('MyProducer', producer_class)
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
stub_const('MyProducer', producer_class)
|
37
|
-
|
38
|
-
producer_class = Class.new(Deimos::ActiveRecordProducer) do
|
39
|
-
schema 'MySchemaWithBooleans'
|
40
|
-
namespace 'com.my-namespace'
|
41
|
-
topic 'my-topic-with-boolean'
|
42
|
-
key_config none: true
|
43
|
-
end
|
44
|
-
stub_const('MyBooleanProducer', producer_class)
|
45
|
-
|
46
|
-
producer_class = Class.new(Deimos::ActiveRecordProducer) do
|
47
|
-
schema 'MySchemaWithId'
|
48
|
-
namespace 'com.my-namespace'
|
49
|
-
topic 'my-topic-with-id'
|
50
|
-
key_config none: true
|
51
|
-
record_class Widget
|
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
|
23
|
+
stub_const('MyBooleanProducer', producer_class)
|
52
24
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
25
|
+
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
|
+
record_class Widget
|
57
31
|
|
32
|
+
# :nodoc:
|
33
|
+
def self.generate_payload(attrs, widget)
|
34
|
+
super.merge(message_id: widget.generated_id)
|
58
35
|
end
|
59
|
-
stub_const('MyProducerWithID', producer_class)
|
60
36
|
|
61
|
-
producer_class = Class.new(Deimos::ActiveRecordProducer) do
|
62
|
-
schema 'MySchemaWithUniqueId'
|
63
|
-
namespace 'com.my-namespace'
|
64
|
-
topic 'my-topic-with-unique-id'
|
65
|
-
key_config field: :id
|
66
|
-
record_class Widget
|
67
|
-
end
|
68
|
-
stub_const('MyProducerWithUniqueID', producer_class)
|
69
37
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
38
|
+
stub_const('MyProducerWithID', producer_class)
|
39
|
+
|
40
|
+
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
|
+
record_class Widget
|
74
46
|
end
|
47
|
+
stub_const('MyProducerWithUniqueID', producer_class)
|
48
|
+
end
|
75
49
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
expect('my-topic').to have_sent(test_id: 'abc', some_int: 4)
|
81
|
-
expect {
|
82
|
-
MyProducer.send_event(Widget.new(test_id: 'abc', some_int: nil))
|
83
|
-
}.to raise_error(Avro::SchemaValidator::ValidationError)
|
84
|
-
|
85
|
-
MyBooleanProducer.send_event(Widget.new(test_id: 'abc', some_bool: nil))
|
86
|
-
MyBooleanProducer.send_event(Widget.new(test_id: 'abc', some_bool: true))
|
87
|
-
expect('my-topic-with-boolean').to have_sent(test_id: 'abc', some_bool: false)
|
88
|
-
expect('my-topic-with-boolean').to have_sent(test_id: 'abc', some_bool: true)
|
89
|
-
end
|
50
|
+
it 'should send events correctly' do
|
51
|
+
MyProducer.send_event(Widget.new(test_id: 'abc', some_int: 3))
|
52
|
+
expect('my-topic').to have_sent(test_id: 'abc', some_int: 3)
|
53
|
+
end
|
90
54
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
55
|
+
it 'should coerce values' do
|
56
|
+
MyProducer.send_event(Widget.new(test_id: 'abc', some_int: '3'))
|
57
|
+
MyProducer.send_event(Widget.new(test_id: 'abc', some_int: 4.5))
|
58
|
+
expect('my-topic').to have_sent(test_id: 'abc', some_int: 3)
|
59
|
+
expect('my-topic').to have_sent(test_id: 'abc', some_int: 4)
|
60
|
+
expect {
|
61
|
+
MyProducer.send_event(Widget.new(test_id: 'abc', some_int: nil))
|
62
|
+
}.to raise_error(Avro::SchemaValidator::ValidationError)
|
63
|
+
|
64
|
+
MyBooleanProducer.send_event(Widget.new(test_id: 'abc', some_bool: nil))
|
65
|
+
MyBooleanProducer.send_event(Widget.new(test_id: 'abc', some_bool: true))
|
66
|
+
expect('my-topic-with-boolean').to have_sent(test_id: 'abc', some_bool: false)
|
67
|
+
expect('my-topic-with-boolean').to have_sent(test_id: 'abc', some_bool: true)
|
68
|
+
end
|
101
69
|
|
102
|
-
|
103
|
-
|
104
|
-
|
70
|
+
it 'should be able to call the record' do
|
71
|
+
widget = Widget.create!(test_id: 'abc2', some_int: 3)
|
72
|
+
MyProducerWithID.send_event(id: widget.id, test_id: 'abc2', some_int: 3)
|
73
|
+
expect('my-topic-with-id').to have_sent(
|
74
|
+
test_id: 'abc2',
|
75
|
+
some_int: 3,
|
76
|
+
message_id: 'generated_id',
|
77
|
+
timestamp: anything
|
78
|
+
)
|
79
|
+
end
|
105
80
|
|
81
|
+
specify '#watched_attributes' do
|
82
|
+
expect(MyProducer.watched_attributes).to eq(%w(test_id some_int))
|
106
83
|
end
|
84
|
+
|
107
85
|
end
|
data/spec/batch_consumer_spec.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'deimos/batch_consumer'
|
4
|
-
|
5
3
|
# :nodoc:
|
6
4
|
module ConsumerTest
|
7
|
-
describe Deimos::
|
5
|
+
describe Deimos::Consumer, 'Batch Consumer' do
|
8
6
|
|
9
7
|
prepend_before(:each) do
|
10
8
|
# :nodoc:
|
11
|
-
consumer_class = Class.new(
|
9
|
+
consumer_class = Class.new(described_class) do
|
12
10
|
schema 'MySchema'
|
13
11
|
namespace 'com.my-namespace'
|
14
12
|
key_config field: 'test_id'
|
@@ -32,6 +30,24 @@ module ConsumerTest
|
|
32
30
|
batch.concat([{ 'invalid' => 'key' }])
|
33
31
|
end
|
34
32
|
|
33
|
+
it 'should provide backwards compatibility for BatchConsumer class' do
|
34
|
+
consumer_class = Class.new(Deimos::BatchConsumer) do
|
35
|
+
schema 'MySchema'
|
36
|
+
namespace 'com.my-namespace'
|
37
|
+
key_config field: 'test_id'
|
38
|
+
|
39
|
+
# :nodoc:
|
40
|
+
def consume_batch(_payloads, _metadata)
|
41
|
+
raise 'This should not be called unless call_original is set'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
stub_const('ConsumerTest::MyOldBatchConsumer', consumer_class)
|
45
|
+
|
46
|
+
test_consume_batch(MyOldBatchConsumer, batch) do |received, _metadata|
|
47
|
+
expect(received).to eq(batch)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
35
51
|
it 'should consume a batch of messages' do
|
36
52
|
test_consume_batch(MyBatchConsumer, batch) do |received, _metadata|
|
37
53
|
expect(received).to eq(batch)
|
@@ -99,7 +115,7 @@ module ConsumerTest
|
|
99
115
|
end
|
100
116
|
|
101
117
|
it 'should decode plain keys for all messages in the batch' do
|
102
|
-
consumer_class = Class.new(
|
118
|
+
consumer_class = Class.new(described_class) do
|
103
119
|
schema 'MySchema'
|
104
120
|
namespace 'com.my-namespace'
|
105
121
|
key_config plain: true
|
@@ -115,7 +131,7 @@ module ConsumerTest
|
|
115
131
|
describe 'timestamps' do
|
116
132
|
before(:each) do
|
117
133
|
# :nodoc:
|
118
|
-
consumer_class = Class.new(
|
134
|
+
consumer_class = Class.new(described_class) do
|
119
135
|
schema 'MySchemaWithDateTimes'
|
120
136
|
namespace 'com.my-namespace'
|
121
137
|
key_config plain: true
|
@@ -197,7 +213,7 @@ module ConsumerTest
|
|
197
213
|
describe 'logging' do
|
198
214
|
before(:each) do
|
199
215
|
# :nodoc:
|
200
|
-
consumer_class = Class.new(
|
216
|
+
consumer_class = Class.new(described_class) do
|
201
217
|
schema 'MySchemaWithUniqueId'
|
202
218
|
namespace 'com.my-namespace'
|
203
219
|
key_config plain: true
|