lhm-shopify 3.5.5 → 4.1.0
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/.github/workflows/test.yml +20 -18
- data/Appraisals +8 -19
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +37 -20
- data/README.md +21 -14
- data/dev.yml +12 -8
- data/docker-compose-mysql-5.7.yml +1 -0
- data/docker-compose-mysql-8.0.yml +63 -0
- data/docker-compose.yml +5 -3
- data/gemfiles/activerecord_6.1.gemfile +1 -0
- data/gemfiles/activerecord_6.1.gemfile.lock +23 -13
- data/gemfiles/{activerecord_7.0.0.alpha2.gemfile → activerecord_7.0.gemfile} +2 -1
- data/gemfiles/{activerecord_7.0.0.alpha2.gemfile.lock → activerecord_7.0.gemfile.lock} +29 -19
- data/gemfiles/{activerecord_6.0.gemfile → activerecord_7.1.gemfile} +1 -1
- data/gemfiles/activerecord_7.1.gemfile.lock +83 -0
- data/lhm.gemspec +2 -1
- data/lib/lhm/atomic_switcher.rb +3 -3
- data/lib/lhm/chunker.rb +4 -4
- data/lib/lhm/connection.rb +9 -1
- data/lib/lhm/sql_helper.rb +1 -1
- data/lib/lhm/sql_retry.rb +36 -18
- data/lib/lhm/table.rb +3 -4
- data/lib/lhm/throttler/replica_lag.rb +166 -0
- data/lib/lhm/throttler/slave_lag.rb +5 -155
- data/lib/lhm/throttler/threads_running.rb +3 -1
- data/lib/lhm/throttler.rb +7 -3
- data/lib/lhm/version.rb +1 -1
- data/scripts/helpers/wait-for-dbs.sh +3 -3
- data/scripts/mysql/writer/create_users.sql +1 -1
- data/spec/.lhm.example +1 -1
- data/spec/README.md +8 -9
- data/spec/integration/atomic_switcher_spec.rb +6 -10
- data/spec/integration/chunk_insert_spec.rb +2 -2
- data/spec/integration/chunker_spec.rb +54 -44
- data/spec/integration/database.yml +4 -4
- data/spec/integration/entangler_spec.rb +4 -4
- data/spec/integration/integration_helper.rb +23 -15
- data/spec/integration/lhm_spec.rb +70 -44
- data/spec/integration/locked_switcher_spec.rb +2 -2
- data/spec/integration/proxysql_spec.rb +10 -10
- data/spec/integration/sql_retry/db_connection_helper.rb +2 -4
- data/spec/integration/sql_retry/lock_wait_spec.rb +7 -8
- data/spec/integration/sql_retry/lock_wait_timeout_test_helper.rb +18 -10
- data/spec/integration/sql_retry/proxysql_helper.rb +1 -1
- data/spec/integration/sql_retry/retry_with_proxysql_spec.rb +1 -2
- data/spec/integration/table_spec.rb +1 -1
- data/spec/integration/toxiproxy_helper.rb +1 -1
- data/spec/test_helper.rb +27 -3
- data/spec/unit/atomic_switcher_spec.rb +2 -2
- data/spec/unit/chunker_spec.rb +43 -43
- data/spec/unit/connection_spec.rb +2 -2
- data/spec/unit/entangler_spec.rb +14 -24
- data/spec/unit/printer_spec.rb +2 -6
- data/spec/unit/sql_helper_spec.rb +2 -2
- data/spec/unit/throttler/{slave_lag_spec.rb → replica_lag_spec.rb} +84 -92
- data/spec/unit/throttler/threads_running_spec.rb +18 -0
- data/spec/unit/throttler_spec.rb +8 -8
- metadata +26 -12
- data/.travis.yml +0 -21
- data/gemfiles/activerecord_5.2.gemfile +0 -9
- data/gemfiles/activerecord_5.2.gemfile.lock +0 -65
- data/gemfiles/activerecord_6.0.gemfile.lock +0 -67
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
require 'mysql2'
|
3
2
|
require 'lhm'
|
4
3
|
require 'toxiproxy'
|
5
4
|
|
@@ -50,7 +49,7 @@ describe Lhm::SqlRetry, "ProxiSQL tests for LHM retry" do
|
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
|
-
assert_equal @connection.
|
52
|
+
assert_equal 2000, @connection.select_one("SELECT * FROM #{DBConnectionHelper.test_table_name} WHERE id=2000")["id"]
|
54
53
|
|
55
54
|
logs = @logger.string.split("\n")
|
56
55
|
|
@@ -23,7 +23,7 @@ describe Lhm::Table do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should parse columns' do
|
26
|
-
value(@table.columns['id'][:type]).must_match(/(bigint|int)\(\d+\)
|
26
|
+
value(@table.columns['id'][:type]).must_match(/(bigint|int)(\(\d+\))?/)
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should return true for method that should be renamed' do
|
@@ -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
|
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
@@ -14,6 +14,7 @@ require 'after_do'
|
|
14
14
|
require 'byebug'
|
15
15
|
require 'pathname'
|
16
16
|
require 'lhm'
|
17
|
+
require 'active_record'
|
17
18
|
|
18
19
|
$project = Pathname.new(File.dirname(__FILE__) + '/..').cleanpath
|
19
20
|
$spec = $project.join('spec')
|
@@ -21,8 +22,31 @@ $fixtures = $spec.join('fixtures')
|
|
21
22
|
|
22
23
|
$db_name = 'test'
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
Database = Struct.new(:adapter, :client, :error_class, :timeout_error) do
|
26
|
+
def query(connection, sql)
|
27
|
+
results = connection.query(sql)
|
28
|
+
results = results.each_hash if adapter == "trilogy"
|
29
|
+
results
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
DATABASE =
|
34
|
+
case ENV['DATABASE_ADAPTER']
|
35
|
+
when 'trilogy'
|
36
|
+
require 'trilogy'
|
37
|
+
|
38
|
+
if ActiveRecord.version < ::Gem::Version.new('7.1.0')
|
39
|
+
require 'activerecord-trilogy-adapter'
|
40
|
+
require 'trilogy_adapter/connection'
|
41
|
+
|
42
|
+
ActiveRecord::Base.public_send :extend, TrilogyAdapter::Connection
|
43
|
+
end
|
44
|
+
|
45
|
+
Database.new('trilogy', Trilogy, Trilogy::BaseError, Trilogy::TimeoutError)
|
46
|
+
else
|
47
|
+
require 'mysql2'
|
48
|
+
Database.new('mysql2', Mysql2::Client, Mysql2::Error, Mysql2::Error::TimeoutError)
|
49
|
+
end
|
26
50
|
|
27
51
|
logger = Logger.new STDOUT
|
28
52
|
logger.level = Logger::WARN
|
@@ -53,7 +77,7 @@ end
|
|
53
77
|
|
54
78
|
def init_test_db
|
55
79
|
db_config = YAML.load_file(File.expand_path(File.dirname(__FILE__)) + '/integration/database.yml')
|
56
|
-
conn =
|
80
|
+
conn = DATABASE.client.new(
|
57
81
|
:host => '127.0.0.1',
|
58
82
|
:username => db_config['master']['user'],
|
59
83
|
:password => db_config['master']['password'],
|
@@ -21,8 +21,8 @@ describe Lhm::AtomicSwitcher do
|
|
21
21
|
describe 'atomic switch' do
|
22
22
|
it 'should perform a single atomic rename' do
|
23
23
|
value(@switcher.atomic_switch).must_equal(
|
24
|
-
"
|
25
|
-
'`destination`
|
24
|
+
"RENAME TABLE `origin` TO `#{ @migration.archive_name }`, " \
|
25
|
+
'`destination` TO `origin`'
|
26
26
|
)
|
27
27
|
end
|
28
28
|
end
|
data/spec/unit/chunker_spec.rb
CHANGED
@@ -20,7 +20,7 @@ describe Lhm::Chunker do
|
|
20
20
|
@destination = Lhm::Table.new('bar')
|
21
21
|
@migration = Lhm::Migration.new(@origin, @destination)
|
22
22
|
@connection = mock()
|
23
|
-
@connection.stubs(:
|
23
|
+
@connection.stubs(:select_value).returns("dummy")
|
24
24
|
# This is a poor man's stub
|
25
25
|
@throttler = Object.new
|
26
26
|
def @throttler.run
|
@@ -42,11 +42,11 @@ describe Lhm::Chunker do
|
|
42
42
|
5
|
43
43
|
end
|
44
44
|
|
45
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 4/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(7)
|
46
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 8 order by id limit 1 offset 4/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(21)
|
47
|
-
@connection.expects(:update).with(regexp_matches(/between 1 and 7/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
48
|
-
@connection.expects(:update).with(regexp_matches(/between 8 and 10/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
49
|
-
@connection.expects(:
|
45
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 4/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(7)
|
46
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 8 order by id limit 1 offset 4/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(21)
|
47
|
+
@connection.expects(:update).with(regexp_matches(/between 1 and 7/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
48
|
+
@connection.expects(:update).with(regexp_matches(/between 8 and 10/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
49
|
+
@connection.expects(:select_all).twice.with(regexp_matches(/show warnings/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns([])
|
50
50
|
|
51
51
|
@chunker.run
|
52
52
|
end
|
@@ -57,17 +57,17 @@ describe Lhm::Chunker do
|
|
57
57
|
2
|
58
58
|
end
|
59
59
|
|
60
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
61
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 3 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(4)
|
62
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 5 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(6)
|
63
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 7 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(8)
|
64
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 9 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(10)
|
60
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
61
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 3 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(4)
|
62
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 5 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(6)
|
63
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 7 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(8)
|
64
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 9 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(10)
|
65
65
|
|
66
|
-
@connection.expects(:update).with(regexp_matches(/between 1 and 2/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
67
|
-
@connection.expects(:update).with(regexp_matches(/between 3 and 4/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
68
|
-
@connection.expects(:update).with(regexp_matches(/between 5 and 6/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
69
|
-
@connection.expects(:update).with(regexp_matches(/between 7 and 8/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
70
|
-
@connection.expects(:update).with(regexp_matches(/between 9 and 10/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
66
|
+
@connection.expects(:update).with(regexp_matches(/between 1 and 2/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
67
|
+
@connection.expects(:update).with(regexp_matches(/between 3 and 4/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
68
|
+
@connection.expects(:update).with(regexp_matches(/between 5 and 6/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
69
|
+
@connection.expects(:update).with(regexp_matches(/between 7 and 8/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
70
|
+
@connection.expects(:update).with(regexp_matches(/between 9 and 10/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
71
71
|
|
72
72
|
@chunker.run
|
73
73
|
end
|
@@ -84,17 +84,17 @@ describe Lhm::Chunker do
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
88
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 3 order by id limit 1 offset 2/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(5)
|
89
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 6 order by id limit 1 offset 2/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(8)
|
90
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 9 order by id limit 1 offset 2/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
87
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
88
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 3 order by id limit 1 offset 2/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(5)
|
89
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 6 order by id limit 1 offset 2/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(8)
|
90
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 9 order by id limit 1 offset 2/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
91
91
|
|
92
|
-
@connection.expects(:update).with(regexp_matches(/between 1 and 2/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
93
|
-
@connection.expects(:update).with(regexp_matches(/between 3 and 5/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
94
|
-
@connection.expects(:update).with(regexp_matches(/between 6 and 8/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
95
|
-
@connection.expects(:update).with(regexp_matches(/between 9 and 10/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
92
|
+
@connection.expects(:update).with(regexp_matches(/between 1 and 2/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
93
|
+
@connection.expects(:update).with(regexp_matches(/between 3 and 5/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
94
|
+
@connection.expects(:update).with(regexp_matches(/between 6 and 8/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
95
|
+
@connection.expects(:update).with(regexp_matches(/between 9 and 10/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
96
96
|
|
97
|
-
@connection.expects(:
|
97
|
+
@connection.expects(:select_all).twice.with(regexp_matches(/show warnings/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns([])
|
98
98
|
|
99
99
|
@chunker.run
|
100
100
|
end
|
@@ -104,8 +104,8 @@ describe Lhm::Chunker do
|
|
104
104
|
:start => 1,
|
105
105
|
:limit => 1)
|
106
106
|
|
107
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 0/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
108
|
-
@connection.expects(:update).with(regexp_matches(/between 1 and 1/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
107
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 0/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
108
|
+
@connection.expects(:update).with(regexp_matches(/between 1 and 1/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
109
109
|
|
110
110
|
@chunker.run
|
111
111
|
end
|
@@ -118,17 +118,17 @@ describe Lhm::Chunker do
|
|
118
118
|
2
|
119
119
|
end
|
120
120
|
|
121
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 2 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(3)
|
122
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 4 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(5)
|
123
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 6 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(7)
|
124
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 8 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(9)
|
125
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 10 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
121
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 2 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(3)
|
122
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 4 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(5)
|
123
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 6 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(7)
|
124
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 8 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(9)
|
125
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 10 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(nil)
|
126
126
|
|
127
|
-
@connection.expects(:update).with(regexp_matches(/between 2 and 3/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
128
|
-
@connection.expects(:update).with(regexp_matches(/between 4 and 5/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
129
|
-
@connection.expects(:update).with(regexp_matches(/between 6 and 7/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
130
|
-
@connection.expects(:update).with(regexp_matches(/between 8 and 9/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
131
|
-
@connection.expects(:update).with(regexp_matches(/between 10 and 10/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
127
|
+
@connection.expects(:update).with(regexp_matches(/between 2 and 3/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
128
|
+
@connection.expects(:update).with(regexp_matches(/between 4 and 5/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
129
|
+
@connection.expects(:update).with(regexp_matches(/between 6 and 7/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
130
|
+
@connection.expects(:update).with(regexp_matches(/between 8 and 9/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(2)
|
131
|
+
@connection.expects(:update).with(regexp_matches(/between 10 and 10/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
132
132
|
|
133
133
|
@chunker.run
|
134
134
|
end
|
@@ -142,9 +142,9 @@ describe Lhm::Chunker do
|
|
142
142
|
2
|
143
143
|
end
|
144
144
|
|
145
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
146
|
-
@connection.expects(:update).with(regexp_matches(/where \(foo.created_at > '2013-07-10' or foo.baz = 'quux'\) and `foo`/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
147
|
-
@connection.expects(:
|
145
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
146
|
+
@connection.expects(:update).with(regexp_matches(/where \(foo.created_at > '2013-07-10' or foo.baz = 'quux'\) and `foo`/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
147
|
+
@connection.expects(:select_all).with(regexp_matches(/show warnings/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns([])
|
148
148
|
|
149
149
|
def @migration.conditions
|
150
150
|
"where foo.created_at > '2013-07-10' or foo.baz = 'quux'"
|
@@ -162,9 +162,9 @@ describe Lhm::Chunker do
|
|
162
162
|
2
|
163
163
|
end
|
164
164
|
|
165
|
-
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/),EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
166
|
-
@connection.expects(:update).with(regexp_matches(/inner join bar on foo.id = bar.foo_id and/),EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
167
|
-
@connection.expects(:
|
165
|
+
@connection.expects(:select_value).with(regexp_matches(/where id >= 1 order by id limit 1 offset 1/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns(2)
|
166
|
+
@connection.expects(:update).with(regexp_matches(/inner join bar on foo.id = bar.foo_id and/i), EXPECTED_RETRY_FLAGS_CHUNK_INSERT).returns(1)
|
167
|
+
@connection.expects(:select_all).with(regexp_matches(/show warnings/i), EXPECTED_RETRY_FLAGS_CHUNKER).returns([])
|
168
168
|
|
169
169
|
def @migration.conditions
|
170
170
|
'inner join bar on foo.id = bar.foo_id'
|
@@ -93,7 +93,7 @@ describe Lhm::Connection do
|
|
93
93
|
it "Queries should be tagged with ProxySQL tag if reconnect_with_consistent_host is enabled" do
|
94
94
|
ar_connection = mock()
|
95
95
|
ar_connection.expects(:public_send).with(:select_value, "SHOW TABLES #{Lhm::ProxySQLHelper::ANNOTATION}").returns("dummy")
|
96
|
-
ar_connection.stubs(:
|
96
|
+
ar_connection.stubs(:select_value).times(4).returns("dummy")
|
97
97
|
ar_connection.stubs(:active?).returns(true)
|
98
98
|
|
99
99
|
connection = Lhm::Connection.new(connection: ar_connection, options: {
|
@@ -108,4 +108,4 @@ describe Lhm::Connection do
|
|
108
108
|
|
109
109
|
assert_equal val, "dummy"
|
110
110
|
end
|
111
|
-
end
|
111
|
+
end
|
data/spec/unit/entangler_spec.rb
CHANGED
@@ -63,10 +63,9 @@ describe Lhm::Entangler do
|
|
63
63
|
it 'should retry trigger creation when it hits a lock wait timeout' do
|
64
64
|
tries = 1
|
65
65
|
ar_connection = mock()
|
66
|
+
ar_connection.stubs(:select_value).returns("dummy")
|
66
67
|
ar_connection.stubs(:execute)
|
67
|
-
|
68
|
-
.then
|
69
|
-
.raises(Mysql2::Error, 'Lock wait timeout exceeded; try restarting transaction')
|
68
|
+
.raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction')
|
70
69
|
ar_connection.stubs(:active?).returns(true)
|
71
70
|
|
72
71
|
connection = Lhm::Connection.new(connection: ar_connection, options: {
|
@@ -79,15 +78,14 @@ describe Lhm::Entangler do
|
|
79
78
|
|
80
79
|
@entangler = Lhm::Entangler.new(@migration, connection)
|
81
80
|
|
82
|
-
assert_raises(
|
81
|
+
assert_raises(ActiveRecord::StatementInvalid) { @entangler.before }
|
83
82
|
end
|
84
83
|
|
85
84
|
it 'should not retry trigger creation with other mysql errors' do
|
86
85
|
ar_connection = mock()
|
86
|
+
ar_connection.stubs(:select_value).returns("dummy")
|
87
87
|
ar_connection.stubs(:execute)
|
88
|
-
.
|
89
|
-
.then
|
90
|
-
.raises(Mysql2::Error, 'The MySQL server is running with the --read-only option so it cannot execute this statement.')
|
88
|
+
.raises(DATABASE.error_class, 'The MySQL server is running with the --read-only option so it cannot execute this statement.')
|
91
89
|
ar_connection.stubs(:active?).returns(true)
|
92
90
|
connection = Lhm::Connection.new(connection: ar_connection, options: {
|
93
91
|
reconnect_with_consistent_host: true,
|
@@ -97,15 +95,14 @@ describe Lhm::Entangler do
|
|
97
95
|
})
|
98
96
|
|
99
97
|
@entangler = Lhm::Entangler.new(@migration, connection)
|
100
|
-
assert_raises(
|
98
|
+
assert_raises(DATABASE.error_class) { @entangler.before }
|
101
99
|
end
|
102
100
|
|
103
101
|
it 'should succesfully finish after retrying' do
|
104
102
|
ar_connection = mock()
|
103
|
+
ar_connection.stubs(:select_value).returns("dummy")
|
105
104
|
ar_connection.stubs(:execute)
|
106
|
-
.
|
107
|
-
.then
|
108
|
-
.raises(Mysql2::Error, 'Lock wait timeout exceeded; try restarting transaction')
|
105
|
+
.raises(ActiveRecord::StatementInvalid, 'Lock wait timeout exceeded; try restarting transaction')
|
109
106
|
.then
|
110
107
|
.returns([["dummy"]])
|
111
108
|
ar_connection.stubs(:active?).returns(true)
|
@@ -124,22 +121,15 @@ describe Lhm::Entangler do
|
|
124
121
|
|
125
122
|
it 'should retry as many times as specified by configuration' do
|
126
123
|
ar_connection = mock()
|
124
|
+
ar_connection.stubs(:select_value).returns("dummy")
|
127
125
|
ar_connection.stubs(:execute)
|
128
|
-
.
|
129
|
-
.then
|
130
|
-
.raises(Mysql2::Error, 'Lock wait timeout exceeded; try restarting transaction')
|
131
|
-
.then
|
132
|
-
.returns([["dummy"]]) # reconnect 1
|
133
|
-
.then
|
134
|
-
.raises(Mysql2::Error, 'Lock wait timeout exceeded; try restarting transaction')
|
135
|
-
.then
|
136
|
-
.returns([["dummy"]]) # reconnect 2
|
126
|
+
.raises(DATABASE.error_class, 'Lock wait timeout exceeded; try restarting transaction')
|
137
127
|
.then
|
138
|
-
.raises(
|
128
|
+
.raises(DATABASE.error_class, 'Lock wait timeout exceeded; try restarting transaction')
|
139
129
|
.then
|
140
|
-
.
|
130
|
+
.raises(DATABASE.error_class, 'Lock wait timeout exceeded; try restarting transaction')
|
141
131
|
.then
|
142
|
-
.raises(
|
132
|
+
.raises(DATABASE.error_class, 'Lock wait timeout exceeded; try restarting transaction') # final error
|
143
133
|
ar_connection.stubs(:active?).returns(true)
|
144
134
|
|
145
135
|
connection = Lhm::Connection.new(connection: ar_connection, options: {
|
@@ -152,7 +142,7 @@ describe Lhm::Entangler do
|
|
152
142
|
|
153
143
|
@entangler = Lhm::Entangler.new(@migration, connection)
|
154
144
|
|
155
|
-
assert_raises(
|
145
|
+
assert_raises(DATABASE.error_class) { @entangler.before }
|
156
146
|
end
|
157
147
|
|
158
148
|
describe 'super long table names' do
|
data/spec/unit/printer_spec.rb
CHANGED
@@ -70,15 +70,11 @@ describe Lhm::Printer do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'prints the dots' do
|
73
|
-
mock =
|
74
|
-
|
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
|