lhm-shopify 3.5.1 → 3.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/lhm/sql_retry.rb CHANGED
@@ -18,6 +18,12 @@ module Lhm
18
18
  class SqlRetry
19
19
  RECONNECT_SUCCESSFUL_MESSAGE = "LHM successfully reconnected to initial host:"
20
20
  CLOUDSQL_VERSION_COMMENT = "(Google)"
21
+ # Will retry for 120 seconds (approximately, since connecting takes time).
22
+ RECONNECT_RETRY_MAX_ITERATION = 120
23
+ RECONNECT_RETRY_INTERVAL = 1
24
+ # Will abort the LHM if it had to reconnect more than 25 times in a single run (indicator that there might be
25
+ # something wrong with the network and would be better to run the LHM at a later time).
26
+ RECONNECTION_MAXIMUM = 25
21
27
 
22
28
  MYSQL_VAR_NAMES = {
23
29
  hostname: "@@global.hostname",
@@ -25,30 +31,24 @@ module Lhm
25
31
  version_comment: "@@version_comment",
26
32
  }
27
33
 
28
- # This internal error is used to trigger retries from the parent Retriable.retriable in #with_retries
29
- class ReconnectToHostSuccessful < Lhm::Error; end
30
-
31
- def initialize(connection, options: {}, reconnect_with_consistent_host: true)
34
+ def initialize(connection, retry_options: {}, reconnect_with_consistent_host: false)
32
35
  @connection = connection
33
- @log_prefix = options.delete(:log_prefix)
34
- @global_retry_config = default_retry_config.dup.merge!(options)
35
- if (@reconnect_with_consistent_host = reconnect_with_consistent_host)
36
- @initial_hostname = hostname
37
- @initial_server_id = server_id
38
- end
36
+ self.retry_config = retry_options
37
+ self.reconnect_with_consistent_host = reconnect_with_consistent_host
39
38
  end
40
39
 
41
40
  # Complete explanation of algorithm: https://github.com/Shopify/lhm/pull/112
42
- def with_retries(retry_config = {})
43
- @log_prefix = retry_config.delete(:log_prefix)
41
+ def with_retries(log_prefix: nil)
42
+ @log_prefix = log_prefix || "" # No prefix. Just logs
44
43
 
45
- retry_config = @global_retry_config.dup.merge!(retry_config)
44
+ # Amount of time LHM had to reconnect. Aborting if more than RECONNECTION_MAXIMUM
45
+ reconnection_counter = 0
46
46
 
47
- Retriable.retriable(retry_config) do
47
+ Retriable.retriable(@retry_config) do
48
48
  # Using begin -> rescue -> end for Ruby 2.4 compatibility
49
49
  begin
50
50
  if @reconnect_with_consistent_host
51
- raise Lhm::Error.new("Could not reconnected to initial MySQL host. Aborting to avoid data-loss") unless same_host_as_initial?
51
+ raise Lhm::Error.new("MySQL host has changed since the start of the LHM. Aborting to avoid data-loss") unless same_host_as_initial?
52
52
  end
53
53
 
54
54
  yield(@connection)
@@ -57,13 +57,36 @@ module Lhm
57
57
  # The error will be raised the connection is still active (i.e. no need to reconnect) or if the connection is
58
58
  # dead (i.e. not active) and @reconnect_with_host is false (i.e. instructed not to reconnect)
59
59
  raise e if @connection.active? || (!@connection.active? && !@reconnect_with_consistent_host)
60
- reconnect_with_host_check! if @reconnect_with_consistent_host
60
+
61
+ # Lhm could be stuck in a weird state where it loses connection, reconnects and re looses-connection instantly
62
+ # after, creating an infinite loop (because of the usage of `retry`). Hence, abort after 25 reconnections
63
+ raise Lhm::Error.new("LHM reached host reconnection max of #{RECONNECTION_MAXIMUM} times. " \
64
+ "Please try again later.") if reconnection_counter > RECONNECTION_MAXIMUM
65
+
66
+ reconnection_counter += 1
67
+ if reconnect_with_host_check!
68
+ retry
69
+ else
70
+ raise Lhm::Error.new("LHM tried the reconnection procedure but failed. Aborting")
71
+ end
61
72
  end
