lhm-shopify 3.5.4 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +6 -6
  3. data/Appraisals +8 -13
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile.lock +22 -20
  6. data/README.md +14 -7
  7. data/dev.yml +12 -8
  8. data/docker-compose.yml +2 -0
  9. data/gemfiles/activerecord_6.0.gemfile +1 -1
  10. data/gemfiles/activerecord_6.0.gemfile.lock +25 -21
  11. data/gemfiles/activerecord_6.1.gemfile.lock +17 -13
  12. data/gemfiles/{activerecord_7.0.0.alpha2.gemfile → activerecord_7.0.gemfile} +1 -1
  13. data/gemfiles/{activerecord_7.0.0.alpha2.gemfile.lock → activerecord_7.0.gemfile.lock} +23 -19
  14. data/gemfiles/{activerecord_5.2.gemfile → activerecord_7.1.0.beta1.gemfile} +1 -3
  15. data/gemfiles/activerecord_7.1.0.beta1.gemfile.lock +81 -0
  16. data/lhm.gemspec +1 -1
  17. data/lib/lhm/sql_helper.rb +1 -1
  18. data/lib/lhm/sql_retry.rb +37 -47
  19. data/lib/lhm/throttler/replica_lag.rb +162 -0
  20. data/lib/lhm/throttler/slave_lag.rb +5 -155
  21. data/lib/lhm/throttler/threads_running.rb +3 -1
  22. data/lib/lhm/throttler.rb +7 -3
  23. data/lib/lhm/version.rb +1 -1
  24. data/spec/.lhm.example +1 -1
  25. data/spec/README.md +8 -9
  26. data/spec/integration/atomic_switcher_spec.rb +2 -2
  27. data/spec/integration/chunk_insert_spec.rb +2 -2
  28. data/spec/integration/chunker_spec.rb +33 -38
  29. data/spec/integration/database.yml +1 -1
  30. data/spec/integration/entangler_spec.rb +4 -4
  31. data/spec/integration/integration_helper.rb +12 -12
  32. data/spec/integration/lhm_spec.rb +41 -32
  33. data/spec/integration/locked_switcher_spec.rb +2 -2
  34. data/spec/integration/sql_retry/retry_with_proxysql_spec.rb +6 -5
  35. data/spec/integration/toxiproxy_helper.rb +1 -1
  36. data/spec/test_helper.rb +3 -0
  37. data/spec/unit/printer_spec.rb +2 -6
  38. data/spec/unit/sql_helper_spec.rb +2 -2
  39. data/spec/unit/throttler/{slave_lag_spec.rb → replica_lag_spec.rb} +79 -79
  40. data/spec/unit/throttler/threads_running_spec.rb +18 -0
  41. data/spec/unit/throttler_spec.rb +8 -8
  42. metadata +10 -9
  43. data/gemfiles/activerecord_5.2.gemfile.lock +0 -65
@@ -28,7 +28,7 @@ describe Lhm::Chunker do
28
28
 
29
29
  Lhm::Chunker.new(@migration, connection, {throttler: throttler, printer: printer} ).run
30
30
 
31
- slave do
31
+ replica do
32
32
  value(count_all(@destination.name)).must_equal(1)
33
33
  end
34
34
 
@@ -41,7 +41,7 @@ describe Lhm::Chunker do
41
41
 
42
42
  Lhm::Chunker.new(@migration, connection, {throttler: throttler, printer: printer} ).run
43
43
 
44
- slave do
44
+ replica do
45
45
  value(count_all(@destination.name)).must_equal(2)
46
46
  end
47
47
  end
@@ -57,7 +57,7 @@ describe Lhm::Chunker do
57
57
 
58
58
  Lhm::Chunker.new(migration, connection, {throttler: throttler, printer: printer} ).run
59
59
 
60
- slave do
60
+ replica do
61
61
  value(count_all(destination.name)).must_equal(2)
62
62
  end
63
63
  end
