deimos-ruby 1.22.5 → 1.23.1.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -96,12 +96,17 @@ module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
96
96
  key_config plain: true
97
97
  record_class Widget
98
98
 
99
- def should_consume?(record)
99
+ def should_consume?(record, associations)
100
100
  if self.should_consume_proc
101
- return self.should_consume_proc.call(record)
101
+ case self.should_consume_proc.parameters.size
102
+ when 2
103
+ self.should_consume_proc.call(record, associations)
104
+ else
105
+ self.should_consume_proc.call(record)
106
+ end
107
+ else
108
+ true
102
109
  end
103
-
104
- true
105
110
  end
106
111
 
107
112
  def record_attributes(payload, _key)
@@ -269,7 +274,7 @@ module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
269
274
 
270
275
  context 'with invalid models' do
271
276
  before(:each) do
272
- consumer_class.should_consume_proc = proc { |val| val.some_int <= 10 }
277
+ consumer_class.should_consume_proc = proc { |record| record.some_int <= 10 }
273
278
  end
274
279
 
275
280
  it 'should only save valid models' do
@@ -280,5 +285,27 @@ module ActiveRecordBatchConsumerTest # rubocop:disable Metrics/ModuleLength
280
285
  expect(Widget.count).to eq(2)
281
286
  end
282
287
  end
288
+
289
+ context 'with invalid associations' do
290
+
291
+ before(:each) do
292
+ consumer_class.should_consume_proc = proc { |record, associations|
293
+ record.some_int <= 10 && associations['detail']['title'] != 'invalid'
294
+ }
295
+ end
296
+
297
+ it 'should only save valid associations' do
298
+ publish_batch([
299
+ { key: 2,
300
+ payload: { test_id: 'xyz', some_int: 5, title: 'valid' } },
301
+ { key: 3,
302
+ payload: { test_id: 'abc', some_int: 15, title: 'valid' } },
303
+ { key: 4,
304
+ payload: { test_id: 'abc', some_int: 9, title: 'invalid' } }
305
+ ])
306
+ expect(Widget.count).to eq(2)
307
+ expect(Widget.second.some_int).to eq(5)
308
+ end
309
+ end
283
310
  end
284
311
  end
@@ -11,6 +11,7 @@ module ActiveRecordBatchConsumerTest
11
11
  t.string(:part_two)
12
12
  t.integer(:some_int)
13
13
  t.boolean(:deleted, default: false)
14
+ t.string(:bulk_import_id)
14
15
  t.timestamps
15
16
 
16
17
  t.index(%i(part_one part_two), unique: true)
@@ -73,8 +74,12 @@ module ActiveRecordBatchConsumerTest
73
74
  describe 'consume_batch' do
74
75
  SCHEMA_CLASS_SETTINGS.each do |setting, use_schema_classes|
75
76
  context "with Schema Class consumption #{setting}" do
77
+
76
78
  before(:each) do
77
- Deimos.configure { |config| config.schema.use_schema_classes = use_schema_classes }
79
+ Deimos.configure do |config|
80
+ config.schema.use_schema_classes = use_schema_classes
81
+ config.schema.generate_namespace_folders = true
82
+ end
78
83
  end
79
84
 
80
85
  it 'should handle an empty batch' do
@@ -205,6 +210,48 @@ module ActiveRecordBatchConsumerTest
205
210
  ]
206
211
  )
207
212
  end
213
+
214
+ it 'should handle deletes with deadlock retries' do
215
+ allow(Deimos::Utils::DeadlockRetry).to receive(:sleep)
216
+ allow(instance_double(ActiveRecord::Relation)).to receive(:delete_all).and_raise(
217
+ ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')
218
+ ).twice.ordered
219
+
220
+ Widget.create!(id: 1, test_id: 'abc', some_int: 2)
221
+
222
+ publish_batch(
223
+ [
224
+ { key: 1,
225
+ payload: nil },
226
+ { key: 1,
227
+ payload: nil }
228
+ ]
229
+ )
230
+
231
+ expect(all_widgets).to be_empty
232
+ end
233
+
234
+ it 'should not delete after multiple deadlock retries' do
235
+ allow(Deimos::Utils::DeadlockRetry).to receive(:sleep)
236
+ allow(instance_double(ActiveRecord::Relation)).to receive(:delete_all).and_raise(
237
+ ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')
238
+ ).exactly(3).times
239
+
240
+ Widget.create!(id: 1, test_id: 'abc', some_int: 2)
241
+
242
+ publish_batch(
243
+ [
244
+ { key: 1,
245
+ payload: nil },
246
+ { key: 1,
247
+ payload: nil }
248
+ ]
249
+ )
250
+
251
+ expect(Widget.count).to eq(0)
252
+
253
+ end
254
+
208
255
  end
