deimos-ruby 1.24.2 → 2.0.0.pre.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +0 -17
- data/.tool-versions +1 -0
- data/CHANGELOG.md +5 -0
- data/README.md +287 -498
- data/deimos-ruby.gemspec +4 -4
- data/docs/CONFIGURATION.md +133 -226
- data/docs/UPGRADING.md +237 -0
- data/lib/deimos/active_record_consume/batch_consumption.rb +29 -28
- data/lib/deimos/active_record_consume/mass_updater.rb +59 -4
- data/lib/deimos/active_record_consume/message_consumption.rb +15 -21
- data/lib/deimos/active_record_consumer.rb +36 -21
- data/lib/deimos/active_record_producer.rb +28 -9
- data/lib/deimos/backends/base.rb +4 -35
- data/lib/deimos/backends/kafka.rb +6 -22
- data/lib/deimos/backends/kafka_async.rb +6 -22
- data/lib/deimos/backends/{db.rb → outbox.rb} +13 -9
- data/lib/deimos/config/configuration.rb +116 -379
- data/lib/deimos/consume/batch_consumption.rb +24 -124
- data/lib/deimos/consume/message_consumption.rb +36 -63
- data/lib/deimos/consumer.rb +16 -75
- data/lib/deimos/ext/consumer_route.rb +35 -0
- data/lib/deimos/ext/producer_middleware.rb +94 -0
- data/lib/deimos/ext/producer_route.rb +22 -0
- data/lib/deimos/ext/redraw.rb +29 -0
- data/lib/deimos/ext/routing_defaults.rb +72 -0
- data/lib/deimos/ext/schema_route.rb +70 -0
- data/lib/deimos/kafka_message.rb +2 -2
- data/lib/deimos/kafka_source.rb +2 -7
- data/lib/deimos/kafka_topic_info.rb +1 -1
- data/lib/deimos/logging.rb +71 -0
- data/lib/deimos/message.rb +2 -11
- data/lib/deimos/metrics/datadog.rb +40 -1
- data/lib/deimos/metrics/provider.rb +4 -4
- data/lib/deimos/producer.rb +39 -116
- data/lib/deimos/railtie.rb +6 -0
- data/lib/deimos/schema_backends/avro_base.rb +21 -21
- data/lib/deimos/schema_backends/avro_schema_registry.rb +1 -2
- data/lib/deimos/schema_backends/avro_validation.rb +2 -2
- data/lib/deimos/schema_backends/base.rb +19 -12
- data/lib/deimos/schema_backends/mock.rb +6 -1
- data/lib/deimos/schema_backends/plain.rb +47 -0
- data/lib/deimos/schema_class/base.rb +2 -2
- data/lib/deimos/schema_class/enum.rb +1 -1
- data/lib/deimos/schema_class/record.rb +2 -2
- data/lib/deimos/test_helpers.rb +95 -320
- data/lib/deimos/tracing/provider.rb +6 -6
- data/lib/deimos/transcoder.rb +88 -0
- data/lib/deimos/utils/db_poller/base.rb +16 -14
- data/lib/deimos/utils/db_poller/state_based.rb +3 -3
- data/lib/deimos/utils/db_poller/time_based.rb +4 -4
- data/lib/deimos/utils/db_poller.rb +1 -1
- data/lib/deimos/utils/deadlock_retry.rb +1 -1
- data/lib/deimos/utils/{db_producer.rb → outbox_producer.rb} +16 -47
- data/lib/deimos/utils/schema_class.rb +0 -7
- data/lib/deimos/version.rb +1 -1
- data/lib/deimos.rb +79 -26
- data/lib/generators/deimos/{db_backend_generator.rb → outbox_backend_generator.rb} +4 -4
- data/lib/generators/deimos/schema_class_generator.rb +0 -1
- data/lib/generators/deimos/v2/templates/karafka.rb.tt +149 -0
- data/lib/generators/deimos/v2_generator.rb +193 -0
- data/lib/tasks/deimos.rake +5 -7
- data/spec/active_record_batch_consumer_association_spec.rb +22 -13
- data/spec/active_record_batch_consumer_spec.rb +84 -65
- data/spec/active_record_consume/batch_consumption_spec.rb +10 -10
- data/spec/active_record_consume/batch_slicer_spec.rb +12 -12
- data/spec/active_record_consume/mass_updater_spec.rb +137 -0
- data/spec/active_record_consumer_spec.rb +29 -13
- data/spec/active_record_producer_spec.rb +36 -26
- data/spec/backends/base_spec.rb +0 -23
- data/spec/backends/kafka_async_spec.rb +1 -3
- data/spec/backends/kafka_spec.rb +1 -3
- data/spec/backends/{db_spec.rb → outbox_spec.rb} +14 -20
- data/spec/batch_consumer_spec.rb +66 -116
- data/spec/consumer_spec.rb +53 -147
- data/spec/deimos_spec.rb +10 -126
- data/spec/kafka_source_spec.rb +19 -52
- data/spec/karafka/karafka.rb +69 -0
- data/spec/karafka_config/karafka_spec.rb +97 -0
- data/spec/logging_spec.rb +25 -0
- data/spec/message_spec.rb +9 -9
- data/spec/producer_spec.rb +112 -254
- data/spec/rake_spec.rb +1 -3
- data/spec/schema_backends/avro_validation_spec.rb +1 -1
- data/spec/schemas/com/my-namespace/MySchemaWithTitle.avsc +22 -0
- data/spec/snapshots/consumers-no-nest.snap +49 -0
- data/spec/snapshots/consumers.snap +49 -0
- data/spec/snapshots/consumers_and_producers-no-nest.snap +49 -0
- data/spec/snapshots/consumers_and_producers.snap +49 -0
- data/spec/snapshots/consumers_circular-no-nest.snap +49 -0
- data/spec/snapshots/consumers_circular.snap +49 -0
- data/spec/snapshots/consumers_complex_types-no-nest.snap +49 -0
- data/spec/snapshots/consumers_complex_types.snap +49 -0
- data/spec/snapshots/consumers_nested-no-nest.snap +49 -0
- data/spec/snapshots/consumers_nested.snap +49 -0
- data/spec/snapshots/namespace_folders.snap +49 -0
- data/spec/snapshots/namespace_map.snap +49 -0
- data/spec/snapshots/producers_with_key-no-nest.snap +49 -0
- data/spec/snapshots/producers_with_key.snap +49 -0
- data/spec/spec_helper.rb +61 -29
- data/spec/utils/db_poller_spec.rb +49 -39
- data/spec/utils/{db_producer_spec.rb → outbox_producer_spec.rb} +17 -184
- metadata +58 -67
- data/lib/deimos/batch_consumer.rb +0 -7
- data/lib/deimos/config/phobos_config.rb +0 -163
- data/lib/deimos/instrumentation.rb +0 -95
- data/lib/deimos/monkey_patches/phobos_cli.rb +0 -35
- data/lib/deimos/utils/inline_consumer.rb +0 -158
- data/lib/deimos/utils/lag_reporter.rb +0 -186
- data/lib/deimos/utils/schema_controller_mixin.rb +0 -129
- data/spec/config/configuration_spec.rb +0 -321
- data/spec/kafka_listener_spec.rb +0 -55
- data/spec/phobos.bad_db.yml +0 -73
- data/spec/phobos.yml +0 -77
- data/spec/utils/inline_consumer_spec.rb +0 -31
- data/spec/utils/lag_reporter_spec.rb +0 -76
- data/spec/utils/platform_schema_validation_spec.rb +0 -0
- data/spec/utils/schema_controller_mixin_spec.rb +0 -84
- /data/lib/generators/deimos/{db_backend → outbox_backend}/templates/migration +0 -0
- /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 },
|
8
|
-
Deimos::Message.new({ v: 123 },
|
9
|
-
Deimos::Message.new({ v: 999 },
|
10
|
-
Deimos::Message.new({ v: 456 },
|
11
|
-
Deimos::Message.new({ v: 2 },
|
12
|
-
Deimos::Message.new({ v: 3 },
|
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 },
|
23
|
-
Deimos::Message.new({ v: 123 },
|
24
|
-
Deimos::Message.new({ v: 999 },
|
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 },
|
28
|
-
Deimos::Message.new({ v: 2 },
|
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 },
|
31
|
+
Deimos::Message.new({ v: 3 }, key: 'C')
|
32
32
|
])
|
33
33
|
])
|
34
34
|
end
|
@@ -114,5 +114,142 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
|
|
114
114
|
|
115
115
|
end
|
116
116
|
|
117
|
+
context 'with save_associations_first' do
|
118
|
+
before(:all) do
|
119
|
+
ActiveRecord::Base.connection.create_table(:fidgets, force: true) do |t|
|
120
|
+
t.string(:test_id)
|
121
|
+
t.integer(:some_int)
|
122
|
+
t.string(:bulk_import_id)
|
123
|
+
t.timestamps
|
124
|
+
end
|
125
|
+
|
126
|
+
ActiveRecord::Base.connection.create_table(:fidget_details, force: true) do |t|
|
127
|
+
t.string(:title)
|
128
|
+
t.string(:bulk_import_id)
|
129
|
+
t.belongs_to(:fidget)
|
130
|
+
|
131
|
+
t.index(%i(title), unique: true)
|
132
|
+
end
|
133
|
+
|
134
|
+
ActiveRecord::Base.connection.create_table(:widget_fidgets, force: true, id: false) do |t|
|
135
|
+
t.belongs_to(:fidget)
|
136
|
+
t.belongs_to(:widget)
|
137
|
+
t.string(:bulk_import_id)
|
138
|
+
t.string(:note)
|
139
|
+
t.index(%i(widget_id fidget_id), unique: true)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
after(:all) do
|
144
|
+
ActiveRecord::Base.connection.drop_table(:fidgets)
|
145
|
+
ActiveRecord::Base.connection.drop_table(:fidget_details)
|
146
|
+
ActiveRecord::Base.connection.drop_table(:widget_fidgets)
|
147
|
+
end
|
148
|
+
|
149
|
+
let(:fidget_detail_class) do
|
150
|
+
Class.new(ActiveRecord::Base) do
|
151
|
+
self.table_name = 'fidget_details'
|
152
|
+
belongs_to :fidget
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
let(:fidget_class) do
|
157
|
+
Class.new(ActiveRecord::Base) do
|
158
|
+
self.table_name = 'fidgets'
|
159
|
+
has_one :fidget_detail
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
let(:widget_fidget_class) do
|
164
|
+
Class.new(ActiveRecord::Base) do
|
165
|
+
self.table_name = 'widget_fidgets'
|
166
|
+
belongs_to :fidget
|
167
|
+
belongs_to :widget
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
let(:bulk_id_generator) { proc { SecureRandom.uuid } }
|
172
|
+
|
173
|
+
let(:key_proc) do
|
174
|
+
lambda do |klass|
|
175
|
+
case klass.to_s
|
176
|
+
when 'Widget', 'Fidget'
|
177
|
+
%w(id)
|
178
|
+
when 'WidgetFidget'
|
179
|
+
%w(widget_id fidget_id)
|
180
|
+
when 'FidgetDetail', 'Detail'
|
181
|
+
%w(title)
|
182
|
+
else
|
183
|
+
raise "Key Columns for #{klass} not defined"
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
before(:each) do
|
190
|
+
stub_const('Fidget', fidget_class)
|
191
|
+
stub_const('FidgetDetail', fidget_detail_class)
|
192
|
+
stub_const('WidgetFidget', widget_fidget_class)
|
193
|
+
Widget.reset_column_information
|
194
|
+
Fidget.reset_column_information
|
195
|
+
WidgetFidget.reset_column_information
|
196
|
+
end
|
197
|
+
|
198
|
+
# rubocop:disable RSpec/MultipleExpectations, RSpec/ExampleLength
|
199
|
+
it 'should backfill the associations when upserting primary records' do
|
200
|
+
batch = Deimos::ActiveRecordConsume::BatchRecordList.new(
|
201
|
+
[
|
202
|
+
Deimos::ActiveRecordConsume::BatchRecord.new(
|
203
|
+
klass: WidgetFidget,
|
204
|
+
attributes: {
|
205
|
+
widget: { test_id: 'id1', some_int: 10, detail: { title: 'Widget Title 1' } },
|
206
|
+
fidget: { test_id: 'id1', some_int: 10, fidget_detail: { title: 'Fidget Title 1' } },
|
207
|
+
note: 'Stuff 1'
|
208
|
+
},
|
209
|
+
bulk_import_column: 'bulk_import_id',
|
210
|
+
bulk_import_id_generator: bulk_id_generator
|
211
|
+
),
|
212
|
+
Deimos::ActiveRecordConsume::BatchRecord.new(
|
213
|
+
klass: WidgetFidget,
|
214
|
+
attributes: {
|
215
|
+
widget: { test_id: 'id2', some_int: 20, detail: { title: 'Widget Title 2' } },
|
216
|
+
fidget: { test_id: 'id2', some_int: 20, fidget_detail: { title: 'Fidget Title 2' } },
|
217
|
+
note: 'Stuff 2'
|
218
|
+
},
|
219
|
+
bulk_import_column: 'bulk_import_id',
|
220
|
+
bulk_import_id_generator: bulk_id_generator
|
221
|
+
)
|
222
|
+
]
|
223
|
+
)
|
224
|
+
|
225
|
+
results = described_class.new(WidgetFidget,
|
226
|
+
bulk_import_id_generator: bulk_id_generator,
|
227
|
+
bulk_import_id_column: 'bulk_import_id',
|
228
|
+
key_col_proc: key_proc,
|
229
|
+
save_associations_first: true).mass_update(batch)
|
230
|
+
expect(results.count).to eq(2)
|
231
|
+
expect(Widget.count).to eq(2)
|
232
|
+
expect(Detail.count).to eq(2)
|
233
|
+
expect(Fidget.count).to eq(2)
|
234
|
+
expect(FidgetDetail.count).to eq(2)
|
235
|
+
|
236
|
+
WidgetFidget.all.each_with_index do |widget_fidget, ind|
|
237
|
+
widget = Widget.find_by(id: widget_fidget.widget_id)
|
238
|
+
expect(widget.test_id).to eq("id#{ind + 1}")
|
239
|
+
expect(widget.some_int).to eq((ind + 1) * 10)
|
240
|
+
detail = Detail.find_by(widget_id: widget_fidget.widget_id)
|
241
|
+
expect(detail.title).to eq("Widget Title #{ind + 1}")
|
242
|
+
fidget = Fidget.find_by(id: widget_fidget.fidget_id)
|
243
|
+
expect(fidget.test_id).to eq("id#{ind + 1}")
|
244
|
+
expect(fidget.some_int).to eq((ind + 1) * 10)
|
245
|
+
fidget_detail = FidgetDetail.find_by(fidget_id: widget_fidget.fidget_id)
|
246
|
+
expect(fidget_detail.title).to eq("Fidget Title #{ind + 1}")
|
247
|
+
expect(widget_fidget.note).to eq("Stuff #{ind + 1}")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
# rubocop:enable RSpec/MultipleExpectations, RSpec/ExampleLength
|
251
|
+
|
252
|
+
end
|
253
|
+
|
117
254
|
end
|
118
255
|
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
|
-
}
|
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
|
-
}
|
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
|
-
}
|
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)
|
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
|
data/spec/backends/base_spec.rb
CHANGED
@@ -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
|
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
|
data/spec/backends/kafka_spec.rb
CHANGED
@@ -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
|
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::
|
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
|
-
|
9
|
-
|
10
|
-
|
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' => '{"
|
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' => '{"
|
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' => '{"
|
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: [
|
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
|