62
73
  end
63
74
  end
64
75
 
65
- attr_reader :global_retry_config
66
- attr_accessor :reconnect_with_consistent_host
76
+ # Both attributes will have defined setters
77
+ attr_reader :retry_config, :reconnect_with_consistent_host
78
+ attr_accessor :connection
79
+
80
+ def retry_config=(retry_options)
81
+ @retry_config = default_retry_config.dup.merge!(retry_options)
82
+ end
83
+
84
+ def reconnect_with_consistent_host=(reconnect)
85
+ if (@reconnect_with_consistent_host = reconnect)
86
+ @initial_hostname = hostname
87
+ @initial_server_id = server_id
88
+ end
89
+ end
67
90
 
68
91
  private
69
92
 
@@ -99,34 +122,32 @@ module Lhm
99
122
 
100
123
  def reconnect_with_host_check!
101
124
  log_with_prefix("Lost connection to MySQL, will retry to connect to same host")
102
- begin
103
- Retriable.retriable(host_retry_config) do
125
+
126
+ RECONNECT_RETRY_MAX_ITERATION.times do
127
+ begin
128
+ sleep(RECONNECT_RETRY_INTERVAL)
129
+
104
130
  # tries to reconnect. On failure will trigger a retry
105
131
  @connection.reconnect!
106
132
 
107
133
  if same_host_as_initial?
108
134
  # This is not an actual error, but controlled way to get the parent `Retriable.retriable` to retry
109
135
  # the statement that failed (since the Retriable gem only retries on errors).
110
- raise ReconnectToHostSuccessful.new("LHM successfully reconnected to initial host: #{@initial_hostname} (server_id: #{@initial_server_id})")
136
+ log_with_prefix("LHM successfully reconnected to initial host: #{@initial_hostname} (server_id: #{@initial_server_id})")
137
+ return true
111
138
  else
112
139
  # New Master --> abort LHM (reconnecting will not change anything)
113
- raise Lhm::Error.new("Reconnected to wrong host. Started migration on: #{@initial_hostname} (server_id: #{@initial_server_id}), but reconnected to: #{hostname} (server_id: #{@initial_server_id}).")
140
+ log_with_prefix("Reconnected to wrong host. Started migration on: #{@initial_hostname} (server_id: #{@initial_server_id}), but reconnected to: #{hostname} (server_id: #{server_id}).", :error)
141
+ return false
114
142
  end
143
+ rescue StandardError => e
144
+ # Retry if ActiveRecord cannot reach host
145
+ next if /Lost connection to MySQL server at 'reading initial communication packet'/ === e.message
146
+ log_with_prefix("Encountered error: [#{e.class}] #{e.message}. Will stop reconnection procedure.", :info)
147
+ return false
115
148
  end
116
- rescue StandardError => e
117
- # The parent Retriable.retriable is configured to retry if it encounters an error with the success message.
118
- # Therefore, if the connection is re-established successfully AND the host is the same, LHM can retry the query
119
- # that originally failed.
120
- raise e if reconnect_successful?(e)
121
- # If the connection was not successful, the parent retriable will raise any error that originated from the
122
- # `@connection.reconnect!`
123
- # Therefore, this error will cause the LHM to abort
124
- raise Lhm::Error.new("LHM tried the reconnection procedure but failed. Latest error: #{e.message}")
125
149
  end
126
- end
127
-
128
- def reconnect_successful?(e)
129
- e.is_a?(ReconnectToHostSuccessful)
150
+ false
130
151
  end
131
152
 
132
153
  # For a full list of configuration options see https://github.com/kamui/retriable
@@ -143,9 +164,6 @@ module Lhm
143
164
  /Unknown MySQL server host/,