209
256
  end
210
257
  end
@@ -254,64 +301,6 @@ module ActiveRecordBatchConsumerTest
254
301
  end
255
302
  end
256
303
 
257
- describe 'batch atomicity' do
258
- it 'should roll back if there was an exception while deleting' do
259
- Widget.create!(id: 1, test_id: 'abc', some_int: 2)
260
-
261
- travel 1.day
262
-
263
- expect(Widget.connection).to receive(:delete).and_raise('Some error')
264
-
265
- expect {
266
- publish_batch(
267
- [
268
- { key: 1,
269
- payload: { test_id: 'def', some_int: 3 } },
270
- { key: 1,
271
- payload: nil }
272
- ]
273
- )
274
- }.to raise_error('Some error')
275
-
276
- expect(all_widgets).
277
- to match_array(
278
- [
279
- have_attributes(id: 1, test_id: 'abc', some_int: 2, updated_at: start, created_at: start)
280
- ]
281
- )
282
- end
283
-
284
- it 'should roll back if there was an invalid instance while upserting' do
285
- Widget.create!(id: 1, test_id: 'abc', some_int: 2) # Updated but rolled back
286
- Widget.create!(id: 3, test_id: 'ghi', some_int: 3) # Removed but rolled back
287
-
288
- travel 1.day
289
-
290
- expect {
291
- publish_batch(
292
- [
293
- { key: 1,
294
- payload: { test_id: 'def', some_int: 3 } },
295
- { key: 2,
296
- payload: nil },
297
- { key: 2,
298
- payload: { test_id: '', some_int: 4 } }, # Empty string is not valid for test_id
299
- { key: 3,
300
- payload: nil }
301
- ]
302
- )
303
- }.to raise_error(ActiveRecord::RecordInvalid)
304
-
305
- expect(all_widgets).
306
- to match_array(
307
- [
308
- have_attributes(id: 1, test_id: 'abc', some_int: 2, updated_at: start, created_at: start),
309
- have_attributes(id: 3, test_id: 'ghi', some_int: 3, updated_at: start, created_at: start)
310
- ]
311
- )
312
- end
313
- end
314
-
315
304
  describe 'compound keys' do
316
305
  let(:consumer_class) do
317
306
  Class.new(described_class) do
@@ -493,5 +482,333 @@ module ActiveRecordBatchConsumerTest
493
482
  end
494
483
  end
495
484
 