@@ -127,7 +127,7 @@ describe Lhm::Chunker do
127
127
 
128
128
  Lhm::Chunker.new(@migration, connection, {throttler: throttler, printer: printer} ).run
129
129
 
130
- slave do
130
+ replica do
131
131
  value(count_all(@destination.name)).must_equal(0)
132
132
  end
133
133
 
@@ -136,20 +136,17 @@ describe Lhm::Chunker do
136
136
  it 'should copy 23 rows from origin to destination in one shot, regardless of the value of the id' do
137
137
  23.times { |n| execute("insert into origin set id = '#{ n * n + 23 }'") }
138
138
 
139
- printer = MiniTest::Mock.new
140
- printer.expect(:notify, :return_value, [Integer, Integer])
141
- printer.expect(:end, :return_value, [])
139
+ printer = mock("printer")
140
+ printer.expects(:notify).with(kind_of(Integer), kind_of(Integer))
141
+ printer.expects(:end)
142
142
 
143
143
  Lhm::Chunker.new(
144
144
  @migration, connection, { throttler: throttler, printer: printer }
145
145
  ).run
146
146
 
147
- slave do
147
+ replica do
148
148
  value(count_all(@destination.name)).must_equal(23)
149
149
  end
150
-
151
- printer.verify
152
-
153
150
  end
154
151
 
155
152
  it 'should copy all the records of a table, even if the last chunk starts with the last record of it.' do
@@ -160,42 +157,40 @@ describe Lhm::Chunker do
160
157
  @migration, connection, { throttler: Lhm::Throttler::Time.new(stride: 10), printer: printer }
161
158
  ).run
162
159
 
163
- slave do
160
+ replica do
164
161
  value(count_all(@destination.name)).must_equal(11)
165
162
  end
166
163
 
167
164
  end
168
165
 
169
- it 'should copy 23 rows from origin to destination in one shot with slave lag based throttler, regardless of the value of the id' do
166
+ it 'should copy 23 rows from origin to destination in one shot with replica lag based throttler, regardless of the value of the id' do
170
167
  23.times { |n| execute("insert into origin set id = '#{ 100000 + n * n + 23 }'") }
171
168
 
172
- printer = MiniTest::Mock.new
173
- printer.expect(:notify, :return_value, [Integer, Integer])
174
- printer.expect(:end, :return_value, [])
169
+ printer = mock("printer")
170
+ printer.expects(:notify).with(kind_of(Integer), kind_of(Integer))
171
+ printer.expects(:end)
175
172
 
176
- Lhm::Throttler::Slave.any_instance.stubs(:slave_hosts).returns(['127.0.0.1'])
177
- Lhm::Throttler::SlaveLag.any_instance.stubs(:master_slave_hosts).returns(['127.0.0.1'])
173
+ Lhm::Throttler::Replica.any_instance.stubs(:replica_hosts).returns(['127.0.0.1'])
174
+ Lhm::Throttler::ReplicaLag.any_instance.stubs(:master_replica_hosts).returns(['127.0.0.1'])
178
175
 
179
176
  Lhm::Chunker.new(
180
- @migration, connection, { throttler: Lhm::Throttler::SlaveLag.new(stride: 100), printer: printer }
177
+ @migration, connection, { throttler: Lhm::Throttler::ReplicaLag.new(stride: 100), printer: printer }
181
178
  ).run
182
179
 
183
- slave do
180
+ replica do
184
181
  value(count_all(@destination.name)).must_equal(23)
185
182
  end
186
-
187
- printer.verify
188
183
  end
189
184
 
190
- it 'should throttle work stride based on slave lag' do
185
+ it 'should throttle work stride based on replica lag' do
191
186
  15.times { |n| execute("insert into origin set id = '#{ (n * n) + 1 }'") }
192
187
 
193
188
  printer = mock()
194
189
  printer.expects(:notify).with(instance_of(Integer), instance_of(Integer)).twice
195
190
  printer.expects(:end)
196
191
 