144
165
  /connection is locked to hostgroup/,
145
166
  /The MySQL server is running with the --read-only option so it cannot execute this statement/,
146
- ],
147
- ReconnectToHostSuccessful => [
148
- /#{RECONNECT_SUCCESSFUL_MESSAGE}/
149
167
  ]
150
168
  },
151
169
  multiplier: 1, # each successive interval grows by this factor
@@ -153,28 +171,6 @@ module Lhm
153
171
  tries: 20, # Number of attempts to make at running your code block (includes initial attempt).
154
172
  rand_factor: 0, # percentage to randomize the next retry interval time
155
173
  max_elapsed_time: Float::INFINITY, # max total time in seconds that code is allowed to keep being retried
156
- on_retry: Proc.new do |exception, try_number, total_elapsed_time, next_interval|
157
- if reconnect_successful?(exception)
158
- log_with_prefix("#{exception.message} -- triggering retry", :info)
159
- else
160
- log_with_prefix("#{exception.class}: '#{exception.message}' - #{try_number} tries in #{total_elapsed_time} seconds and #{next_interval} seconds until the next try.", :error)
161
- end
162
- end
163
- }.freeze
164
- end
165
-
166
- def host_retry_config
167
- {
168
- on: {
169
- StandardError => [
170
- /Lost connection to MySQL server at 'reading initial communication packet'/
171
- ]
172
- },
173
- multiplier: 1, # each successive interval grows by this factor
174
- base_interval: 0.25, # the initial interval in seconds between tries.
175
- tries: 20, # Number of attempts to make at running your code block (includes initial attempt).
176
- rand_factor: 0, # percentage to randomize the next retry interval time
177
- max_elapsed_time: Float::INFINITY, # max total time in seconds that code is allowed to keep being retried
178
174
  on_retry: Proc.new do |exception, try_number, total_elapsed_time, next_interval|
179
175
  log_with_prefix("#{exception.class}: '#{exception.message}' - #{try_number} tries in #{total_elapsed_time} seconds and #{next_interval} seconds until the next try.", :error)
180
176
  end
data/lib/lhm/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # Schmidt
3
3
 
4
4
  module Lhm
5
- VERSION = '3.5.1'
5
+ VERSION = '3.5.5'
6
6
  end
data/lib/lhm.rb CHANGED
@@ -28,7 +28,7 @@ module Lhm
28
28
  extend Throttler
29
29
  extend self
30
30
 
31
- DEFAULT_LOGGER_OPTIONS = { level: Logger::INFO, file: STDOUT }
31
+ DEFAULT_LOGGER_OPTIONS = { level: Logger::INFO, file: STDOUT }
32
32
 
33
33
  # Alters a table with the changes described in the block
34
34
  #
@@ -46,15 +46,19 @@ module Lhm
46
46
  # Use atomic switch to rename tables (defaults to: true)
47
47
  # If using a version of mysql affected by atomic switch bug, LHM forces user
48
48
  # to set this option (see SqlHelper#supports_atomic_switch?)
49
+ # @option options [Boolean] :reconnect_with_consistent_host
50
+ # Active / Deactivate ProxySQL-aware reconnection procedure (default to: false)
49
51
  # @yield [Migrator] Yielded Migrator object records the changes
50
52
  # @return [Boolean] Returns true if the migration finishes
51
53
  # @raise [Error] Raises Lhm::Error in case of a error and aborts the migration
52
54
  def change_table(table_name, options = {}, &block)
53
- origin = Table.parse(table_name, connection)
54
- invoker = Invoker.new(origin, connection)
55
- block.call(invoker.migrator)
56
- invoker.run(options)
57
- true
55
+ with_flags(options) do
56
+ origin = Table.parse(table_name, connection)
57
+ invoker = Invoker.new(origin, connection)
58
+ block.call(invoker.migrator)
59
+ invoker.run(options)
60
+ true
61
+ end
58
62
  end
59
63
 
60
64
  # Cleanup tables and triggers
@@ -86,26 +90,16 @@ module Lhm
86
90
  # Setups DB connection
87
91
  #
88
92
  # @param [ActiveRecord::Base] connection ActiveRecord Connection
89
- # @param [Hash] connection_options Optional options (defaults to: empty hash)
90
- # @option connection_options [Boolean] :reconnect_with_consistent_host
91
- # Active / Deactivate ProxySQL-aware reconnection procedure (default to: false)
92
- def setup(connection, connection_options = {})
93
- @@connection = Connection.new(connection: connection, options: connection_options)
93
+ def setup(connection)
94
+ @@connection = Connection.new(connection: connection)
94
95
  end
95
96
 
96
- # Setups DB connection
97
- #
98
- # @param [Hash] connection_options Optional options (defaults to: empty hash)
99
- # @option connection_options [Boolean] :reconnect_with_consistent_host
100
- # Active / Deactivate ProxySQL-aware reconnection procedure (default to: false)
101
- def connection(connection_options = nil)
102
- if @@connection.nil?
103
- raise 'Please call Lhm.setup' unless defined?(ActiveRecord)
104
- @@connection = Connection.new(connection: ActiveRecord::Base.connection, options: connection_options || {})
105
- else
106
- @@connection.options = connection_options unless connection_options.nil?
107
- end
108
- @@connection
97
+ # Returns DB connection (or initializes it if not created yet)
98
+ def connection
99
+ @@connection ||= begin
100
+ raise 'Please call Lhm.setup' unless defined?(ActiveRecord)
101
+ @@connection = Connection.new(connection: ActiveRecord::Base.connection)
102
+ end
109
103
  end
110
104
 
111
105
  def self.logger=(new_logger)
@@ -147,4 +141,16 @@ module Lhm
147
141
  false
148
142
  end
149
143
  end
144
+
145
+ def with_flags(options)
146
+ old_flags = {
147
+ reconnect_with_consistent_host: Lhm.connection.reconnect_with_consistent_host,
148
+ }
149
+
150
+ Lhm.connection.reconnect_with_consistent_host = options[:reconnect_with_consistent_host] || false
151
+
152
+ yield
153
+ ensure
154
+ Lhm.connection.reconnect_with_consistent_host = old_flags[:reconnect_with_consistent_host]
155
+ end
150
156
  end
@@ -39,10 +39,15 @@ describe Lhm::AtomicSwitcher do
39
39
  .then
40
40
  .returns([["dummy"]]) # Matches initial host -> triggers retry
41
41
 
42
- connection = Lhm::Connection.new(connection: ar_connection, options: {reconnect_with_consistent_host: true})
42
+ connection = Lhm::Connection.new(connection: ar_connection, options: {
43
+ reconnect_with_consistent_host: true,
44
+ retriable: {
45
+ tries: 3,
46
+ base_interval: 0
47
+ }
48
+ })
43
49
 
44
-
45
- switcher = Lhm::AtomicSwitcher.new(@migration, connection, retriable: { tries: 3, base_interval: 0 })
50
+ switcher = Lhm::AtomicSwitcher.new(@migration, connection)
46
51
 
47
52
  assert switcher.run
48
53
 
@@ -58,20 +63,26 @@ describe Lhm::AtomicSwitcher do
58
63
  ar_connection.stubs(:data_source_exists?).returns(true)
59
64
  ar_connection.stubs(:active?).returns(true)
60
65
  ar_connection.stubs(:execute).returns([["dummy"]], [["dummy"]], [["dummy"]])
61
- .then
62
- .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.')
63
- .then
64
- .returns([["dummy"]]) # triggers retry 1
65
- .then
66
- .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.')
67
- .then
68
- .returns([["dummy"]]) # triggers retry 2
69
- .then
70
- .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.') # triggers retry 2
71
-
72
- connection = Lhm::Connection.new(connection: ar_connection, options: {reconnect_with_consistent_host: true})
73
-
74
- switcher = Lhm::AtomicSwitcher.new(@migration, connection, retriable: { tries: 2, base_interval: 0 })
66
+ .then
67
+ .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.')
68
+ .then
69
+ .returns([["dummy"]]) # triggers retry 1
70
+ .then
71
+ .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.')
72
+ .then
73
+ .returns([["dummy"]]) # triggers retry 2
74
+ .then
75
+ .raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction.') # triggers retry 2
76
+
77
+ connection = Lhm::Connection.new(connection: ar_connection, options: {
78
+ reconnect_with_consistent_host: true,
79
+ retriable: {
80
+ tries: 2,
81
+ base_interval: 0
82
+ }
83
+ })
84
+
85
+ switcher = Lhm::AtomicSwitcher.new(@migration, connection)
75
86
 
76
87
  assert_raises(ActiveRecord::StatementInvalid) { switcher.run }
77
88
  end
@@ -173,6 +173,9 @@ describe Lhm::Chunker do
173
173
  printer.expect(:notify, :return_value, [Integer, Integer])
174
174
  printer.expect(:end, :return_value, [])
175
175
 
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'])
178
+
176
179
  Lhm::Chunker.new(
177
180
  @migration, connection, { throttler: Lhm::Throttler::SlaveLag.new(stride: 100), printer: printer }
178
181
  ).run
@@ -215,17 +218,16 @@ describe Lhm::Chunker do
215
218
  printer.expects(:verify)
216
219
  printer.expects(:end)
217
220
 
218
- throttler = Lhm::Throttler::SlaveLag.new(stride: 10, allowed_lag: 0)
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'])
219
223
 
220
- def throttler.slave_hosts
221
- ['127.0.0.1']
222
- end
224
+ throttler = Lhm::Throttler::SlaveLag.new(stride: 10, allowed_lag: 0)
223
225
 
224
226
  if master_slave_mode?
225
227
  def throttler.slave_connection(slave)
226
228
  config = ActiveRecord::Base.connection_pool.db_config.configuration_hash.dup
227
229
  config[:host] = slave
228
- config[:port] = 3307
230
+ config[:port] = 33007
229
231
  ActiveRecord::Base.send('mysql2_connection', config)
230
232
  end
231
233
  end
@@ -62,18 +62,16 @@ module IntegrationHelper
62
62
  )