485
+ describe 'pre processing' do
486
+ context 'with uncompacted messages' do
487
+ let(:consumer_class) do
488
+ Class.new(described_class) do
489
+ schema 'MySchema'
490
+ namespace 'com.my-namespace'
491
+ key_config plain: true
492
+ record_class Widget
493
+ compacted false
494
+
495
+ def pre_process(messages)
496
+ messages.each do |message|
497
+ message.payload[:some_int] = -message.payload[:some_int]
498
+ end
499
+ end
500
+
501
+ end
502
+ end
503
+
504
+ it 'should pre-process records' do
505
+ Widget.create!(id: 1, test_id: 'abc', some_int: 1)
506
+ Widget.create!(id: 2, test_id: 'def', some_int: 2)
507
+
508
+ publish_batch(
509
+ [
510
+ { key: 1,
511
+ payload: { test_id: 'abc', some_int: 11 } },
512
+ { key: 2,
513
+ payload: { test_id: 'def', some_int: 20 } }
514
+ ]
515
+ )
516
+
517
+ widget_one, widget_two = Widget.all.to_a
518
+
519
+ expect(widget_one.some_int).to eq(-11)
520
+ expect(widget_two.some_int).to eq(-20)
521
+ end
522
+ end
523
+ end
524
+
525
+ describe 'global configurations' do
526
+
527
+ context 'with a global bulk_import_id_generator' do
528
+
529
+ before(:each) do
530
+ Deimos.configure do
531
+ consumers.bulk_import_id_generator(proc { 'global' })
532
+ end
533
+ end
534
+
535
+ it 'should call the default bulk_import_id_generator proc' do
536
+ publish_batch(
537
+ [
538
+ { key: 1,
539
+ payload: { test_id: 'abc', some_int: 3 } }
540
+ ]
541
+ )
542
+
543
+ expect(all_widgets).
544
+ to match_array(
545
+ [
546
+ have_attributes(id: 1,
547
+ test_id: 'abc',
548
+ some_int: 3,
549
+ updated_at: start,
550
+ created_at: start,
551
+ bulk_import_id: 'global')
552
+ ]
553
+ )
554
+
555
+ end
556
+
557
+ end
558
+
559
+ context 'with a class defined bulk_import_id_generator' do
560
+
561
+ before(:each) do
562
+ Deimos.configure do
563
+ consumers.bulk_import_id_generator(proc { 'global' })
564
+ end
565
+ consumer_class.config[:bulk_import_id_generator] = proc { 'custom' }
566
+ end
567
+
568
+ it 'should call the default bulk_import_id_generator proc' do
569
+
570
+ publish_batch(
571
+ [
572
+ { key: 1,
573
+ payload: { test_id: 'abc', some_int: 3 } }
574
+ ]
575
+ )
576
+
577
+ expect(all_widgets).
578
+ to match_array(
579
+ [
580
+ have_attributes(id: 1,
581
+ test_id: 'abc',
582
+ some_int: 3,
583
+ updated_at: start,
584
+ created_at: start,
585
+ bulk_import_id: 'custom')
586
+ ]
587
+ )
588
+
589
+ end
590
+ end
591
+
592
+ end
593
+
594
+ describe 'should_consume?' do
595
+
596
+ let(:consumer_class) do
597
+ Class.new(described_class) do
598
+ schema 'MySchema'
599
+ namespace 'com.my-namespace'
600
+ key_config plain: true
601
+ record_class Widget
602
+ compacted false
603
+
604
+ def should_consume?(record)
605
+ record.test_id != 'def'
606
+ end
607
+
608
+ def self.process_invalid_records(_)
609
+ nil
610
+ end
611
+
612
+ ActiveSupport::Notifications.subscribe('batch_consumption.invalid_records') do |*args|
613
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
614
+ payload[:consumer].process_invalid_records(payload[:records])
615
+ end
616
+
617
+ end
618
+ end
619
+
620
+ it "should skip records that shouldn't be consumed" do
621
+ Widget.create!(id: 1, test_id: 'abc', some_int: 1)
622
+ Widget.create!(id: 2, test_id: 'def', some_int: 2)
623
+ publish_batch(
624
+ [
625
+ { key: 1,
626
+ payload: { test_id: 'abc', some_int: 11 } },
627
+ { key: 2,
628
+ payload: { test_id: 'def', some_int: 20 } }
629
+ ]
630
+ )
631
+
632
+ expect(Widget.count).to eq(2)
633
+ expect(Widget.all.to_a).to match_array([
634
+ have_attributes(id: 1,
635
+ test_id: 'abc',
636
+ some_int: 11,
637
+ updated_at: start,
638
+ created_at: start),
639
+ have_attributes(id: 2,
640
+ test_id: 'def',
641
+ some_int: 2,
642
+ updated_at: start,
643
+ created_at: start)
644
+ ])
645
+ end
646
+
647
+ end
648
+
649
+ describe 'post processing' do
650
+
651
+ context 'with uncompacted messages' do
652
+ let(:consumer_class) do
653
+ Class.new(described_class) do
654
+ schema 'MySchema'
655
+ namespace 'com.my-namespace'
656
+ key_config plain: true
657
+ record_class Widget
658
+ compacted false
659
+
660
+ def should_consume?(record)
661
+ record.some_int.even?
662
+ end
663
+
664
+ def self.process_valid_records(valid)
665
+ # Success
666
+ attrs = valid.first.attributes
667
+ Widget.find_by(id: attrs['id'], test_id: attrs['test_id']).update!(some_int: 2000)
668
+ end
669
+
670
+ def self.process_invalid_records(invalid)
671
+ # Invalid
672
+ attrs = invalid.first.record.attributes
673
+ Widget.find_by(id: attrs['id'], test_id: attrs['test_id']).update!(some_int: attrs['some_int'])
674
+ end
675
+
676
+ ActiveSupport::Notifications.subscribe('batch_consumption.invalid_records') do |*args|
677
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
678
+ payload[:consumer].process_invalid_records(payload[:records])
679
+ end
680
+
681
+ ActiveSupport::Notifications.subscribe('batch_consumption.valid_records') do |*args|
682
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
683
+ payload[:consumer].process_valid_records(payload[:records])
684
+ end
685
+
686
+ end
687
+ end
688
+
689
+ it 'should process successful and failed records' do
690
+ Widget.create!(id: 1, test_id: 'abc', some_int: 1)
691
+ Widget.create!(id: 2, test_id: 'def', some_int: 2)
692
+
693
+ publish_batch(
694
+ [
695
+ { key: 1,
696
+ payload: { test_id: 'abc', some_int: 11 } },
697
+ { key: 2,
698
+ payload: { test_id: 'def', some_int: 20 } }
699
+ ]
700
+ )
701
+
702
+ widget_one, widget_two = Widget.all.to_a
703
+
704
+ expect(widget_one.some_int).to eq(11)
705
+ expect(widget_two.some_int).to eq(2000)
706
+ end
707
+ end
708
+
709
+ context 'with compacted messages' do
710
+ let(:consumer_class) do
711
+ Class.new(described_class) do
712
+ schema 'MySchema'
713
+ namespace 'com.my-namespace'
714
+ key_config plain: true
715
+ record_class Widget
716
+ compacted true
717
+
718
+ def should_consume?(record)
719
+ record.some_int.even?
720
+ end
721
+
722
+ def self.process_valid_records(valid)
723
+ # Success
724
+ attrs = valid.first.attributes
725
+ Widget.find_by(id: attrs['id'], test_id: attrs['test_id']).update!(some_int: 2000)
726
+ end
727
+
728
+ def self.process_invalid_records(invalid)
729
+ # Invalid
730
+ attrs = invalid.first.record.attributes
731
+ Widget.find_by(id: attrs['id'], test_id: attrs['test_id']).update!(some_int: attrs['some_int'])
732
+ end
733
+
734
+ ActiveSupport::Notifications.subscribe('batch_consumption.invalid_records') do |*args|
735
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
736
+ payload[:consumer].process_invalid_records(payload[:records])
737
+ end
738
+
739
+ ActiveSupport::Notifications.subscribe('batch_consumption.valid_records') do |*args|
740
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
741
+ payload[:consumer].process_valid_records(payload[:records])
742
+ end
743
+
744
+ end
745
+ end
746
+
747
+ it 'should process successful and failed records' do
748
+ Widget.create!(id: 1, test_id: 'abc', some_int: 1)
749
+ Widget.create!(id: 2, test_id: 'def', some_int: 2)
750
+
751
+ publish_batch(
752
+ [
753
+ { key: 1,
754
+ payload: { test_id: 'abc', some_int: 11 } },
755
+ { key: 2,
756
+ payload: { test_id: 'def', some_int: 20 } }
757
+ ]
758
+ )
759
+
760
+ widget_one, widget_two = Widget.all.to_a
761
+
762
+ expect(widget_one.some_int).to eq(11)
763
+ expect(widget_two.some_int).to eq(2000)
764
+ end
765
+ end
766
+
767
+ context 'with post processing errors' do
768
+ let(:consumer_class) do
769
+ Class.new(described_class) do
770
+ schema 'MySchema'
771
+ namespace 'com.my-namespace'
772
+ key_config plain: true
773
+ record_class Widget
774
+ compacted false
775
+
776
+ def self.process_valid_records(_)
777
+ raise StandardError, 'Something went wrong'
778
+ end
779
+
780
+ ActiveSupport::Notifications.subscribe('batch_consumption.valid_records') do |*args|
781
+ payload = ActiveSupport::Notifications::Event.new(*args).payload
782
+ payload[:consumer].process_valid_records(payload[:records])
783
+ end
784
+
785
+ end
786
+ end
787
+
788
+ it 'should save records if an exception occurs in post processing' do
789
+ Widget.create!(id: 1, test_id: 'abc', some_int: 1)
790
+ Widget.create!(id: 2, test_id: 'def', some_int: 2)
791
+
792
+ expect {
793
+ publish_batch(
794
+ [
795
+ { key: 1,
796
+ payload: { test_id: 'abc', some_int: 11 } },
797
+ { key: 2,
798
+ payload: { test_id: 'def', some_int: 20 } }
799
+ ]
800
+ )
801
+ }.to raise_error(StandardError, 'Something went wrong')
802
+
803
+ widget_one, widget_two = Widget.all.to_a
804
+
805
+ expect(widget_one.some_int).to eq(11)
806
+ expect(widget_two.some_int).to eq(20)
807
+
808
+ end
809
+ end
810
+
811
+ end
812
+
496
813
  end
