deimos-ruby 1.20.1 → 1.22.1
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 +12 -0
- data/README.md +23 -16
- data/docs/CONFIGURATION.md +2 -0
- data/lib/deimos/active_record_consume/batch_consumption.rb +81 -151
- 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 +284 -0
- data/spec/active_record_batch_consumer_spec.rb +5 -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
@@ -1,244 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActiveRecordBatchConsumerTest
|
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.boolean(:deleted, default: false)
|
17
|
-
t.timestamps
|
18
|
-
|
19
|
-
t.index(%i(part_one part_two), unique: true)
|
20
|
-
end
|
21
|
-
|
22
|
-
# create one-to-one association -- Details
|
23
|
-
ActiveRecord::Base.connection.create_table(:details, force: true) do |t|
|
24
|
-
t.string(:title)
|
25
|
-
t.belongs_to(:widget)
|
26
|
-
|
27
|
-
t.index(%i(title), unique: true)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Create one-to-many association Locales
|
31
|
-
ActiveRecord::Base.connection.create_table(:locales, force: true) do |t|
|
32
|
-
t.string(:title)
|
33
|
-
t.string(:language)
|
34
|
-
t.belongs_to(:widget)
|
35
|
-
|
36
|
-
t.index(%i(title language), unique: true)
|
37
|
-
end
|
38
|
-
|
39
|
-
class Detail < ActiveRecord::Base
|
40
|
-
validates :title, presence: true
|
41
|
-
end
|
42
|
-
|
43
|
-
class Locale < ActiveRecord::Base
|
44
|
-
validates :title, presence: true
|
45
|
-
validates :language, presence: true
|
46
|
-
end
|
47
|
-
|
48
|
-
# Sample model
|
49
|
-
class Widget < ActiveRecord::Base
|
50
|
-
has_one :detail
|
51
|
-
has_many :locales
|
52
|
-
validates :test_id, presence: true
|
53
|
-
|
54
|
-
default_scope -> { where(deleted: false) }
|
55
|
-
end
|
56
|
-
|
57
|
-
Widget.reset_column_information
|
58
|
-
Detail.reset_column_information
|
59
|
-
Locale.reset_column_information
|
60
|
-
end
|
61
|
-
|
62
|
-
after(:all) do
|
63
|
-
ActiveRecord::Base.connection.drop_table(:widgets)
|
64
|
-
ActiveRecord::Base.connection.drop_table(:details)
|
65
|
-
ActiveRecord::Base.connection.drop_table(:locales)
|
66
|
-
end
|
67
|
-
|
68
|
-
before(:each) do
|
69
|
-
ActiveRecord::Base.connection.truncate_tables(%i(widgets details locales))
|
70
|
-
end
|
71
|
-
|
72
|
-
prepend_before(:each) do
|
73
|
-
stub_const('MyBatchConsumer', consumer_class)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Helper to publish a list of messages and call the consumer
|
77
|
-
def publish_batch(messages)
|
78
|
-
keys = messages.map { |m| m[:key] }
|
79
|
-
payloads = messages.map { |m| m[:payload] }
|
80
|
-
|
81
|
-
test_consume_batch(MyBatchConsumer, payloads, keys: keys, call_original: true)
|
82
|
-
end
|
83
|
-
|
84
|
-
context 'when association_list configured in consumer without model changes' do
|
85
|
-
let(:consumer_class) do
|
86
|
-
Class.new(described_class) do
|
87
|
-
schema 'MySchema'
|
88
|
-
namespace 'com.my-namespace'
|
89
|
-
key_config plain: true
|
90
|
-
record_class Widget
|
91
|
-
association_list :detail
|
92
|
-
|
93
|
-
def build_records(messages)
|
94
|
-
messages.map do |m|
|
95
|
-
payload = m.payload
|
96
|
-
w = Widget.new(test_id: payload['test_id'], some_int: payload['some_int'])
|
97
|
-
d = Detail.new(title: payload['title'])
|
98
|
-
w.detail = d
|
99
|
-
w
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should raise error when bulk_import_id is not found' do
|
106
|
-
stub_const('MyBatchConsumer', consumer_class)
|
107
|
-
expect {
|
108
|
-
publish_batch([{ key: 2,
|
109
|
-
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
110
|
-
}.to raise_error('Create bulk_import_id on ActiveRecordBatchConsumerTest::Widget'\
|
111
|
-
' and set it in `build_records` for associations. Run rails g deimos:bulk_import_id {table}'\
|
112
|
-
' to create the migration.')
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context 'with one-to-one relation in association_list and custom bulk_import_id' do
|
117
|
-
let(:consumer_class) do
|
118
|
-
Class.new(described_class) do
|
119
|
-
schema 'MySchema'
|
120
|
-
namespace 'com.my-namespace'
|
121
|
-
key_config plain: true
|
122
|
-
record_class Widget
|
123
|
-
association_list :detail
|
124
|
-
bulk_import_id_column :custom_id
|
125
|
-
|
126
|
-
def build_records(messages)
|
127
|
-
messages.map do |m|
|
128
|
-
payload = m.payload
|
129
|
-
w = Widget.new(test_id: payload['test_id'],
|
130
|
-
some_int: payload['some_int'],
|
131
|
-
custom_id: SecureRandom.uuid)
|
132
|
-
d = Detail.new(title: payload['title'])
|
133
|
-
w.detail = d
|
134
|
-
w
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def key_columns(messages, klass)
|
139
|
-
case klass.to_s
|
140
|
-
when Widget.to_s
|
141
|
-
super
|
142
|
-
when Detail.to_s
|
143
|
-
%w(title widget_id)
|
144
|
-
else
|
145
|
-
[]
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def columns(record_class)
|
150
|
-
all_cols = record_class.columns.map(&:name)
|
151
|
-
|
152
|
-
case record_class.to_s
|
153
|
-
when Widget.to_s
|
154
|
-
super
|
155
|
-
when Detail.to_s
|
156
|
-
all_cols - ['id']
|
157
|
-
else
|
158
|
-
[]
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
before(:all) do
|
165
|
-
ActiveRecord::Base.connection.add_column(:widgets, :custom_id, :string, if_not_exists: true)
|
166
|
-
Widget.reset_column_information
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'should save item to widget and associated detail' do
|
170
|
-
stub_const('MyBatchConsumer', consumer_class)
|
171
|
-
publish_batch([{ key: 2,
|
172
|
-
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
173
|
-
expect(Widget.count).to eq(1)
|
174
|
-
expect(Detail.count).to eq(1)
|
175
|
-
expect(Widget.first.id).to eq(Detail.first.widget_id)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context 'with one-to-many relationship in association_list and default bulk_import_id' do
|
180
|
-
let(:consumer_class) do
|
181
|
-
Class.new(described_class) do
|
182
|
-
schema 'MySchema'
|
183
|
-
namespace 'com.my-namespace'
|
184
|
-
key_config plain: true
|
185
|
-
record_class Widget
|
186
|
-
association_list :locales
|
187
|
-
|
188
|
-
def build_records(messages)
|
189
|
-
messages.map do |m|
|
190
|
-
payload = m.payload
|
191
|
-
w = Widget.new(test_id: payload['test_id'],
|
192
|
-
some_int: payload['some_int'],
|
193
|
-
bulk_import_id: SecureRandom.uuid)
|
194
|
-
w.locales << Locale.new(title: payload['title'], language: 'en')
|
195
|
-
w.locales << Locale.new(title: payload['title'], language: 'fr')
|
196
|
-
w
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def key_columns(messages, klass)
|
201
|
-
case klass.to_s
|
202
|
-
when Widget.to_s
|
203
|
-
super
|
204
|
-
when Detail.to_s
|
205
|
-
%w(title widget_id)
|
206
|
-
when Locale.to_s
|
207
|
-
%w(title language)
|
208
|
-
else
|
209
|
-
[]
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def columns(record_class)
|
214
|
-
all_cols = record_class.columns.map(&:name)
|
215
|
-
|
216
|
-
case record_class.to_s
|
217
|
-
when Widget.to_s
|
218
|
-
super
|
219
|
-
when Detail.to_s, Locale.to_s
|
220
|
-
all_cols - ['id']
|
221
|
-
else
|
222
|
-
[]
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
before(:all) do
|
229
|
-
ActiveRecord::Base.connection.add_column(:widgets, :bulk_import_id, :string, if_not_exists: true)
|
230
|
-
Widget.reset_column_information
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'should save item to widget and associated details' do
|
234
|
-
stub_const('MyBatchConsumer', consumer_class)
|
235
|
-
publish_batch([{ key: 2,
|
236
|
-
payload: { test_id: 'xyz', some_int: 5, title: 'Widget Title' } }])
|
237
|
-
expect(Widget.count).to eq(1)
|
238
|
-
expect(Locale.count).to eq(2)
|
239
|
-
expect(Widget.first.id).to eq(Locale.first.widget_id)
|
240
|
-
expect(Widget.first.id).to eq(Locale.second.widget_id)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|