63
63
  end
64
64
 
65
- def connect_master_with_toxiproxy!(with_retry: false)
65
+ def connect_master_with_toxiproxy!
66
66
  connect!(
67
67
  '127.0.0.1',
68
68
  $db_config['master_toxic']['port'],
69
69
  $db_config['master_toxic']['user'],
70
- $db_config['master_toxic']['password'],
71
- with_retry)
70
+ $db_config['master_toxic']['password'])
72
71
  end
73
72
 
74
- def connect!(hostname, port, user, password, with_retry = false)
75
- adapter = ar_conn(hostname, port, user, password)
76
- Lhm.setup(adapter,{reconnect_with_consistent_host: with_retry})
73
+ def connect!(hostname, port, user, password)
74
+ Lhm.setup(ar_conn(hostname, port, user, password))
77
75
  unless defined?(@@cleaned_up)
78
76
  Lhm.cleanup(true)
79
77
  @@cleaned_up = true
@@ -592,7 +592,7 @@ describe Lhm do
592
592
  end
593
593
 
594
594
  it " should not try to reconnect if reconnect_with_consistent_host is not provided" do
595
- connect_master_with_toxiproxy!(with_retry: false)
595
+ connect_master_with_toxiproxy!
596
596
 
597
597
  table_create(:users)