497
814
  end
@@ -39,6 +39,8 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
39
39
  end
40
40
  end
41
41
 
42
+ let(:bulk_id_generator) { proc { SecureRandom.uuid } }
43
+
42
44
  before(:each) do
43
45
  stub_const('Widget', widget_class)
44
46
  stub_const('Detail', detail_class)
@@ -52,24 +54,65 @@ RSpec.describe Deimos::ActiveRecordConsume::MassUpdater do
52
54
  Deimos::ActiveRecordConsume::BatchRecord.new(
53
55
  klass: Widget,
54
56
  attributes: { test_id: 'id1', some_int: 5, detail: { title: 'Title 1' } },
55
- bulk_import_column: 'bulk_import_id'
57
+ bulk_import_column: 'bulk_import_id',
58
+ bulk_import_id_generator: bulk_id_generator
56
59
  ),
57
60
  Deimos::ActiveRecordConsume::BatchRecord.new(
58
61
  klass: Widget,
59
62
  attributes: { test_id: 'id2', some_int: 10, detail: { title: 'Title 2' } },
60
- bulk_import_column: 'bulk_import_id'
63
+ bulk_import_column: 'bulk_import_id',
64
+ bulk_import_id_generator: bulk_id_generator
61
65
  )
62
66
  ]
63
67
  )
