deimos-ruby 1.7.0.pre.beta1 → 1.8.1.pre.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -4
- data/CHANGELOG.md +50 -0
- data/Gemfile.lock +109 -75
- data/README.md +147 -16
- data/deimos-ruby.gemspec +4 -2
- data/docs/ARCHITECTURE.md +144 -0
- data/docs/CONFIGURATION.md +4 -0
- data/lib/deimos.rb +8 -7
- 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/batch_consumer.rb +2 -142
- data/lib/deimos/config/configuration.rb +8 -10
- data/lib/deimos/consume/batch_consumption.rb +150 -0
- data/lib/deimos/consume/message_consumption.rb +94 -0
- data/lib/deimos/consumer.rb +79 -72
- data/lib/deimos/instrumentation.rb +10 -5
- data/lib/deimos/kafka_message.rb +1 -1
- data/lib/deimos/kafka_topic_info.rb +21 -2
- data/lib/deimos/message.rb +6 -1
- data/lib/deimos/schema_backends/avro_base.rb +33 -1
- data/lib/deimos/schema_backends/avro_schema_coercer.rb +30 -11
- data/lib/deimos/schema_backends/base.rb +21 -2
- data/lib/deimos/utils/db_poller.rb +6 -6
- data/lib/deimos/utils/db_producer.rb +57 -15
- data/lib/deimos/utils/deadlock_retry.rb +68 -0
- data/lib/deimos/utils/lag_reporter.rb +19 -26
- data/lib/deimos/utils/schema_controller_mixin.rb +111 -0
- data/lib/deimos/version.rb +1 -1
- data/lib/generators/deimos/active_record/templates/migration.rb.tt +28 -0
- data/lib/generators/deimos/active_record/templates/model.rb.tt +5 -0
- data/lib/generators/deimos/active_record_generator.rb +79 -0
- data/lib/generators/deimos/db_backend/templates/migration +1 -0
- data/lib/generators/deimos/db_backend/templates/rails3_migration +1 -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 +3 -11
- data/spec/batch_consumer_spec.rb +24 -7
- data/spec/config/configuration_spec.rb +4 -0
- data/spec/consumer_spec.rb +6 -6
- data/spec/deimos_spec.rb +57 -49
- data/spec/generators/active_record_generator_spec.rb +56 -0
- data/spec/handlers/my_batch_consumer.rb +6 -1
- data/spec/handlers/my_consumer.rb +6 -1
- data/spec/kafka_listener_spec.rb +54 -0
- data/spec/kafka_topic_info_spec.rb +39 -16
- data/spec/message_spec.rb +19 -0
- data/spec/producer_spec.rb +34 -0
- data/spec/schemas/com/my-namespace/Generated.avsc +71 -0
- data/spec/schemas/com/my-namespace/MyNestedSchema.avsc +55 -0
- data/spec/schemas/com/my-namespace/MySchemaCompound-key.avsc +18 -0
- data/spec/schemas/com/my-namespace/Wibble.avsc +43 -0
- data/spec/schemas/com/my-namespace/request/Index.avsc +11 -0
- data/spec/schemas/com/my-namespace/request/UpdateRequest.avsc +11 -0
- data/spec/schemas/com/my-namespace/response/Index.avsc +11 -0
- data/spec/schemas/com/my-namespace/response/UpdateResponse.avsc +11 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/utils/db_poller_spec.rb +2 -2
- data/spec/utils/db_producer_spec.rb +84 -10
- data/spec/utils/deadlock_retry_spec.rb +74 -0
- data/spec/utils/lag_reporter_spec.rb +29 -22
- data/spec/utils/schema_controller_mixin_spec.rb +68 -0
- metadata +87 -30
- data/lib/deimos/base_consumer.rb +0 -100
- 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|
|
@@ -137,13 +137,5 @@ module ActiveRecordProducerTest
|
|
137
137
|
expect(Widget.find_by_test_id('id1').some_int).to eq(3)
|
138
138
|
expect(Widget.find_by_test_id('id2').some_int).to eq(4)
|
139
139
|
end
|
140
|
-
|
141
|
-
it 'should coerce int values to datetimes' do
|
142
|
-
column = Widget.columns.find { |c| c.name == 'some_datetime_int' }
|
143
|
-
expect(MyConsumer.new.send(:_coerce_field, column, 1_579_046_400)).to eq('2020-01-14 19:00:00 -0500')
|
144
|
-
expect(MyConsumer.new.send(:_coerce_field, column, '1579046400')).to eq('2020-01-14 19:00:00 -0500')
|
145
|
-
expect(MyConsumer.new.send(:_coerce_field, column, 'some-other-val')).to eq('some-other-val')
|
146
|
-
end
|
147
|
-
|
148
140
|
end
|
149
141
|
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)
|
@@ -95,11 +111,12 @@ module ConsumerTest
|
|
95
111
|
test_consume_batch('my_batch_consume_topic', batch, keys: keys) do |_received, metadata|
|
96
112
|
# Mock decode_key extracts the value of the first field as the key
|
97
113
|
expect(metadata[:keys]).to eq(%w(foo bar))
|
114
|
+
expect(metadata[:first_offset]).to eq(1)
|
98
115
|
end
|
99
116
|
end
|
100
117
|
|
101
118
|
it 'should decode plain keys for all messages in the batch' do
|
102
|
-
consumer_class = Class.new(
|
119
|
+
consumer_class = Class.new(described_class) do
|
103
120
|
schema 'MySchema'
|
104
121
|
namespace 'com.my-namespace'
|
105
122
|
key_config plain: true
|
@@ -115,7 +132,7 @@ module ConsumerTest
|
|
115
132
|
describe 'timestamps' do
|
116
133
|
before(:each) do
|
117
134
|
# :nodoc:
|
118
|
-
consumer_class = Class.new(
|
135
|
+
consumer_class = Class.new(described_class) do
|
119
136
|
schema 'MySchemaWithDateTimes'
|
120
137
|
namespace 'com.my-namespace'
|
121
138
|
key_config plain: true
|
@@ -197,7 +214,7 @@ module ConsumerTest
|
|
197
214
|
describe 'logging' do
|
198
215
|
before(:each) do
|
199
216
|
# :nodoc:
|
200
|
-
consumer_class = Class.new(
|
217
|
+
consumer_class = Class.new(described_class) do
|
201
218
|
schema 'MySchemaWithUniqueId'
|
202
219
|
namespace 'com.my-namespace'
|
203
220
|
key_config plain: true
|
data/spec/consumer_spec.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
# :nodoc:
|
4
4
|
module ConsumerTest
|
5
|
-
describe Deimos::Consumer do
|
5
|
+
describe Deimos::Consumer, 'Message Consumer' do
|
6
6
|
|
7
7
|
prepend_before(:each) do
|
8
8
|
# :nodoc:
|
9
|
-
consumer_class = Class.new(
|
9
|
+
consumer_class = Class.new(described_class) do
|
10
10
|
schema 'MySchema'
|
11
11
|
namespace 'com.my-namespace'
|
12
12
|
key_config field: 'test_id'
|
@@ -121,7 +121,7 @@ module ConsumerTest
|
|
121
121
|
end
|
122
122
|
|
123
123
|
it 'should use the key schema if set' do
|
124
|
-
consumer_class = Class.new(
|
124
|
+
consumer_class = Class.new(described_class) do
|
125
125
|
schema 'MySchema'
|
126
126
|
namespace 'com.my-namespace'
|
127
127
|
key_config schema: 'MySchema_key'
|
@@ -132,7 +132,7 @@ module ConsumerTest
|
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'should not decode if plain is set' do
|
135
|
-
consumer_class = Class.new(
|
135
|
+
consumer_class = Class.new(described_class) do
|
136
136
|
schema 'MySchema'
|
137
137
|
namespace 'com.my-namespace'
|
138
138
|
key_config plain: true
|
@@ -142,7 +142,7 @@ module ConsumerTest
|
|
142
142
|
end
|
143
143
|
|
144
144
|
it 'should error with nothing set' do
|
145
|
-
consumer_class = Class.new(
|
145
|
+
consumer_class = Class.new(described_class) do
|
146
146
|
schema 'MySchema'
|
147
147
|
namespace 'com.my-namespace'
|
148
148
|
end
|
@@ -156,7 +156,7 @@ module ConsumerTest
|
|
156
156
|
describe 'timestamps' do
|
157
157
|
before(:each) do
|
158
158
|
# :nodoc:
|
159
|
-
consumer_class = Class.new(
|
159
|
+
consumer_class = Class.new(described_class) do
|
160
160
|
schema 'MySchemaWithDateTimes'
|
161
161
|
namespace 'com.my-namespace'
|
162
162
|
key_config plain: true
|
data/spec/deimos_spec.rb
CHANGED
@@ -68,11 +68,11 @@ describe Deimos do
|
|
68
68
|
|
69
69
|
describe '#start_db_backend!' do
|
70
70
|
it 'should start if backend is db and thread_count is > 0' do
|
71
|
-
signal_handler = instance_double(
|
71
|
+
signal_handler = instance_double(Sigurd::SignalHandler)
|
72
72
|
allow(signal_handler).to receive(:run!)
|
73
|
-
expect(
|
73
|
+
expect(Sigurd::Executor).to receive(:new).
|
74
74
|
with(anything, sleep_seconds: 5, logger: anything).and_call_original
|
75
|
-
expect(
|
75
|
+
expect(Sigurd::SignalHandler).to receive(:new) do |executor|
|
76
76
|
expect(executor.runners.size).to eq(2)
|
77
77
|
signal_handler
|
78
78
|
end
|
@@ -83,7 +83,7 @@ describe Deimos do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'should not start if backend is not db' do
|
86
|
-
expect(
|
86
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
87
87
|
described_class.configure do |config|
|
88
88
|
config.producers.backend = :kafka
|
89
89
|
end
|
@@ -92,7 +92,7 @@ describe Deimos do
|
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'should not start if thread_count is nil' do
|
95
|
-
expect(
|
95
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
96
96
|
described_class.configure do |config|
|
97
97
|
config.producers.backend = :db
|
98
98
|
end
|
@@ -101,61 +101,69 @@ describe Deimos do
|
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'should not start if thread_count is 0' do
|
104
|
-
expect(
|
104
|
+
expect(Sigurd::SignalHandler).not_to receive(:new)
|
105
105
|
described_class.configure do |config|
|
106
106
|
config.producers.backend = :db
|
107
107
|
end
|
108
108
|
expect { described_class.start_db_backend!(thread_count: 0) }.
|
109
109
|
to raise_error('Thread count is not given or set to zero, exiting')
|
110
110
|
end
|
111
|
+
end
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
it 'should not raise an error with properly configured handlers' do
|
118
|
-
path = config_path # for scope issues in the block below
|
119
|
-
# Add explicit consumers
|
120
|
-
phobos_configuration['listeners'] << { 'handler' => 'ConsumerTest::MyConsumer',
|
121
|
-
'delivery' => 'message' }
|
122
|
-
phobos_configuration['listeners'] << { 'handler' => 'ConsumerTest::MyConsumer',
|
123
|
-
'delivery' => 'batch' }
|
124
|
-
|
125
|
-
expect {
|
126
|
-
described_class.configure { |c| c.phobos_config_file = path }
|
127
|
-
}.not_to raise_error
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'should raise an error if BatchConsumers do not have inline_batch delivery' do
|
131
|
-
path = config_path # for scope issues in the block below
|
132
|
-
phobos_configuration['listeners'] = [{ 'handler' => 'ConsumerTest::MyBatchConsumer',
|
133
|
-
'delivery' => 'message' }]
|
134
|
-
|
135
|
-
expect {
|
136
|
-
described_class.configure { |c| c.phobos_config_file = path }
|
137
|
-
}.to raise_error('BatchConsumer ConsumerTest::MyBatchConsumer must have delivery set to `inline_batch`')
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should raise an error if Consumers do not have message or batch delivery' do
|
141
|
-
path = config_path # for scope issues in the block below
|
142
|
-
phobos_configuration['listeners'] = [{ 'handler' => 'ConsumerTest::MyConsumer',
|
143
|
-
'delivery' => 'inline_batch' }]
|
113
|
+
describe 'delivery configuration' do
|
114
|
+
before(:each) do
|
115
|
+
allow(YAML).to receive(:load).and_return(phobos_configuration)
|
116
|
+
end
|
144
117
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
118
|
+
it 'should not raise an error with properly configured handlers' do
|
119
|
+
expect {
|
120
|
+
described_class.configure do
|
121
|
+
consumer do
|
122
|
+
class_name 'ConsumerTest::MyConsumer'
|
123
|
+
delivery :message
|
124
|
+
end
|
125
|
+
consumer do
|
126
|
+
class_name 'ConsumerTest::MyConsumer'
|
127
|
+
delivery :batch
|
128
|
+
end
|
129
|
+
consumer do
|
130
|
+
class_name 'ConsumerTest::MyBatchConsumer'
|
131
|
+
delivery :inline_batch
|
132
|
+
end
|
133
|
+
end
|
134
|
+
}.not_to raise_error
|
135
|
+
end
|
149
136
|
|
150
|
-
|
151
|
-
|
152
|
-
|
137
|
+
it 'should raise an error if inline_batch listeners do not implement consume_batch' do
|
138
|
+
expect {
|
139
|
+
described_class.configure do
|
140
|
+
consumer do
|
141
|
+
class_name 'ConsumerTest::MyConsumer'
|
142
|
+
delivery :inline_batch
|
143
|
+
end
|
144
|
+
end
|
145
|
+
}.to raise_error('BatchConsumer ConsumerTest::MyConsumer does not implement `consume_batch`')
|
146
|
+
end
|
153
147
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
148
|
+
it 'should raise an error if Consumers do not have message or batch delivery' do
|
149
|
+
expect {
|
150
|
+
described_class.configure do
|
151
|
+
consumer do
|
152
|
+
class_name 'ConsumerTest::MyBatchConsumer'
|
153
|
+
delivery :message
|
154
|
+
end
|
155
|
+
end
|
156
|
+
}.to raise_error('Non-batch Consumer ConsumerTest::MyBatchConsumer does not implement `consume`')
|
157
|
+
end
|
158
158
|
|
159
|
+
it 'should treat nil as `batch`' do
|
160
|
+
expect {
|
161
|
+
described_class.configure do
|
162
|
+
consumer do
|
163
|
+
class_name 'ConsumerTest::MyConsumer'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
}.not_to raise_error
|
159
167
|
end
|
160
168
|
end
|
161
169
|
end
|