deimos-ruby 1.20.1 → 1.22
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/CHANGELOG.md +8 -0
- data/README.md +23 -16
- data/docs/CONFIGURATION.md +2 -0
- data/lib/deimos/active_record_consume/batch_consumption.rb +78 -152
- data/lib/deimos/active_record_consume/batch_record.rb +78 -0
- data/lib/deimos/active_record_consume/batch_record_list.rb +78 -0
- data/lib/deimos/active_record_consume/mass_updater.rb +92 -0
- data/lib/deimos/active_record_consumer.rb +3 -12
- data/lib/deimos/config/configuration.rb +17 -1
- data/lib/deimos/config/phobos_config.rb +2 -1
- data/lib/deimos/version.rb +1 -1
- data/spec/active_record_batch_consumer_association_spec.rb +288 -0
- data/spec/active_record_batch_consumer_spec.rb +3 -19
- data/spec/active_record_consume/mass_updater_spec.rb +75 -0
- metadata +9 -5
- data/CHANGELOG.md.orig +0 -517
- data/spec/active_record_batch_consumer_mysql_spec.rb +0 -244
@@ -7,7 +7,7 @@ require_relative '../tracing/mock'
|
|
7
7
|
require 'active_support/core_ext/numeric'
|
8
8
|
|
9
9
|
# :nodoc:
|
10
|
-
module Deimos
|
10
|
+
module Deimos # rubocop:disable Metrics/ModuleLength
|
11
11
|
include FigTree
|
12
12
|
|
13
13
|
# :nodoc:
|
@@ -87,6 +87,12 @@ module Deimos
|
|
87
87
|
namespace(kafka_config.namespace) if kafka_config.namespace.present?
|
88
88
|
key_config(**kafka_config.key_config) if kafka_config.key_config.present?
|
89
89
|
schema_class_config(kafka_config.use_schema_classes) if kafka_config.use_schema_classes.present?
|
90
|
+
if kafka_config.respond_to?(:bulk_import_id_column) # consumer
|
91
|
+
klass.config.merge!(
|
92
|
+
bulk_import_id_column: kafka_config.bulk_import_id_column,
|
93
|
+
replace_associations: kafka_config.replace_associations
|
94
|
+
)
|
95
|
+
end
|
90
96
|
end
|
91
97
|
end
|
92
98
|
|
@@ -402,6 +408,10 @@ module Deimos
|
|
402
408
|
# Configure the usage of generated schema classes for this producer
|
403
409
|
# @return [Boolean]
|
404
410
|
setting :use_schema_classes
|
411
|
+
# If true, and using the multi-table feature of ActiveRecordConsumers, replace associations
|
412
|
+
# instead of appending to them.
|
413
|
+
# @return [Boolean]
|
414
|
+
setting :replace_associations
|
405
415
|
end
|
406
416
|
|
407
417
|
setting_object :consumer do
|
@@ -430,6 +440,12 @@ module Deimos
|
|
430
440
|
# Optional maximum limit for batching database calls to reduce the load on the db.
|
431
441
|
# @return [Integer]
|
432
442
|
setting :max_db_batch_size
|
443
|
+
# Column to use for bulk imports, for multi-table feature.
|
444
|
+
# @return [String]
|
445
|
+
setting :bulk_import_id_column, :bulk_import_id
|
446
|
+
# If true, multi-table consumers will blow away associations rather than appending to them.
|
447
|
+
# @return [Boolean]
|
448
|
+
setting :replace_associations, true
|
433
449
|
|
434
450
|
# These are the phobos "listener" configs. See CONFIGURATION.md for more
|
435
451
|
# info.
|
@@ -67,7 +67,8 @@ module Deimos
|
|
67
67
|
next nil if consumer.disabled
|
68
68
|
|
69
69
|
hash = consumer.to_h.reject do |k, _|
|
70
|
-
%i(class_name schema namespace key_config backoff disabled
|
70
|
+
%i(class_name schema namespace key_config backoff disabled replace_associations
|
71
|
+
bulk_import_id_column).include?(k)
|
71
72
|
end
|
72
73
|
hash = hash.map { |k, v| [k, v.is_a?(Symbol) ? v.to_s : v] }.to_h
|
73
74
|
hash[:handler] = consumer.class_name
|
data/lib/deimos/version.rb
CHANGED
@@ -0,0 +1,288 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
|
4
|
+
describe Deimos::ActiveRecordConsumer,
|
5
|
+
'Batch Consumer with MySQL handling associations',
|
6
|
+
:integration,
|
7
|
+
db_config: DbConfigs::DB_OPTIONS.second do
|
8
|
+
include_context('with DB')
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
ActiveRecord::Base.connection.create_table(:widgets, force: true) do |t|
|
12
|
+
t.string(:test_id)
|
13
|
+
t.string(:part_one)
|
14
|
+
t.string(:part_two)
|
15
|
+
t.integer(:some_int)
|
16
|
+
t.string(:bulk_import_id)
|
17
|
+
t.boolean(:deleted, default: false)
|
18
|
+
t.timestamps
|
19
|
+
|
20
|
+
t.index(%i(part_one part_two), unique: true)
|
21
|
+
end
|
22
|
+
|
23
|
+
# create one-to-one association -- Details
|
24
|
+
ActiveRecord::Base.connection.create_table(:details, force: true) do |t|
|
25
|
+
t.string(:title)
|
26
|
+
t.string(:bulk_import_id)
|
27
|
+
t.belongs_to(:widget)
|
28
|
+
|
29
|
+
t.index(%i(title), unique: true)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create one-to-many association Locales
|
33
|
+
ActiveRecord::Base.connection.create_table(:locales, force: true) do |t|
|
34
|
+
t.string(:title)
|
35
|
+
t.string(:language)
|
36
|
+
t.string(:bulk_import_id)
|
37
|
+
t.belongs_to(:widget)
|
38
|
+
|
39
|
+
t.index(%i(widget_id title language), unique: true)
|
40
|
+
end
|
41
|
+
|
42
|
+
class Detail < ActiveRecord::Base
|
43
|
+
validates :title, presence: true
|
44
|
+
end
|
45
|
+
|
46
|
+
class Locale < ActiveRecord::Base
|
47
|
+
validates :title, presence: true
|
48
|
+
validates :language, presence: true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sample model
|
52
|
+
class Widget < ActiveRecord::Base
|
53
|
+
has_one :detail
|
54
|
+
has_many :locales, dependent: :destroy
|
55
|
+
validates :test_id, presence: true
|
56
|
+
|
57
|
+
default_scope -> { where(deleted: false) }
|
58
|
+
end
|
59
|
+
|
60
|
+
Widget.reset_column_information
|
61
|
+
Detail.reset_column_information
|
62
|
+
Locale.reset_column_information
|
63
|
+
end
|
64
|
+
|
65
|
+
after(:all) do
|
66
|
+
ActiveRecord::Base.connection.drop_table(:widgets)
|
67
|
+
ActiveRecord::Base.connection.drop_table(:details)
|
68
|
+
ActiveRecord::Base.connection.drop_table(:locales)
|
69
|
+
end
|
70
|
+
|
71
|
+
before(:each) do
|
72
|
+
ActiveRecord::Base.connection.truncate_tables(%i(widgets details locales))
|
73
|
+
Widget.create!(test_id: 'bad_id', some_int: 100) # should not show up
|
74
|
+
end
|
75
|
+
|
76
|
+
prepend_before(:each) do
|
77
|
+
stub_const('MyBatchConsumer', consumer_class)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Helper to publish a list of messages and call the consumer
|
81
|
+
def publish_batch(messages)
|
82
|
+
keys = messages.map { |m| m[:key] }
|
83
|
+
payloads = messages.map { |m| m[:payload] }
|
84
|
+
|
85
|
+
test_consume_batch(MyBatchConsumer, payloads, keys: keys, call_original: true)
|
86
|
+
end
|
87
|
+
|
88
|
+
let(:consumer_class) do
|
89
|
+
klass = Class.new(described_class) do
|
90
|
+
cattr_accessor :record_attributes_proc
|
91
|
+
cattr_accessor :should_consume_proc
|
92
|
+
schema 'MySchema'
|
93
|
+
namespace 'com.my-namespace'
|
94
|
+
key_config plain: true
|
95
|
+
record_class Widget
|
96
|
+
|
97
|
+
def should_consume?(record)
|
98
|
+
if self.should_consume_proc
|
99
|
+
return self.should_consume_proc.call(record)
|
100
|
+
end
|
101
|
+
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def record_attributes(payload, _key)
|
106
|
+
if self.record_attributes_proc
|
107
|
+
return self.record_attributes_proc.call(payload)
|
108
|
+
end
|
109
|
+
|
110
|
+
{
|
111
|
+
test_id: payload['test_id'],
|
112
|
+
some_int: payload['some_int'],
|
113
|
+
detail: {
|
114
|
+
title: payload['title']
|
115
|
+
}
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def key_columns(klass)
|
120
|
+
case klass.to_s
|
121
|
+
when Widget.to_s
|
122
|
+
nil
|
123
|
+
when Detail.to_s
|
124
|
+
%w(title widget_id)
|
125
|
+
when Locale.to_s
|
126
|
+
%w(widget_id title language)
|
127
|
+
else
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def columns(record_class)
|
133
|
+
all_cols = record_class.columns.map(&:name)
|
134
|
+
|
135
|
+
case record_class.to_s
|
136
|
+
when Widget.to_s
|
137
|
+
nil
|
138
|
+
when Detail.to_s, Locale.to_s
|
139
|
+
all_cols - ['id']
|
140
|
+
else
|
141
|
+
[]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
klass
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'when association configured in consumer without model changes' do
|
149
|
+
before(:each) do
|
150
|
+
consumer_class.config[:bulk_import_id_column] = :bulk_import_id
|
151
|
+
ActiveRecord::Base.connection.remove_column(:widgets, :bulk_import_id)
|
152
|
+
Widget.reset_column_information
|
153
|
+
end
|
154
|
+
|
155
|
+
after(:each) do
|
156
|
+
ActiveRecord::Base.connection.add_column(:widgets, :bulk_import_id, :string)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should raise error when bulk_import_id is not found' do
|
160
|
+
stub_const('MyBatchConsumer', consumer_class)
|
161
|
+
expect {
|
162
|
+
publish_batch([{ key: 2,
|
163
|
+
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
164
|
+
}.to raise_error('Create bulk_import_id on the widgets table. Run rails g deimos:bulk_import_id {table}'\
|
165
|
+
' to create the migration.')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'with one-to-one relation in association and custom bulk_import_id' do
|
170
|
+
before(:each) do
|
171
|
+
consumer_class.config[:bulk_import_id_column] = :custom_id
|
172
|
+
end
|
173
|
+
|
174
|
+
before(:all) do
|
175
|
+
ActiveRecord::Base.connection.add_column(:widgets, :custom_id, :string, if_not_exists: true)
|
176
|
+
Widget.reset_column_information
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should save item to widget and associated detail' do
|
180
|
+
stub_const('MyBatchConsumer', consumer_class)
|
181
|
+
publish_batch([{ key: 2,
|
182
|
+
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
183
|
+
expect(Widget.count).to eq(2)
|
184
|
+
expect(Detail.count).to eq(1)
|
185
|
+
expect(Widget.last.id).to eq(Detail.first.widget_id)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'with one-to-many relationship in association and default bulk_import_id' do
|
190
|
+
before(:each) do
|
191
|
+
consumer_class.config[:bulk_import_id_column] = :bulk_import_id
|
192
|
+
consumer_class.config[:replace_associations] = false
|
193
|
+
consumer_class.record_attributes_proc = proc do |payload|
|
194
|
+
{
|
195
|
+
test_id: payload['test_id'],
|
196
|
+
some_int: payload['some_int'],
|
197
|
+
locales: [
|
198
|
+
{
|
199
|
+
title: payload['title'],
|
200
|
+
language: 'en'
|
201
|
+
},
|
202
|
+
{
|
203
|
+
title: payload['title'],
|
204
|
+
language: 'fr'
|
205
|
+
}
|
206
|
+
]
|
207
|
+
}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'should save item to widget and associated details' do
|
212
|
+
stub_const('MyBatchConsumer', consumer_class)
|
213
|
+
publish_batch([{ key: 2,
|
214
|
+
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
215
|
+
expect(Widget.count).to eq(2)
|
216
|
+
expect(Locale.count).to eq(2)
|
217
|
+
expect(Widget.last.id).to eq(Locale.first.widget_id)
|
218
|
+
expect(Widget.last.id).to eq(Locale.second.widget_id)
|
219
|
+
|
220
|
+
# publish again - should add locales to the widget
|
221
|
+
publish_batch([{ key: 2,
|
222
|
+
payload: { test_id: 'xyz', some_int: 7, title: 'Widget Title 2' } }])
|
223
|
+
expect(Widget.count).to eq(2)
|
224
|
+
expect(Widget.last.some_int).to eq(7)
|
225
|
+
expect(Locale.count).to eq(4)
|
226
|
+
expect(Locale.all.map(&:widget_id).uniq).to eq([Widget.last.id])
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context 'with replace_associations on' do
|
231
|
+
before(:each) do
|
232
|
+
consumer_class.config[:bulk_import_id_column] = :bulk_import_id
|
233
|
+
consumer_class.config[:replace_associations] = true
|
234
|
+
consumer_class.record_attributes_proc = proc do |payload|
|
235
|
+
{
|
236
|
+
test_id: payload['test_id'],
|
237
|
+
some_int: payload['some_int'],
|
238
|
+
locales: [
|
239
|
+
{
|
240
|
+
title: payload['title'],
|
241
|
+
language: 'en'
|
242
|
+
},
|
243
|
+
{
|
244
|
+
title: payload['title'],
|
245
|
+
language: 'fr'
|
246
|
+
}
|
247
|
+
]
|
248
|
+
}
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'should save item to widget and replace associated details' do
|
253
|
+
stub_const('MyBatchConsumer', consumer_class)
|
254
|
+
publish_batch([{ key: 2,
|
255
|
+
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
256
|
+
expect(Widget.count).to eq(2)
|
257
|
+
expect(Locale.count).to eq(2)
|
258
|
+
expect(Widget.last.id).to eq(Locale.first.widget_id)
|
259
|
+
expect(Widget.last.id).to eq(Locale.second.widget_id)
|
260
|
+
|
261
|
+
# publish again - should replace locales
|
262
|
+
publish_batch([{ key: 2,
|
263
|
+
payload: { test_id: 'xyz', some_int: 7, title: 'Widget Title 2' } }])
|
264
|
+
expect(Widget.count).to eq(2)
|
265
|
+
expect(Widget.last.some_int).to eq(7)
|
266
|
+
expect(Locale.count).to eq(2)
|
267
|
+
expect(Locale.all.map(&:title).uniq).to contain_exactly('Widget Title 2')
|
268
|
+
expect(Locale.all.map(&:widget_id).uniq).to contain_exactly(Widget.last.id)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context 'with invalid models' do
|
273
|
+
before(:each) do
|
274
|
+
consumer_class.config[:bulk_import_id_column] = :bulk_import_id
|
275
|
+
consumer_class.should_consume_proc = proc { |val| val.some_int <= 10 }
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should only save valid models' do
|
279
|
+
stub_const('MyBatchConsumer', consumer_class)
|
280
|
+
publish_batch([{ key: 2,
|
281
|
+
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } },
|
282
|
+
{ key: 3,
|
283
|
+
payload: { test_id: 'abc', some_int: 15, title: 'Widget Title 2' } }])
|
284
|
+
expect(Widget.count).to eq(2)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
@@ -337,6 +337,9 @@ module ActiveRecordBatchConsumerTest
|
|
337
337
|
Widget.create!(test_id: 'xxx', some_int: 2, part_one: 'ghi', part_two: 'jkl')
|
338
338
|
Widget.create!(test_id: 'yyy', some_int: 7, part_one: 'mno', part_two: 'pqr')
|
339
339
|
|
340
|
+
allow_any_instance_of(MyBatchConsumer).to receive(:key_columns).
|
341
|
+
and_return(%w(part_one part_two))
|
342
|
+
|
340
343
|
publish_batch(
|
341
344
|
[
|
342
345
|
{ key: { part_one: 'abc', part_two: 'def' }, # To be created
|
@@ -488,24 +491,5 @@ module ActiveRecordBatchConsumerTest
|
|
488
491
|
end
|
489
492
|
end
|
490
493
|
|
491
|
-
describe 'association_list feature for SQLite database' do
|
492
|
-
let(:consumer_class) do
|
493
|
-
Class.new(described_class) do
|
494
|
-
schema 'MySchema'
|
495
|
-
namespace 'com.my-namespace'
|
496
|
-
key_config plain: true
|
497
|
-
record_class Widget
|
498
|
-
association_list :locales
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
it 'should throw NotImplemented error' do
|
503
|
-
stub_const('MyBatchConsumer', consumer_class)
|
504
|
-
expect {
|
505
|
-
publish_batch([{ key: 2, payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
506
|
-
}.to raise_error(Deimos::MissingImplementationError)
|
507
|
-
end
|
508
|
-
end
|
509
|
-
|
510
494
|
end
|
511
495
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
ActiveRecord::Base.connection.create_table(:widgets, force: true) do |t|
|
7
|
+
t.string(:test_id)
|
8
|
+
t.integer(:some_int)
|
9
|
+
t.string(:bulk_import_id)
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
# create one-to-one association -- Details
|
14
|
+
ActiveRecord::Base.connection.create_table(:details, force: true) do |t|
|
15
|
+
t.string(:title)
|
16
|
+
t.string(:bulk_import_id)
|
17
|
+
t.belongs_to(:widget)
|
18
|
+
|
19
|
+
t.index(%i(title), unique: true)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:all) do
|
24
|
+
ActiveRecord::Base.connection.drop_table(:widgets)
|
25
|
+
ActiveRecord::Base.connection.drop_table(:details)
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:detail_class) do
|
29
|
+
Class.new(ActiveRecord::Base) do
|
30
|
+
self.table_name = 'details'
|
31
|
+
belongs_to :widget
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:widget_class) do
|
36
|
+
Class.new(ActiveRecord::Base) do
|
37
|
+
self.table_name = 'widgets'
|
38
|
+
has_one :detail
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
before(:each) do
|
43
|
+
stub_const('Widget', widget_class)
|
44
|
+
stub_const('Detail', detail_class)
|
45
|
+
Widget.reset_column_information
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#mass_update' do
|
49
|
+
let(:batch) do
|
50
|
+
Deimos::ActiveRecordConsume::BatchRecordList.new(
|
51
|
+
[
|
52
|
+
Deimos::ActiveRecordConsume::BatchRecord.new(
|
53
|
+
klass: Widget,
|
54
|
+
attributes: { test_id: 'id1', some_int: 5, detail: { title: 'Title 1' } },
|
55
|
+
bulk_import_column: 'bulk_import_id'
|
56
|
+
),
|
57
|
+
Deimos::ActiveRecordConsume::BatchRecord.new(
|
58
|
+
klass: Widget,
|
59
|
+
attributes: { test_id: 'id2', some_int: 10, detail: { title: 'Title 2' } },
|
60
|
+
bulk_import_column: 'bulk_import_id'
|
61
|
+
)
|
62
|
+
]
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should mass update the batch' do
|
67
|
+
described_class.new(Widget).mass_update(batch)
|
68
|
+
expect(Widget.count).to eq(2)
|
69
|
+
expect(Detail.count).to eq(2)
|
70
|
+
expect(Widget.first.detail).not_to be_nil
|
71
|
+
expect(Widget.last.detail).not_to be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deimos-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.22'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro_turf
|
@@ -410,7 +410,6 @@ files:
|
|
410
410
|
- ".rubocop_todo.yml"
|
411
411
|
- ".ruby-version"
|
412
412
|
- CHANGELOG.md
|
413
|
-
- CHANGELOG.md.orig
|
414
413
|
- CODE_OF_CONDUCT.md
|
415
414
|
- Dockerfile
|
416
415
|
- Gemfile
|
@@ -431,7 +430,10 @@ files:
|
|
431
430
|
- docs/UPGRADING.md
|
432
431
|
- lib/deimos.rb
|
433
432
|
- lib/deimos/active_record_consume/batch_consumption.rb
|
433
|
+
- lib/deimos/active_record_consume/batch_record.rb
|
434
|
+
- lib/deimos/active_record_consume/batch_record_list.rb
|
434
435
|
- lib/deimos/active_record_consume/batch_slicer.rb
|
436
|
+
- lib/deimos/active_record_consume/mass_updater.rb
|
435
437
|
- lib/deimos/active_record_consume/message_consumption.rb
|
436
438
|
- lib/deimos/active_record_consume/schema_model_converter.rb
|
437
439
|
- lib/deimos/active_record_consumer.rb
|
@@ -509,10 +511,11 @@ files:
|
|
509
511
|
- sig/avro.rbs
|
510
512
|
- sig/defs.rbs
|
511
513
|
- sig/fig_tree.rbs
|
512
|
-
- spec/
|
514
|
+
- spec/active_record_batch_consumer_association_spec.rb
|
513
515
|
- spec/active_record_batch_consumer_spec.rb
|
514
516
|
- spec/active_record_consume/batch_consumption_spec.rb
|
515
517
|
- spec/active_record_consume/batch_slicer_spec.rb
|
518
|
+
- spec/active_record_consume/mass_updater_spec.rb
|
516
519
|
- spec/active_record_consume/schema_model_converter_spec.rb
|
517
520
|
- spec/active_record_consumer_spec.rb
|
518
521
|
- spec/active_record_producer_spec.rb
|
@@ -635,10 +638,11 @@ signing_key:
|
|
635
638
|
specification_version: 4
|
636
639
|
summary: Kafka libraries for Ruby.
|
637
640
|
test_files:
|
638
|
-
- spec/
|
641
|
+
- spec/active_record_batch_consumer_association_spec.rb
|
639
642
|
- spec/active_record_batch_consumer_spec.rb
|
640
643
|
- spec/active_record_consume/batch_consumption_spec.rb
|
641
644
|
- spec/active_record_consume/batch_slicer_spec.rb
|
645
|
+
- spec/active_record_consume/mass_updater_spec.rb
|
642
646
|
- spec/active_record_consume/schema_model_converter_spec.rb
|
643
647
|
- spec/active_record_consumer_spec.rb
|
644
648
|
- spec/active_record_producer_spec.rb
|