64
68
  end
65
69
 
66
70
  it 'should mass update the batch' do
67
- described_class.new(Widget).mass_update(batch)
71
+ allow(SecureRandom).to receive(:uuid).and_return('1', '2')
72
+ results = described_class.new(Widget, bulk_import_id_generator: bulk_id_generator).mass_update(batch)
73
+ expect(results.count).to eq(2)
74
+ expect(results.map(&:test_id)).to match(%w(id1 id2))
68
75
  expect(Widget.count).to eq(2)
76
+ expect(Widget.all.to_a.map(&:bulk_import_id)).to match(%w(1 2))
69
77
  expect(Detail.count).to eq(2)
70
78
  expect(Widget.first.detail).not_to be_nil
71
79
  expect(Widget.last.detail).not_to be_nil
72
80
  end
73
81
 
82
+ context 'with deadlock retries' do
83
+ before(:each) do
84
+ allow(Deimos::Utils::DeadlockRetry).to receive(:sleep)
85
+ end
86
+
87
+ it 'should upsert rows after deadlocks' do
88
+ allow(Widget).to receive(:import!).and_raise(
89
+ ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')
90
+ ).twice.ordered
91
+ allow(Widget).to receive(:import!).and_raise(
92
+ ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')
93
+ ).once.and_call_original
94
+
95
+ results = described_class.new(Widget, bulk_import_id_generator: bulk_id_generator).mass_update(batch)
96
+ expect(results.count).to eq(2)
97
+ expect(results.map(&:test_id)).to match(%w(id1 id2))
98
+ expect(Widget.count).to eq(2)
99
+ expect(Detail.count).to eq(2)
100
+ expect(Widget.first.detail).not_to be_nil
101
+ expect(Widget.last.detail).not_to be_nil
102
+ end
103
+
104
+ it 'should not upsert after encountering multiple deadlocks' do
105
+ allow(Widget).to receive(:import!).and_raise(
106
+ ActiveRecord::Deadlocked.new('Lock wait timeout exceeded')
107
+ ).exactly(3).times
108
+ expect {
109
+ described_class.new(Widget, bulk_import_id_generator: bulk_id_generator).mass_update(batch)
110
+ }.to raise_error(ActiveRecord::Deadlocked)
111
+ expect(Widget.count).to eq(0)
112
+ expect(Detail.count).to eq(0)
113
+ end
114
+
115
+ end
116
+
74
117
  end