598
598
  100.times { |n| execute("insert into users set reference = '#{ n }'") }
@@ -610,7 +610,7 @@ describe Lhm do
610
610
  end
611
611
 
612
612
  it "should reconnect if reconnect_with_consistent_host is true" do
613
- connect_master_with_toxiproxy!(with_retry: true)
613
+ connect_master_with_toxiproxy!
614
614
  mysql_disabled = false
615
615
 
616
616
  table_create(:users)
@@ -635,7 +635,7 @@ describe Lhm do
635
635
  method_added(:insert_and_return_count_of_rows_created)
636
636
  end
637
637
 
638
- Lhm.change_table(:users, :atomic_switch => false) do |t|
638
+ Lhm.change_table(:users, atomic_switch: false, reconnect_with_consistent_host: true) do |t|
639
639
  t.ddl("ALTER TABLE #{t.name} CHANGE id id bigint (20) NOT NULL")
640
640
  t.ddl("ALTER TABLE #{t.name} DROP PRIMARY KEY, ADD PRIMARY KEY (username, id)")
641
641
  t.ddl("ALTER TABLE #{t.name} ADD INDEX (id)")
@@ -645,7 +645,6 @@ describe Lhm do
645
645
  log_lines = @logs.string.split("\n")
646
646
 
647
647
  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
