lhm-shopify 3.5.0 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +17 -4
- data/.gitignore +0 -2
- data/Appraisals +24 -0
- data/Gemfile.lock +66 -0
- data/README.md +42 -0
- data/Rakefile +1 -0
- data/dev.yml +18 -3
- data/docker-compose.yml +15 -3
- data/gemfiles/activerecord_5.2.gemfile +9 -0
- data/gemfiles/activerecord_5.2.gemfile.lock +65 -0
- data/gemfiles/activerecord_6.0.gemfile +7 -0
- data/gemfiles/activerecord_6.0.gemfile.lock +67 -0
- data/gemfiles/activerecord_6.1.gemfile +7 -0
- data/gemfiles/activerecord_6.1.gemfile.lock +66 -0
- data/gemfiles/activerecord_7.0.0.alpha2.gemfile +7 -0
- data/gemfiles/activerecord_7.0.0.alpha2.gemfile.lock +64 -0
- data/lhm.gemspec +7 -3
- data/lib/lhm/atomic_switcher.rb +1 -1
- data/lib/lhm/chunk_insert.rb +2 -1
- data/lib/lhm/chunker.rb +3 -3
- data/lib/lhm/cleanup/current.rb +1 -1
- data/lib/lhm/connection.rb +50 -11
- data/lib/lhm/entangler.rb +2 -2
- data/lib/lhm/invoker.rb +2 -2
- data/lib/lhm/proxysql_helper.rb +10 -0
- data/lib/lhm/sql_retry.rb +126 -8
- data/lib/lhm/throttler/slave_lag.rb +19 -2
- data/lib/lhm/version.rb +1 -1
- data/lib/lhm.rb +22 -8
- data/scripts/mysql/writer/create_users.sql +3 -0
- data/spec/integration/atomic_switcher_spec.rb +27 -10
- data/spec/integration/chunk_insert_spec.rb +2 -1
- data/spec/integration/chunker_spec.rb +1 -1
- data/spec/integration/database.yml +10 -0
- data/spec/integration/entangler_spec.rb +3 -1
- data/spec/integration/integration_helper.rb +23 -5
- data/spec/integration/lhm_spec.rb +75 -0
- data/spec/integration/proxysql_spec.rb +34 -0
- data/spec/integration/sql_retry/db_connection_helper.rb +52 -0
- data/spec/integration/sql_retry/lock_wait_spec.rb +8 -6
- data/spec/integration/sql_retry/lock_wait_timeout_test_helper.rb +19 -9
- data/spec/integration/sql_retry/proxysql_helper.rb +22 -0
- data/spec/integration/sql_retry/retry_with_proxysql_spec.rb +108 -0
- data/spec/integration/toxiproxy_helper.rb +40 -0
- data/spec/test_helper.rb +21 -0
- data/spec/unit/chunk_insert_spec.rb +7 -2
- data/spec/unit/chunker_spec.rb +45 -42
- data/spec/unit/connection_spec.rb +22 -4
- data/spec/unit/entangler_spec.rb +41 -11
- data/spec/unit/throttler/slave_lag_spec.rb +13 -8
- metadata +76 -11
- data/gemfiles/ar-2.3_mysql.gemfile +0 -6
- data/gemfiles/ar-3.2_mysql.gemfile +0 -5
- data/gemfiles/ar-3.2_mysql2.gemfile +0 -5
- data/gemfiles/ar-4.0_mysql2.gemfile +0 -5
- data/gemfiles/ar-4.1_mysql2.gemfile +0 -5
- data/gemfiles/ar-4.2_mysql2.gemfile +0 -5
- data/gemfiles/ar-5.0_mysql2.gemfile +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b5fbf9905c14cd938075e3f6b930de0b52cdbc7c048f8ed572c654824681d99
|
4
|
+
data.tar.gz: c950dd9650c4e04412a91a9d21b6bbff3b3f092ecbbce1474a77518716737d62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e92c7cc7cefa85e18a9c5b3d17966574324c8fe8e067f4ac4203241d18e8dae836c82554f92685e90978af26451422852c654fed8f0b855032dee0ac3d0f130d
|
7
|
+
data.tar.gz: 8755a2814d7d92d015d35ae3636993e39a66b5d27d1980a002eec96a2e33012350310d5f903b5f3b225d6b4bf60295841ee4e35919b927914a0cc700683d357b
|
data/.github/workflows/test.yml
CHANGED
@@ -10,15 +10,28 @@ jobs:
|
|
10
10
|
test:
|
11
11
|
name: Run tests
|
12
12
|
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
strategy:
|
15
|
+
fail-fast: false
|
16
|
+
matrix:
|
17
|
+
include:
|
18
|
+
- ruby-version: "2.4"
|
19
|
+
activerecord-version: "5.2"
|
20
|
+
- ruby-version: "2.5"
|
21
|
+
activerecord-version: "6.0"
|
22
|
+
- ruby-version: "2.7.5"
|
23
|
+
activerecord-version: "6.1"
|
24
|
+
- ruby-version: "3.0"
|
25
|
+
activerecord-version: "7.0.0.alpha2"
|
13
26
|
steps:
|
14
27
|
- uses: actions/checkout@v2
|
15
28
|
- name: Set up Ruby
|
16
29
|
uses: ruby/setup-ruby@v1
|
17
30
|
with:
|
18
|
-
ruby-version:
|
19
|
-
bundler-cache:
|
31
|
+
ruby-version: ${{matrix.ruby-version}}
|
32
|
+
bundler-cache: false
|
20
33
|
- name: Install Ruby packages
|
21
|
-
run: bundle install
|
34
|
+
run: BUNDLE_GEMFILE="${GITHUB_WORKSPACE}/gemfiles/activerecord_${{ matrix.activerecord-version }}.gemfile" bundle install
|
22
35
|
- name: Install Ubuntu packages
|
23
36
|
run: sudo apt-get update && sudo apt-get install numactl libaio-dev libmysqlclient-dev
|
24
37
|
- name: Setup MySQL and ProxySQL (docker-compose)
|
@@ -27,4 +40,4 @@ jobs:
|
|
27
40
|
run: ./scripts/helpers/wait-for-dbs.sh
|
28
41
|
timeout-minutes: 2
|
29
42
|
- name: Run tests
|
30
|
-
run: bundle exec rake specs
|
43
|
+
run: BUNDLE_GEMFILE="${GITHUB_WORKSPACE}/gemfiles/activerecord_${{ matrix.activerecord-version }}.gemfile" bundle exec rake specs
|
data/.gitignore
CHANGED
data/Appraisals
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Oldest supported Rails version
|
2
|
+
appraise "activerecord-5.2" do
|
3
|
+
gem "activerecord", "5.2.6"
|
4
|
+
|
5
|
+
# This gemfile will be ran against ruby 2.4 and some gems might require 2.4+. The following list are the gems
|
6
|
+
# and their respective versions that work with ruby <= 2.4
|
7
|
+
gem "simplecov", "0.18.5"
|
8
|
+
gem "docile", "1.3.5"
|
9
|
+
end
|
10
|
+
|
11
|
+
# First conflicted version
|
12
|
+
appraise "activerecord-6.0" do
|
13
|
+
gem "activerecord", "6.0.0"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Second conflicted version
|
17
|
+
appraise "activerecord-6.1" do
|
18
|
+
gem "activerecord", "6.1.0"
|
19
|
+
end
|
20
|
+
|
21
|
+
# Latest version at the moment
|
22
|
+
appraise "activerecord-7.0.0.alpha2" do
|
23
|
+
gem "activerecord", "7.0.0.alpha2"
|
24
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
lhm-shopify (3.5.1)
|
5
|
+
retriable (>= 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (6.1.4.1)
|
11
|
+
activesupport (= 6.1.4.1)
|
12
|
+
activerecord (6.1.4.1)
|
13
|
+
activemodel (= 6.1.4.1)
|
14
|
+
activesupport (= 6.1.4.1)
|
15
|
+
activesupport (6.1.4.1)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 1.6, < 2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
tzinfo (~> 2.0)
|
20
|
+
zeitwerk (~> 2.3)
|
21
|
+
after_do (0.4.0)
|
22
|
+
appraisal (2.4.1)
|
23
|
+
bundler
|
24
|
+
rake
|
25
|
+
thor (>= 0.14.0)
|
26
|
+
byebug (11.1.3)
|
27
|
+
concurrent-ruby (1.1.9)
|
28
|
+
docile (1.4.0)
|
29
|
+
i18n (1.8.11)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
minitest (5.14.4)
|
32
|
+
mocha (1.13.0)
|
33
|
+
mysql2 (0.5.3)
|
34
|
+
rake (13.0.6)
|
35
|
+
retriable (3.1.2)
|
36
|
+
simplecov (0.21.2)
|
37
|
+
docile (~> 1.1)
|
38
|
+
simplecov-html (~> 0.11)
|
39
|
+
simplecov_json_formatter (~> 0.1)
|
40
|
+
simplecov-html (0.12.3)
|
41
|
+
simplecov_json_formatter (0.1.3)
|
42
|
+
thor (1.1.0)
|
43
|
+
toxiproxy (2.0.0)
|
44
|
+
tzinfo (2.0.4)
|
45
|
+
concurrent-ruby (~> 1.0)
|
46
|
+
zeitwerk (2.5.1)
|
47
|
+
|
48
|
+
PLATFORMS
|
49
|
+
x86_64-darwin-20
|
50
|
+
x86_64-linux
|
51
|
+
|
52
|
+
DEPENDENCIES
|
53
|
+
activerecord
|
54
|
+
after_do
|
55
|
+
appraisal
|
56
|
+
byebug
|
57
|
+
lhm-shopify!
|
58
|
+
minitest
|
59
|
+
mocha
|
60
|
+
mysql2
|
61
|
+
rake
|
62
|
+
simplecov
|
63
|
+
toxiproxy
|
64
|
+
|
65
|
+
BUNDLED WITH
|
66
|
+
2.2.22
|
data/README.md
CHANGED
@@ -109,6 +109,48 @@ end
|
|
109
109
|
to prevent accidental data loss. After successful or failed LHM migrations, these leftover
|
110
110
|
tables must be cleaned up.
|
111
111
|
|
112
|
+
### Usage with ProxySQL
|
113
|
+
LHM can recover from connection loss. However, when used in conjunction with ProxySQL, there are multiple ways that
|
114
|
+
connection loss could induce data loss (if triggered by a failover). Therefore it will perform additional checks to
|
115
|
+
ensure that the MySQL host stays consistent across the schema migrations if the feature is enabled.
|
116
|
+
This is done by tagging every query with `/*maintenance:lhm*/`, which will be recognized by ProxySQL.
|
117
|
+
However, to get this feature working, a new ProxySQL query rule must be added.
|
118
|
+
```cnf
|
119
|
+
{
|
120
|
+
rule_id = <rule id>
|
121
|
+
active = 1
|
122
|
+
match_pattern = "maintenance:lhm"
|
123
|
+
destination_hostgroup = <MySQL writer's hostgroup>
|
124
|
+
}
|
125
|
+
```
|
126
|
+
|
127
|
+
This will ensure that all relevant queries are forwarded to the current writer.
|
128
|
+
|
129
|
+
Also, ProxySQL disables [multiplexing](https://proxysql.com/documentation/multiplexing/) for `select` on `@@` variables.
|
130
|
+
Therefore, the following rules must be added to ensure that queries (even if tagged with `/*maintenance:lhm*/`) get
|
131
|
+
forwarded to the right target.
|
132
|
+
```cnf
|
133
|
+
{
|
134
|
+
rule_id = <rule id>
|
135
|
+
active = 1
|
136
|
+
match_digest = "@@global\.server_id"
|
137
|
+
multiplex = 2
|
138
|
+
},
|
139
|
+
{
|
140
|
+
rule_id = <rule id>
|
141
|
+
active = 1
|
142
|
+
match_digest = "@@global\.hostname"
|
143
|
+
multiplex = 2
|
144
|
+
}
|
145
|
+
```
|
146
|
+
|
147
|
+
Once these changes are added to the ProxySQL configuration (either through `.cnf` or dynamically through the admin interface),
|
148
|
+
the feature can be enabled. This is done by adding this flag when doing the initial setup:
|
149
|
+
```ruby
|
150
|
+
Lhm.setup(connection, options: {reconnect_with_consistent_host: true})
|
151
|
+
```
|
152
|
+
**Note**: This feature is disabled by default
|
153
|
+
|
112
154
|
## Throttler
|
113
155
|
|
114
156
|
LHM uses a throttling mechanism to read data in your original table. By default, 2,000 rows are read each 0.1 second. If you want to change that behaviour, you can pass an instance of a throttler with the `throttler` option. In this example, 1,000 rows will be read with a 10 second delay between each processing:
|
data/Rakefile
CHANGED
data/dev.yml
CHANGED
@@ -5,12 +5,16 @@ up:
|
|
5
5
|
or: [mysql@5.7]
|
6
6
|
conflicts: [shopify/shopify/mysql-client, mysql-connector-c, mysql, mysql-client]
|
7
7
|
- wget
|
8
|
-
- ruby: 2.
|
8
|
+
- ruby: 2.7.0
|
9
9
|
- bundler
|
10
|
+
- custom:
|
11
|
+
name: Get Appraisal gems
|
12
|
+
met?: bundle exec appraisal install
|
13
|
+
meet: ":"
|
10
14
|
- docker
|
11
15
|
- custom:
|
12
16
|
name: Docker Compose
|
13
|
-
met?: docker compose ls | grep -ioE -q "lhm.*running\(
|
17
|
+
met?: docker compose ls | grep -ioE -q "lhm.*running\(4\)"
|
14
18
|
meet: docker compose up -d
|
15
19
|
- custom:
|
16
20
|
name: Waiting for DBs to be operational
|
@@ -20,8 +24,19 @@ up:
|
|
20
24
|
commands:
|
21
25
|
unit: bundle exec rake unit
|
22
26
|
int: bundle exec rake integration
|
23
|
-
test:
|
27
|
+
test:
|
28
|
+
optional: file
|
29
|
+
aliases: [ t ]
|
30
|
+
run: |
|
31
|
+
if [[ $# -eq 0 ]]; then
|
32
|
+
bundle exec rake unit && bundle exec rake integration
|
33
|
+
else
|
34
|
+
bundle exec rake dev TEST="$@"
|
35
|
+
fi
|
36
|
+
appraisals: bundle exec appraisal rake specs
|
24
37
|
cov: rm -rf coverage; COV=1 bundle exec rake unit && bundle exec rake integration; open coverage/index.html
|
25
38
|
logs:
|
26
39
|
desc: "See the DB logs (ctrl-c + ctrl-c to exit)"
|
27
40
|
run: docker-compose logs -f
|
41
|
+
clear:
|
42
|
+
run: docker-compose rm -v -s -f && docker-compose up -d && ./scripts/helpers/wait-for-dbs.sh
|
data/docker-compose.yml
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
services:
|
2
|
-
# Writer
|
2
|
+
# Writer
|
3
3
|
mysql-1:
|
4
4
|
container_name: mysql-1
|
5
5
|
image: percona:5.7
|
6
6
|
command:
|
7
7
|
--server-id=1
|
8
|
+
--log-bin
|
8
9
|
--log-slave-updates=ON
|
9
10
|
--gtid-mode=ON
|
10
11
|
--enforce-gtid-consistency=ON
|
11
12
|
--read-only=OFF
|
13
|
+
--max-connections=1000
|
12
14
|
hostname: 'mysql-1'
|
13
15
|
volumes:
|
14
16
|
- ./scripts/mysql/writer:/docker-entrypoint-initdb.d
|
@@ -17,16 +19,18 @@ services:
|
|
17
19
|
MYSQL_HOST: mysql-1
|
18
20
|
ports:
|
19
21
|
- "33006:3306"
|
20
|
-
# Reader
|
22
|
+
# Reader
|
21
23
|
mysql-2:
|
22
24
|
container_name: mysql-2
|
23
25
|
image: percona:5.7
|
24
26
|
command:
|
25
27
|
--server-id=2
|
28
|
+
--log-bin
|
26
29
|
--log-slave-updates=ON
|
27
30
|
--gtid-mode=ON
|
28
31
|
--enforce-gtid-consistency=ON
|
29
32
|
--read-only=ON
|
33
|
+
--max-connections=1000
|
30
34
|
hostname: 'mysql-2'
|
31
35
|
volumes:
|
32
36
|
- ./scripts/mysql/reader:/docker-entrypoint-initdb.d
|
@@ -35,7 +39,7 @@ services:
|
|
35
39
|
MYSQL_HOST: mysql-2
|
36
40
|
ports:
|
37
41
|
- "33007:3306"
|
38
|
-
# Proxysql
|
42
|
+
# Proxysql
|
39
43
|
proxysql:
|
40
44
|
container_name: proxysql
|
41
45
|
image: proxysql/proxysql:2.0.11
|
@@ -44,3 +48,11 @@ services:
|
|
44
48
|
command: "proxysql -c /etc/proxysql.cnf -f --idle-threads"
|
45
49
|
ports:
|
46
50
|
- "33005:3306"
|
51
|
+
- "6032:6032"
|
52
|
+
toxiproxy:
|
53
|
+
container_name: toxiproxy
|
54
|
+
image: "ghcr.io/shopify/toxiproxy"
|
55
|
+
ports:
|
56
|
+
- "8474:8474"
|
57
|
+
- "22220:22220"
|
58
|
+
- "22222:22222"
|
@@ -0,0 +1,65 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
lhm-shopify (3.5.1)
|
5
|
+
retriable (>= 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (5.2.6)
|
11
|
+
activesupport (= 5.2.6)
|
12
|
+
activerecord (5.2.6)
|
13
|
+
activemodel (= 5.2.6)
|
14
|
+
activesupport (= 5.2.6)
|
15
|
+
arel (>= 9.0)
|
16
|
+
activesupport (5.2.6)
|
17
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
18
|
+
i18n (>= 0.7, < 2)
|
19
|
+
minitest (~> 5.1)
|
20
|
+
tzinfo (~> 1.1)
|
21
|
+
after_do (0.4.0)
|
22
|
+
appraisal (2.4.1)
|
23
|
+
bundler
|
24
|
+
rake
|
25
|
+
thor (>= 0.14.0)
|
26
|
+
arel (9.0.0)
|
27
|
+
byebug (11.1.3)
|
28
|
+
concurrent-ruby (1.1.9)
|
29
|
+
docile (1.3.5)
|
30
|
+
i18n (1.8.11)
|
31
|
+
concurrent-ruby (~> 1.0)
|
32
|
+
minitest (5.14.4)
|
33
|
+
mocha (1.13.0)
|
34
|
+
mysql2 (0.5.3)
|
35
|
+
rake (13.0.6)
|
36
|
+
retriable (3.1.2)
|
37
|
+
simplecov (0.18.5)
|
38
|
+
docile (~> 1.1)
|
39
|
+
simplecov-html (~> 0.11)
|
40
|
+
simplecov-html (0.12.3)
|
41
|
+
thor (1.1.0)
|
42
|
+
thread_safe (0.3.6)
|
43
|
+
toxiproxy (2.0.0)
|
44
|
+
tzinfo (1.2.9)
|
45
|
+
thread_safe (~> 0.1)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
x86_64-darwin-20
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
activerecord (= 5.2.6)
|
52
|
+
after_do
|
53
|
+
appraisal
|
54
|
+
byebug
|
55
|
+
docile (= 1.3.5)
|
56
|
+
lhm-shopify!
|
57
|
+
minitest
|
58
|
+
mocha
|
59
|
+
mysql2
|
60
|
+
rake
|
61
|
+
simplecov (= 0.18.5)
|
62
|
+
toxiproxy
|
63
|
+
|
64
|
+
BUNDLED WITH
|
65
|
+
2.2.22
|
@@ -0,0 +1,67 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
lhm-shopify (3.5.1)
|
5
|
+
retriable (>= 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (6.0.0)
|
11
|
+
activesupport (= 6.0.0)
|
12
|
+
activerecord (6.0.0)
|
13
|
+
activemodel (= 6.0.0)
|
14
|
+
activesupport (= 6.0.0)
|
15
|
+
activesupport (6.0.0)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 0.7, < 2)
|
18
|
+
minitest (~> 5.1)
|
19
|
+
tzinfo (~> 1.1)
|
20
|
+
zeitwerk (~> 2.1, >= 2.1.8)
|
21
|
+
after_do (0.4.0)
|
22
|
+
appraisal (2.4.1)
|
23
|
+
bundler
|
24
|
+
rake
|
25
|
+
thor (>= 0.14.0)
|
26
|
+
byebug (11.1.3)
|
27
|
+
concurrent-ruby (1.1.9)
|
28
|
+
docile (1.4.0)
|
29
|
+
i18n (1.8.11)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
minitest (5.14.4)
|
32
|
+
mocha (1.13.0)
|
33
|
+
mysql2 (0.5.3)
|
34
|
+
rake (13.0.6)
|
35
|
+
retriable (3.1.2)
|
36
|
+
simplecov (0.21.2)
|
37
|
+
docile (~> 1.1)
|
38
|
+
simplecov-html (~> 0.11)
|
39
|
+
simplecov_json_formatter (~> 0.1)
|
40
|
+
simplecov-html (0.12.3)
|
41
|
+
simplecov_json_formatter (0.1.3)
|
42
|
+
thor (1.1.0)
|
43
|
+
thread_safe (0.3.6)
|
44
|
+
toxiproxy (2.0.0)
|
45
|
+
tzinfo (1.2.9)
|
46
|
+
thread_safe (~> 0.1)
|
47
|
+
zeitwerk (2.5.1)
|
48
|
+
|
49
|
+
PLATFORMS
|
50
|
+
x86_64-darwin-20
|
51
|
+
x86_64-linux
|
52
|
+
|
53
|
+
DEPENDENCIES
|
54
|
+
activerecord (= 6.0.0)
|
55
|
+
after_do
|
56
|
+
appraisal
|
57
|
+
byebug
|
58
|
+
lhm-shopify!
|
59
|
+
minitest
|
60
|
+
mocha
|
61
|
+
mysql2
|
62
|
+
rake
|
63
|
+
simplecov
|
64
|
+
toxiproxy
|
65
|
+
|
66
|
+
BUNDLED WITH
|
67
|
+
2.2.22
|
@@ -0,0 +1,66 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
lhm-shopify (3.5.1)
|
5
|
+
retriable (>= 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (6.1.0)
|
11
|
+
activesupport (= 6.1.0)
|
12
|
+
activerecord (6.1.0)
|
13
|
+
activemodel (= 6.1.0)
|
14
|
+
activesupport (= 6.1.0)
|
15
|
+
activesupport (6.1.0)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 1.6, < 2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
tzinfo (~> 2.0)
|
20
|
+
zeitwerk (~> 2.3)
|
21
|
+
after_do (0.4.0)
|
22
|
+
appraisal (2.4.1)
|
23
|
+
bundler
|
24
|
+
rake
|
25
|
+
thor (>= 0.14.0)
|
26
|
+
byebug (11.1.3)
|
27
|
+
concurrent-ruby (1.1.9)
|
28
|
+
docile (1.4.0)
|
29
|
+
i18n (1.8.11)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
minitest (5.14.4)
|
32
|
+
mocha (1.13.0)
|
33
|
+
mysql2 (0.5.3)
|
34
|
+
rake (13.0.6)
|
35
|
+
retriable (3.1.2)
|
36
|
+
simplecov (0.21.2)
|
37
|
+
docile (~> 1.1)
|
38
|
+
simplecov-html (~> 0.11)
|
39
|
+
simplecov_json_formatter (~> 0.1)
|
40
|
+
simplecov-html (0.12.3)
|
41
|
+
simplecov_json_formatter (0.1.3)
|
42
|
+
thor (1.1.0)
|
43
|
+
toxiproxy (2.0.0)
|
44
|
+
tzinfo (2.0.4)
|
45
|
+
concurrent-ruby (~> 1.0)
|
46
|
+
zeitwerk (2.5.1)
|
47
|
+
|
48
|
+
PLATFORMS
|
49
|
+
x86_64-darwin-20
|
50
|
+
x86_64-linux
|
51
|
+
|
52
|
+
DEPENDENCIES
|
53
|
+
activerecord (= 6.1.0)
|
54
|
+
after_do
|
55
|
+
appraisal
|
56
|
+
byebug
|
57
|
+
lhm-shopify!
|
58
|
+
minitest
|
59
|
+
mocha
|
60
|
+
mysql2
|
61
|
+
rake
|
62
|
+
simplecov
|
63
|
+
toxiproxy
|
64
|
+
|
65
|
+
BUNDLED WITH
|
66
|
+
2.2.22
|
@@ -0,0 +1,64 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ..
|
3
|
+
specs:
|
4
|
+
lhm-shopify (3.5.1)
|
5
|
+
retriable (>= 3.0.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activemodel (7.0.0.alpha2)
|
11
|
+
activesupport (= 7.0.0.alpha2)
|
12
|
+
activerecord (7.0.0.alpha2)
|
13
|
+
activemodel (= 7.0.0.alpha2)
|
14
|
+
activesupport (= 7.0.0.alpha2)
|
15
|
+
activesupport (7.0.0.alpha2)
|
16
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
|
+
i18n (>= 1.6, < 2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
tzinfo (~> 2.0)
|
20
|
+
after_do (0.4.0)
|
21
|
+
appraisal (2.4.1)
|
22
|
+
bundler
|
23
|
+
rake
|
24
|
+
thor (>= 0.14.0)
|
25
|
+
byebug (11.1.3)
|
26
|
+
concurrent-ruby (1.1.9)
|
27
|
+
docile (1.4.0)
|
28
|
+
i18n (1.8.11)
|
29
|
+
concurrent-ruby (~> 1.0)
|
30
|
+
minitest (5.14.4)
|
31
|
+
mocha (1.13.0)
|
32
|
+
mysql2 (0.5.3)
|
33
|
+
rake (13.0.6)
|
34
|
+
retriable (3.1.2)
|
35
|
+
simplecov (0.21.2)
|
36
|
+
docile (~> 1.1)
|
37
|
+
simplecov-html (~> 0.11)
|
38
|
+
simplecov_json_formatter (~> 0.1)
|
39
|
+
simplecov-html (0.12.3)
|
40
|
+
simplecov_json_formatter (0.1.3)
|
41
|
+
thor (1.1.0)
|
42
|
+
toxiproxy (2.0.0)
|
43
|
+
tzinfo (2.0.4)
|
44
|
+
concurrent-ruby (~> 1.0)
|
45
|
+
|
46
|
+
PLATFORMS
|
47
|
+
x86_64-darwin-20
|
48
|
+
x86_64-linux
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
activerecord (= 7.0.0.alpha2)
|
52
|
+
after_do
|
53
|
+
appraisal
|
54
|
+
byebug
|
55
|
+
lhm-shopify!
|
56
|
+
minitest
|
57
|
+
mocha
|
58
|
+
mysql2
|
59
|
+
rake
|
60
|
+
simplecov
|
61
|
+
toxiproxy
|
62
|
+
|
63
|
+
BUNDLED WITH
|
64
|
+
2.2.22
|
data/lhm.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$:.unshift(lib) unless $:.include?(lib)
|
5
5
|
|
6
6
|
require 'lhm/version'
|
@@ -25,10 +25,14 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.add_dependency 'retriable', '>= 3.0.0'
|
27
27
|
|
28
|
+
s.add_development_dependency 'activerecord'
|
28
29
|
s.add_development_dependency 'minitest'
|
29
30
|
s.add_development_dependency 'mocha'
|
31
|
+
s.add_development_dependency 'after_do'
|
30
32
|
s.add_development_dependency 'rake'
|
31
|
-
s.add_development_dependency 'activerecord'
|
32
33
|
s.add_development_dependency 'mysql2'
|
33
34
|
s.add_development_dependency 'simplecov'
|
35
|
+
s.add_development_dependency 'toxiproxy'
|
36
|
+
s.add_development_dependency 'appraisal'
|
37
|
+
s.add_development_dependency 'byebug'
|
34
38
|
end
|
data/lib/lhm/atomic_switcher.rb
CHANGED
data/lib/lhm/chunk_insert.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'lhm/sql_retry'
|
2
|
+
require 'lhm/proxysql_helper'
|
2
3
|
|
3
4
|
module Lhm
|
4
5
|
class ChunkInsert
|
@@ -11,7 +12,7 @@ module Lhm
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def insert_and_return_count_of_rows_created
|
14
|
-
@connection.update(sql, @retry_options)
|
15
|
+
@connection.update(sql, should_retry: true, retry_options: @retry_options)
|
15
16
|
end
|
16
17
|
|
17
18
|
def sql
|
data/lib/lhm/chunker.rb
CHANGED
@@ -31,7 +31,7 @@ module Lhm
|
|
31
31
|
@retry_options = options[:retriable] || {}
|
32
32
|
@retry_helper = SqlRetry.new(
|
33
33
|
@connection,
|
34
|
-
{
|
34
|
+
options: {
|
35
35
|
log_prefix: "Chunker"
|
36
36
|
}.merge!(@retry_options)
|
37
37
|
)
|
@@ -79,7 +79,7 @@ module Lhm
|
|
79
79
|
private
|
80
80
|
|
81
81
|
def raise_on_non_pk_duplicate_warning
|
82
|
-
@connection.execute("show warnings", @retry_options).each do |level, code, message|
|
82
|
+
@connection.execute("show warnings", should_retry: true, retry_options: @retry_options).each do |level, code, message|
|
83
83
|
unless message.match?(/Duplicate entry .+ for key 'PRIMARY'/)
|
84
84
|
m = "Unexpected warning found for inserted row: #{message}"
|
85
85
|
Lhm.logger.warn(m)
|
@@ -101,7 +101,7 @@ module Lhm
|
|
101
101
|
|
102
102
|
def upper_id(next_id, stride)
|
103
103
|
sql = "select id from `#{ @migration.origin_name }` where id >= #{ next_id } order by id limit 1 offset #{ stride - 1}"
|
104
|
-
top = @connection.select_value(sql, @retry_options)
|
104
|
+
top = @connection.select_value(sql, should_retry: true, retry_options: @retry_options)
|
105
105
|
|
106
106
|
[top ? top.to_i : @limit, @limit].min
|
107
107
|
end
|