197
- throttler = Lhm::Throttler::SlaveLag.new(stride: 10, allowed_lag: 0)
198
- def throttler.max_current_slave_lag
192
+ throttler = Lhm::Throttler::ReplicaLag.new(stride: 10, allowed_lag: 0)
193
+ def throttler.max_current_replica_lag
199
194
  1
200
195
  end
201
196
 
@@ -203,14 +198,14 @@ describe Lhm::Chunker do
203
198
  @migration, connection, { throttler: throttler, printer: printer }
204
199
  ).run
205
200
 
206
- assert_equal(Lhm::Throttler::SlaveLag::INITIAL_TIMEOUT * 2 * 2, throttler.timeout_seconds)
201
+ assert_equal(Lhm::Throttler::ReplicaLag::INITIAL_TIMEOUT * 2 * 2, throttler.timeout_seconds)
207
202
 
208
- slave do
203
+ replica do
209
204
  value(count_all(@destination.name)).must_equal(15)
210
205
  end
211
206
  end
212
207
 
213
- it 'should detect a single slave with no lag in the default configuration' do
208
+ it 'should detect a single replica with no lag in the default configuration' do
214
209
  15.times { |n| execute("insert into origin set id = '#{ (n * n) + 1 }'") }
215
210
 
216
211
  printer = mock()
@@ -218,15 +213,15 @@ describe Lhm::Chunker do
218
213
  printer.expects(:verify)
219
214
  printer.expects(:end)
220
215
 
221
- Lhm::Throttler::Slave.any_instance.stubs(:slave_hosts).returns(['127.0.0.1'])
222
- Lhm::Throttler::SlaveLag.any_instance.stubs(:master_slave_hosts).returns(['127.0.0.1'])
216
+ Lhm::Throttler::Replica.any_instance.stubs(:replica_hosts).returns(['127.0.0.1'])
217
+ Lhm::Throttler::ReplicaLag.any_instance.stubs(:master_replica_hosts).returns(['127.0.0.1'])
223
218
 
224
- throttler = Lhm::Throttler::SlaveLag.new(stride: 10, allowed_lag: 0)
219
+ throttler = Lhm::Throttler::ReplicaLag.new(stride: 10, allowed_lag: 0)
225
220
 
226
- if master_slave_mode?
227
- def throttler.slave_connection(slave)
221
+ if master_replica_mode?
222
+ def throttler.replica_connection(replica)
228
223
  config = ActiveRecord::Base.connection_pool.db_config.configuration_hash.dup
229
- config[:host] = slave
224
+ config[:host] = replica
230
225
  config[:port] = 33007
231
226
  ActiveRecord::Base.send('mysql2_connection', config)
232
227
  end
@@ -236,10 +231,10 @@ describe Lhm::Chunker do
236
231
  @migration, connection, { throttler: throttler, printer: printer }
237
232
  ).run
238
233
 
239
- assert_equal(Lhm::Throttler::SlaveLag::INITIAL_TIMEOUT, throttler.timeout_seconds)
240
- assert_equal(0, throttler.send(:max_current_slave_lag))
234
+ assert_equal(Lhm::Throttler::ReplicaLag::INITIAL_TIMEOUT, throttler.timeout_seconds)
235
+ assert_equal(0, throttler.send(:max_current_replica_lag))
241
236
 
242
- slave do
237
+ replica do
243
238
  value(count_all(@destination.name)).must_equal(15)
244
239
  end
245
240
 
@@ -261,7 +256,7 @@ describe Lhm::Chunker do
261
256
 
262
257
  assert_match "Verification failed, aborting early", exception.message
263
258
 
264
- slave do
259
+ replica do
265
260
  value(count_all(@destination.name)).must_equal(0)
266
261
  end
267
262
  end
@@ -3,7 +3,7 @@ master:
3
3
  user: root
4
4
  password: password
5
5
  port: 33006
6
- slave:
6
+ replica:
7
7
  host: mysql-2
8
8
  user: root