75
118
  end
@@ -3,6 +3,7 @@
3
3
  require 'date'
4
4
 
5
5
  # Wrapped in a module to prevent class leakage
6
+ # rubocop:disable Metrics/ModuleLength
6
7
  module ActiveRecordConsumerTest
7
8
  describe Deimos::ActiveRecordConsumer, 'Message Consumer' do
8
9
  before(:all) do
@@ -66,13 +67,84 @@ module ActiveRecordConsumerTest
66
67
  stub_const('MyCustomFetchConsumer', consumer_class)
67
68
 
68
69
  Time.zone = 'Eastern Time (US & Canada)'
70
+
71
+ schema_class = Class.new(Deimos::SchemaClass::Record) do
72
+ def schema
73
+ 'MySchema'
74
+ end
75
+
76
+ def namespace
77
+ 'com.my-namespace'
78
+ end
79
+
80
+ attr_accessor :test_id
81
+ attr_accessor :some_int
82
+
83
+ def initialize(test_id: nil,
84
+ some_int: nil)
85
+ self.test_id = test_id
86
+ self.some_int = some_int
87
+ end
88
+
89
+ def as_json(_opts={})
90
+ {
91
+ 'test_id' => @test_id,
92
+ 'some_int' => @some_int,
93
+ 'payload_key' => @payload_key&.as_json
94
+ }
95
+ end
96
+ end
97
+ stub_const('Schemas::MySchema', schema_class)
98
+
99
+ schema_datetime_class = Class.new(Deimos::SchemaClass::Record) do
100
+ def schema
101
+ 'MySchemaWithDateTimes'
102
+ end
103
+
104
+ def namespace
105
+ 'com.my-namespace'
106
+ end
107
+
108
+ attr_accessor :test_id
109
+ attr_accessor :some_int
110
+ attr_accessor :updated_at
111
+ attr_accessor :some_datetime_int
112
+ attr_accessor :timestamp
113
+
114
+ def initialize(test_id: nil,
115
+ some_int: nil,
116
+ updated_at: nil,
117
+ some_datetime_int: nil,
118
+ timestamp: nil)
119
+ self.test_id = test_id
120
+ self.some_int = some_int
121
+ self.updated_at = updated_at
122
+ self.some_datetime_int = some_datetime_int
123
+ self.timestamp = timestamp
124
+ end
125
+
126
+ def as_json(_opts={})
127
+ {
128
+ 'test_id' => @test_id,
129
+ 'some_int' => @some_int,
130
+ 'updated_at' => @updated_at,
131
+ 'some_datetime_int' => @some_datetime_int,
132
+ 'timestamp' => @timestamp,
133
+ 'payload_key' => @payload_key&.as_json
134
+ }
135
+ end
136
+ end
137
+ stub_const('Schemas::MySchemaWithDateTimes', schema_datetime_class)
69
138
  end
70
139
 
71
140
  describe 'consume' do
72
141
  SCHEMA_CLASS_SETTINGS.each do |setting, use_schema_classes|
73
142
  context "with Schema Class consumption #{setting}" do
74
143
  before(:each) do
75
- Deimos.configure { |config| config.schema.use_schema_classes = use_schema_classes }
144
+ Deimos.configure do |config|
145
+ config.schema.use_schema_classes = use_schema_classes
146
+ config.schema.generate_namespace_folders = true
147
+ end
76
148
  end
77
149
 
78
150
  it 'should receive events correctly' do
@@ -182,3 +254,4 @@ module ActiveRecordConsumerTest
182
254
  end
183
255
  end
184
256
  end
257
+ # rubocop:enable Metrics/ModuleLength