648
  assert log_lines.one?{ |line| line.include?("LHM successfully reconnected to initial host")}
650
649
  assert log_lines.one?{ |line| line.include?("100% complete")}
651
650
 
@@ -29,6 +29,6 @@ describe "ProxySQL integration" do
29
29
  port: "33005",
30
30
  )
31
31
 
32
- assert_equal conn.query("/*maintenance:lhm*/SELECT @@global.hostname as host").each.first["host"], "mysql-1"
32
+ assert_equal conn.query("SELECT @@global.hostname as host #{Lhm::ProxySQLHelper::ANNOTATION}").each.first["host"], "mysql-1"
33
33
  end
34
34
  end
@@ -55,7 +55,7 @@ describe Lhm::SqlRetry do
55
55
  it "successfully executes the SQL despite the errors encountered" do
56
56
  # Start a thread to retry, once the lock is held, execute the block
57
57
  @helper.with_waiting_lock do |waiting_connection|
58
- sql_retry = Lhm::SqlRetry.new(waiting_connection, options: {
58
+ sql_retry = Lhm::SqlRetry.new(waiting_connection, retry_options: {
59
59
  base_interval: 0.2, # first retry after 200ms
60
60
  multiplier: 1, # subsequent retries wait 1x longer than first retry (no change)
61
61
  tries: 3, # we only need 3 tries (including the first) for the scenario described below
@@ -98,7 +98,7 @@ describe Lhm::SqlRetry do
98
98
  puts "*" * 64
99
99
  # Start a thread to retry, once the lock is held, execute the block
100
100
  @helper.with_waiting_lock do |waiting_connection|
101
- sql_retry = Lhm::SqlRetry.new(waiting_connection, options: {
101
+ sql_retry = Lhm::SqlRetry.new(waiting_connection, retry_options: {
102
102
  base_interval: 0.2, # first retry after 200ms
103
103
  multiplier: 1, # subsequent retries wait 1x longer than first retry (no change)
104
104
  tries: 2, # we need 3 tries (including the first) for the scenario described below, but we only get two...we will fail
@@ -18,7 +18,7 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
18
18
 
19
19
  @connection = DBConnectionHelper::new_mysql_connection(:proxysql, true, true)
20
20
 
21
- @lhm_retry = Lhm::SqlRetry.new(@connection, options: {},
21
+ @lhm_retry = Lhm::SqlRetry.new(@connection, retry_options: {},
22
22
  reconnect_with_consistent_host: true)
23
23
  end
24
24
 
@@ -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,9 +61,10 @@ 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
- lhm_retry = Lhm::SqlRetry.new(@connection, options: {},
67
+ lhm_retry = Lhm::SqlRetry.new(@connection, retry_options: {},
67
68
  reconnect_with_consistent_host: true)
68
69
 
69
70
  e = assert_raises Lhm::Error do
@@ -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
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