9
9
  password: password
@@ -27,7 +27,7 @@ describe Lhm::Entangler do
27
27
  execute("insert into origin (common) values ('inserted')")
28
28
  end
29
29
 
30
- slave do
30
+ replica do
31
31
  value(count(:destination, 'common', 'inserted')).must_equal(1)
32
32
  end
33
33
  end
@@ -39,7 +39,7 @@ describe Lhm::Entangler do
39
39
  execute("delete from origin where common = 'inserted'")
40
40
  end
41
41
 
42
- slave do
42
+ replica do
43
43
  value(count(:destination, 'common', 'inserted')).must_equal(0)
44
44
  end
45
45
  end
@@ -50,7 +50,7 @@ describe Lhm::Entangler do
50
50
  execute("update origin set common = 'updated'")
51
51
  end
52
52
 
53
- slave do
53
+ replica do
54
54
  value(count(:destination, 'common', 'updated')).must_equal(1)
55
55
  end
56
56
  end
@@ -60,7 +60,7 @@ describe Lhm::Entangler do
60
60
 
61
61
  execute("insert into origin (common) values ('inserted')")
62
62
 
63
- slave do
63
+ replica do
64
64
  value(count(:destination, 'common', 'inserted')).must_equal(0)
65
65
  end
66
66
  end
@@ -53,12 +53,12 @@ module IntegrationHelper
53
53
  )
54
54
  end
55
55
 
56
- def connect_slave!
56
+ def connect_replica!
57
57
  connect!(
58
58
  '127.0.0.1',
59
- $db_config['slave']['port'],
60
- $db_config['slave']['user'],
61
- $db_config['slave']['password'],
59
+ $db_config['replica']['port'],
60
+ $db_config['replica']['user'],
61
+ $db_config['replica']['password'],
62
62
  )
63
63
  end
64
64
 
@@ -113,12 +113,12 @@ module IntegrationHelper
113
113
  end
114
114
  end
115
115
 
116
- def slave(&block)
117
- if master_slave_mode?
118
- connect_slave!
116
+ def replica(&block)
117
+ if master_replica_mode?
118
+ connect_replica!
119
119
 
120
- # need to wait for the slave to catch up. a better method would be to
121
- # check the master binlog position and wait for the slave to catch up
120
+ # need to wait for the replica to catch up. a better method would be to
121
+ # check the master binlog position and wait for the replica to catch up
122
122
  # to that position.
123
123
  sleep 1
124
124
  else
@@ -127,7 +127,7 @@ module IntegrationHelper
127
127
 
128
128
  yield block
129
129
 
130
- if master_slave_mode?
130
+ if master_replica_mode?
131
131
  connect_master!
132
132
  end
133
133
  end
@@ -215,8 +215,8 @@ module IntegrationHelper
215
215
  # Environment
216
216
  #
217
217
 
218
- def master_slave_mode?
219
- !!ENV['MASTER_SLAVE']
218
+ def master_replica_mode?
219
+ !!ENV['MASTER_REPLICA']
220
220
  end
221
221
 
222
222
  #
@@ -17,7 +17,7 @@ describe Lhm do
17
17
  t.add_column(:logins, "int(12) default '0'")
18
18
  end
19
19
 
20
- slave do
20
+ replica do
21
21
  value(table_read(:users).columns['logins']).must_equal({
22
22
  :type => 'int(12)',
23
23
  :is_nullable => 'YES',
@@ -35,7 +35,7 @@ describe Lhm do
35
35
  t.add_column(:logins, "int(12) default '0'")
36
36
  end
37
37
 
38
- slave do
38
+ replica do
39
39
  value(table_read(:custom_primary_key).columns['logins']).must_equal({
40
40
  :type => 'int(12)',
41
41
  :is_nullable => 'YES',
@@ -53,7 +53,7 @@ describe Lhm do
53
53
  t.add_column(:logins, "int(12) default '0'")
54
54
  end
55
55
 
56
- slave do
56
+ replica do
57
57
  value(table_read(:composite_primary_key).columns['logins']).must_equal({
58
58
  :type => 'int(12)',
59
59
  :is_nullable => 'YES',
@@ -82,7 +82,7 @@ describe Lhm do
82
82
  t.ddl("ALTER TABLE #{t.name} CHANGE id id bigint (20) NOT NULL AUTO_INCREMENT")
83
83
  end
84
84
 
85
- slave do
85
+ replica do
86
86
  value(connection.primary_key('users')).must_equal(['username', 'id'])
87
87
  end
88
88
  end
@@ -104,7 +104,7 @@ describe Lhm do
104
104
  describe 'when no additional data is inserted into the table' do
105
105
 
106
106
  it 'migrates the existing data' do
107
- slave do
107
+ replica do
108
108
  value(count_all(:permissions)).must_equal(11)
109
109
  end
110
110
  end
@@ -120,7 +120,7 @@ describe Lhm do
120
120
  end
121
121
 
122
122
  it 'migrates all data' do
123
- slave do
123
+ replica do
124
124
  value(count_all(:permissions)).must_equal(13)
125
125
  end
126
126
  end
@@ -132,7 +132,7 @@ describe Lhm do
132
132
  t.add_column(:logins, "INT(12) DEFAULT '0'")
133
133
  end
134
134
 
135
- slave do
135
+ replica do
136
136
  value(table_read(:users).columns['logins']).must_equal({
137
137
  :type => 'int(12)',
138
138
  :is_nullable => 'YES',
@@ -150,7 +150,7 @@ describe Lhm do
150
150
  t.add_column(:logins, "INT(12) DEFAULT '0'")
151
151
  end
152
152
 
153
- slave do
153
+ replica do
154
154
  value(count_all(:users)).must_equal(23)
155
155
  end
156
156
  end
@@ -160,7 +160,7 @@ describe Lhm do
160
160
  t.remove_column(:comment)
161
161
  end
162
162
 
163
- slave do
163
+ replica do
164
164
  assert_nil table_read(:users).columns['comment']
165
165
  end
166
166
  end
@@ -170,7 +170,7 @@ describe Lhm do
170
170
  t.add_index([:comment, :created_at])
171
171
  end
172
172
 
173
- slave do
173
+ replica do
174
174
  value(index_on_columns?(:users, [:comment, :created_at])).must_equal(true)
175
175
  end
176
176
  end
@@ -180,7 +180,7 @@ describe Lhm do
180
180
  t.add_index([:comment, :created_at], :my_index_name)
181
181
  end
182
182
 
183
- slave do
183
+ replica do
184
184
  value(index?(:users, :my_index_name)).must_equal(true)
185
185
  end
186
186
  end
@@ -190,7 +190,7 @@ describe Lhm do
190
190
  t.add_index(:group)
191
191
  end
192
192
 
193
- slave do
193
+ replica do
194
194
  value(index_on_columns?(:users, :group)).must_equal(true)
195
195
  end
196
196
  end
@@ -200,7 +200,7 @@ describe Lhm do
200
200
  t.add_unique_index(:comment)
201
201
  end
202
202
 
203
- slave do
203
+ replica do
204
204
  value(index_on_columns?(:users, :comment, :unique)).must_equal(true)
205
205
  end
206
206
  end
@@ -210,7 +210,7 @@ describe Lhm do
210
210
  t.remove_index([:username, :created_at])
211
211
  end
212
212
 
213
- slave do
213
+ replica do
214
214
  value(index_on_columns?(:users, [:username, :created_at])).must_equal(false)
215
215
  end
216
216
  end
@@ -220,7 +220,7 @@ describe Lhm do
220
220
  t.remove_index([:username, :group])
221
221
  end
222
222
 
223
- slave do
223
+ replica do
224
224
  value(index?(:users, :index_with_a_custom_name)).must_equal(false)
225
225
  end
226
226
  end
@@ -230,17 +230,27 @@ describe Lhm do
230
230
  t.remove_index(:irrelevant_column_name, :index_with_a_custom_name)
231
231
  end
232
232
 
233
- slave do
233
+ replica do
234
234
  value(index?(:users, :index_with_a_custom_name)).must_equal(false)
235
235
  end
236
236
  end
237
237
 
238
+ it 'should add an index with column sizes' do
239
+ Lhm.change_table(:users, :atomic_switch => false) do |t|
240
+ t.add_index(["username(6)", "group (10)", "comment (10)"])
241
+ end
242
+
243
+ replica do
244
+ value(index_on_columns?(:users, [:username, :group, :comment])).must_equal(true)
245
+ end
246
+ end
247
+
238
248
  it 'should apply a ddl statement' do
239
249
  Lhm.change_table(:users, :atomic_switch => false) do |t|
240
250
  t.ddl('alter table %s add column flag tinyint(1)' % t.name)
241
251
  end
242
252
 
243
- slave do
253
+ replica do
244
254
  value(table_read(:users).columns['flag']).must_equal({
245
255
  :type => 'tinyint(1)',
246
256
  :is_nullable => 'YES',
@@ -256,7 +266,7 @@ describe Lhm do
256
266
  t.change_column(:comment, "varchar(20) DEFAULT 'none' NOT NULL")
257
267
  end
258
268
 
259
- slave do
269
+ replica do
260
270
  value(table_read(:users).columns['comment']).must_equal({
261
271
  :type => 'varchar(20)',
262
272
  :is_nullable => 'NO',
@@ -274,7 +284,7 @@ describe Lhm do
274
284
  t.change_column(:id, 'int(5)')
275
285
  end
276
286
 
277
- slave do
287
+ replica do
278
288
  value(table_read(:small_table).columns['id']).must_equal({
279
289
  :type => 'int(5)',
280
290
  :is_nullable => 'NO',
@@ -293,7 +303,7 @@ describe Lhm do
293
303
  t.rename_column(:username, :login)
294
304
  end
295
305
 
296
- slave do
306
+ replica do
297
307
  table_data = table_read(:users)
298
308
  assert_nil table_data.columns['username']
299
309
  value(table_read(:users).columns['login']).must_equal({
@@ -318,7 +328,7 @@ describe Lhm do
318
328
  t.rename_column(:group, :fnord)
319
329
  end
320
330
 
321
- slave do
331
+ replica do
322
332
  table_data = table_read(:users)
323
333
  assert_nil table_data.columns['group']
324
334
  value(table_read(:users).columns['fnord']).must_equal({
@@ -345,7 +355,7 @@ describe Lhm do
345
355
  t.rename_column(:username, :user_name)
346
356
  end
347
357
 
348
- slave do
358
+ replica do
349
359
  table_data = table_read(:users)
350
360
  assert_nil table_data.columns['username']
351
361
  value(table_read(:users).columns['user_name']).must_equal({
@@ -373,7 +383,7 @@ describe Lhm do
373
383
  t.rename_column(:reference, :ref)
374
384
  end
375
385
 
376
- slave do
386
+ replica do
377
387
  table_data = table_read(:users)
378
388
  assert_nil table_data.columns['reference']
379
389
  value(table_read(:users).columns['ref']).must_equal({
@@ -400,7 +410,7 @@ describe Lhm do
400
410
  t.rename_column(:group, :fnord)
401
411
  end
402
412
 
403
- slave do
413
+ replica do
404
414
  table_data = table_read(:users)
405
415
  assert_nil table_data.columns['group']
406
416
  value(table_read(:users).columns['fnord']).must_equal({
@@ -425,7 +435,7 @@ describe Lhm do
425
435
  t.rename_column(:username, :user_name)
426
436
  end
427
437
 
428
- slave do
438
+ replica do
429
439
  table_data = table_read(:users)
430
440
  assert_nil table_data.columns['username']
431
441
  value(table_read(:users).columns['user_name']).must_equal({
@@ -452,7 +462,7 @@ describe Lhm do
452
462
  t.rename_column(:username, :user_name)
453
463
  end
454
464
 
455
- slave do
465
+ replica do
456
466
  table_data = table_read(:users)
457
467
  assert_nil table_data.columns['username']
458
468
  value(table_read(:users).columns['user_name']).must_equal({
@@ -499,7 +509,7 @@ describe Lhm do
499
509
  end
500
510
  end
501
511
 
502
- slave do
512
+ replica do
503
513
  table_data = table_read(:users)
504
514
  assert_nil table_data.columns['fnord']
505
515
  value(table_read(:users).columns['group']).must_equal({
@@ -525,7 +535,7 @@ describe Lhm do
525
535
  t.remove_index('by')
526
536
  end
527
537
 
528
- slave do
538
+ replica do
529
539
  value(table_read(:lines).columns).must_include 'by'
530
540
  value(table_read(:lines).columns).wont_include 'lines'
531
541
  value(index_on_columns?(:lines, ['between'], :unique)).must_equal true
@@ -554,7 +564,7 @@ describe Lhm do
554
564
 
555
565
  insert.join
556
566
 
557
- slave do
567
+ replica do
558
568
  value(count_all(:users)).must_equal(60)
559
569
  end
560
570
  end
@@ -577,7 +587,7 @@ describe Lhm do
577
587
 
578
588
  delete.join
579
589
 
580
- slave do
590
+ replica do
581
591
  value(count_all(:users)).must_equal(40)
582
592
  end
583
593
  end
@@ -645,13 +655,12 @@ describe Lhm do
645
655
  log_lines = @logs.string.split("\n")
646
656
 
647
657
  assert log_lines.one?{ |line| line.include?("Lost connection to MySQL, will retry to connect to same host")}
648
- assert log_lines.any?{ |line| line.include?("Lost connection to MySQL server at 'reading initial communication packet'")}
649
658
  assert log_lines.one?{ |line| line.include?("LHM successfully reconnected to initial host")}
650
659
  assert log_lines.one?{ |line| line.include?("100% complete")}
651
660
 
652
661
  Lhm::ChunkInsert.remove_all_callbacks
653
662
 
654
- slave do
663
+ replica do
655
664
  value(count_all(:users)).must_equal(100)
656
665
  end
657
666
  end
@@ -31,7 +31,7 @@ describe Lhm::LockedSwitcher do
31
31
  switcher = Lhm::LockedSwitcher.new(@migration, connection)
32
32
  switcher.run
33
33
 
34
- slave do
34
+ replica do
35
35
  value(data_source_exists?(@origin)).must_equal true
36
36
  value(table_read(@migration.archive_name).columns.keys).must_include 'origin'
37
37
  end
@@ -41,7 +41,7 @@ describe Lhm::LockedSwitcher do
41
41
  switcher = Lhm::LockedSwitcher.new(@migration, connection)
42
42
  switcher.run
43
43
 
44
- slave do
44
+ replica do
45
45
  value(data_source_exists?(@destination)).must_equal false
46
46
  value(table_read(@origin.name).columns.keys).must_include 'destination'
47
47
  end
@@ -38,7 +38,7 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
38
38
  end
39
39
  end
40
40
  assert_equal Lhm::Error, e.class
41
- assert_match(/LHM tried the reconnection procedure but failed. Latest error:/, e.message)
41
+ assert_match(/LHM tried the reconnection procedure but failed. Aborting/, e.message)
42
42
  end
43
43
 
44
44
  it "Will retry until connection is achieved" do
@@ -61,6 +61,7 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
61
61
  it "Will abort if new writer is not same host" do
62
62
  # The hostname will be constant before the blip
63
63
  Lhm::SqlRetry.any_instance.stubs(:hostname).returns("mysql-1").then.returns("mysql-2")
64
+ Lhm::SqlRetry.any_instance.stubs(:server_id).returns(1).then.returns(2)
64
65
 
65
66
  # Need new instance for stub to take into effect
66
67
  lhm_retry = Lhm::SqlRetry.new(@connection, retry_options: {},
@@ -76,12 +77,12 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
76
77
  end
77
78
 
78
79
  assert_equal e.class, Lhm::Error
79
- assert_match(/LHM tried the reconnection procedure but failed. Latest error: Reconnected to wrong host/, e.message)
80
+ assert_match(/LHM tried the reconnection procedure but failed. Aborting/, e.message)
80
81
 
81
82
  logs = @logger.string.split("\n")
82
83
 
83
84
  assert logs.first.include?("Lost connection to MySQL, will retry to connect to same host")
84
- assert logs.last.include?("Lost connection to MySQL server at 'reading initial communication packet")
85
+ assert logs.last.include?("Reconnected to wrong host. Started migration on: mysql-1 (server_id: 1), but reconnected to: mysql-2 (server_id: 2).")
85
86
  end
86
87
 
87
88
  it "Will abort if failover happens (mimicked with proxySQL)" do
@@ -98,11 +99,11 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
98
99
  end
99
100
 
100
101
  assert_equal e.class, Lhm::Error
101
- assert_match(/LHM tried the reconnection procedure but failed. Latest error: Reconnected to wrong host/, e.message)
102
+ assert_match(/LHM tried the reconnection procedure but failed. Aborting/, e.message)
102
103
 
103
104
  logs = @logger.string.split("\n")
104
105
 
105
106
  assert logs.first.include?("Lost connection to MySQL, will retry to connect to same host")
106
- assert logs.last.include?("Lost connection to MySQL server at 'reading initial communication packet")
107
+ assert logs.last.include?("Reconnected to wrong host. Started migration on: mysql-1 (server_id: 1), but reconnected to: mysql-2 (server_id: 2).")
107
108
  end
108
109
  end
@@ -7,7 +7,7 @@ module ToxiproxyHelper
7
7
  def included(base)
8
8
  Toxiproxy.reset
9
9
 
10
- # listen on localhost, but toxiproxy is in a container itself, thus the upstream uses the Docker-Compose DNS
10
+ # listen on localhost, but toxiproxy is in a container itself, thus the upstream uses the Podman-Compose DNS
11
11
  Toxiproxy.populate(
12
12
  [
13
13
  {
data/spec/test_helper.rb CHANGED
@@ -28,6 +28,9 @@ logger = Logger.new STDOUT
28
28
  logger.level = Logger::WARN
29
29
  Lhm.logger = logger
30
30
 
31
+ # Want test to be efficient without having to wait the normal value of 120s
32
+ Lhm::SqlRetry::RECONNECT_RETRY_MAX_ITERATION = 4
33
+
31
34
  def without_verbose(&block)
32
35
  old_verbose, $VERBOSE = $VERBOSE, nil
33
36
  yield
@@ -70,15 +70,11 @@ describe Lhm::Printer do
70
70
  end
71
71
 
72
72
  it 'prints the dots' do
73
- mock = MiniTest::Mock.new
74
- 10.times do
75
- mock.expect(:write, :return_value, ['.'])
76
- end
73
+ mock = mock("output")
74
+ mock.expects(:write).with('.').times(10)
77
75
 
78
76
  @printer.instance_variable_set(:@output, mock)
79
77
  10.times { @printer.notify }
80
-
81
- mock.verify
82
78
  end
83
79
 
84
80
  end
@@ -22,7 +22,7 @@ describe Lhm::SqlHelper do
22
22
  end
23
23
 
24
24
  it 'should quote column names in index specification' do
25
- value(Lhm::SqlHelper.idx_spec(['title(10)', 'album']))
26
- .must_equal('`title`(10), `album`')
25
+ value(Lhm::SqlHelper.idx_spec(['title(10)', 'name (6)', 'album']))
26
+ .must_equal('`title`(10), `name`(6), `album`')
27
27
  end
28
28
  end