lhm-shopify 4.0.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +20 -18
- data/Appraisals +5 -11
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +22 -7
- data/README.md +7 -7
- data/dev.yml +4 -1
- data/docker-compose-mysql-5.7.yml +1 -0
- data/docker-compose-mysql-8.0.yml +63 -0
- data/docker-compose.yml +3 -3
- data/gemfiles/activerecord_6.1.gemfile +1 -0
- data/gemfiles/activerecord_6.1.gemfile.lock +8 -2
- data/gemfiles/activerecord_7.0.gemfile +1 -0
- data/gemfiles/activerecord_7.0.gemfile.lock +7 -1
- data/gemfiles/{activerecord_6.0.gemfile → activerecord_7.1.gemfile} +1 -1
- data/gemfiles/{activerecord_7.1.0.beta1.gemfile.lock → activerecord_7.1.gemfile.lock} +10 -8
- data/lhm.gemspec +1 -0
- data/lib/lhm/atomic_switcher.rb +3 -3
- data/lib/lhm/chunker.rb +8 -7
- data/lib/lhm/connection.rb +9 -1
- data/lib/lhm/sql_retry.rb +36 -18
- data/lib/lhm/table.rb +3 -4
- data/lib/lhm/throttler/replica_lag.rb +17 -13
- 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/integration/atomic_switcher_spec.rb +4 -8
- data/spec/integration/chunker_spec.rb +23 -9
- data/spec/integration/database.yml +3 -3
- data/spec/integration/integration_helper.rb +11 -3
- data/spec/integration/lhm_spec.rb +29 -13
- 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/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/throttler/replica_lag_spec.rb +6 -14
- metadata +21 -8
- data/.travis.yml +0 -21
- data/gemfiles/activerecord_6.0.gemfile.lock +0 -71
- data/gemfiles/activerecord_7.1.0.beta1.gemfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49f23bf2b018fc5af679644fb6c9f424f943a0d4dd58d7e2d8366b389ae4270b
|
4
|
+
data.tar.gz: 14e15f4fc464d721b20889a1841c4a78a609bb3c6aee1a68ee5f3f5e3e89d2ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86a7153f5278bdf8d26ebd0ca668dab3e4861ad5349e1115796a59b72ac7c8b0eb920cbe74f443e9913efd5b8c2861499c98ba37990d970177e273188656d02a
|
7
|
+
data.tar.gz: f394a26a3dcf8e5737748610db039b28e9cde415a5a82f3b2f29f358f93124155ee6be68c8196bf027b807aedf19feb6f7a60d89097384242f31e65c96907fc7
|
data/.github/workflows/test.yml
CHANGED
@@ -14,30 +14,32 @@ jobs:
|
|
14
14
|
strategy:
|
15
15
|
fail-fast: false
|
16
16
|
matrix:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
activerecord: ["6.1", "7.0", "7.1"]
|
18
|
+
ruby: ["3.0", "3.1", "3.2", "head"]
|
19
|
+
mysql: ["5.7", "8.0"]
|
20
|
+
adapter: ["mysql2", "trilogy"]
|
21
|
+
|
22
|
+
env:
|
23
|
+
BUNDLE_GEMFILE: "${{ github.workspace }}/gemfiles/activerecord_${{ matrix.activerecord }}.gemfile"
|
24
|
+
DATABASE_ADAPTER: "${{ matrix.adapter }}"
|
25
|
+
|
26
26
|
steps:
|
27
|
-
- uses: actions/checkout@
|
28
|
-
-
|
29
|
-
uses: ruby/setup-ruby@v1
|
27
|
+
- uses: actions/checkout@v4
|
28
|
+
- uses: ruby/setup-ruby@v1
|
30
29
|
with:
|
31
|
-
ruby-version: ${{matrix.ruby
|
32
|
-
bundler-cache:
|
33
|
-
|
34
|
-
run: BUNDLE_GEMFILE="${GITHUB_WORKSPACE}/gemfiles/activerecord_${{ matrix.activerecord-version }}.gemfile" bundle install
|
30
|
+
ruby-version: ${{matrix.ruby}}
|
31
|
+
bundler-cache: true
|
32
|
+
|
35
33
|
- name: Install Ubuntu packages
|
36
34
|
run: sudo apt-get update && sudo apt-get install numactl libaio-dev libmysqlclient-dev
|
35
|
+
|
37
36
|
- name: Setup MySQL and ProxySQL (docker-compose)
|
38
|
-
|
37
|
+
# Might have to change to docker compose up -d (i.e. Compose V2) when the Ubuntu image changes the docker-compose version
|
38
|
+
run: docker-compose -f docker-compose-mysql-${{ matrix.mysql }}.yml up -d
|
39
|
+
|
39
40
|
- name: Wait until DBs are alive
|
40
41
|
run: ./scripts/helpers/wait-for-dbs.sh
|
41
42
|
timeout-minutes: 2
|
43
|
+
|
42
44
|
- name: Run tests
|
43
|
-
run:
|
45
|
+
run: bundle exec rake specs
|
data/Appraisals
CHANGED
@@ -1,19 +1,13 @@
|
|
1
|
-
# First conflicted version
|
2
|
-
appraise "activerecord-6.0" do
|
3
|
-
gem "activerecord", "6.0.3"
|
4
|
-
end
|
5
|
-
|
6
|
-
# Second conflicted version
|
7
1
|
appraise "activerecord-6.1" do
|
8
2
|
gem "activerecord", "6.1.0"
|
3
|
+
gem "activerecord-trilogy-adapter"
|
9
4
|
end
|
10
5
|
|
11
|
-
# Latest version at the moment
|
12
6
|
appraise "activerecord-7.0" do
|
13
7
|
gem "activerecord", "7.0.8"
|
8
|
+
gem "activerecord-trilogy-adapter"
|
14
9
|
end
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
11
|
+
appraise "activerecord-7.1" do
|
12
|
+
gem "activerecord", "7.1.1"
|
13
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 4.1.1 (Nov, 2023)
|
4
|
+
* Fix check for warnings against PK in MySQL 8+
|
5
|
+
|
6
|
+
# 4.1.0 (Oct, 2023)
|
7
|
+
* Test against MySQL 8.0.
|
8
|
+
* Test against Ruby Head.
|
9
|
+
* Drop support for ActiveRecord below version 6.1, as it has reached EOL.
|
10
|
+
* Add support for Trilogy MySQL client. It's works with built in ActiveRecord adapter from Rails 7.1 on, as well as dedicated one in older Rails versions.
|
11
|
+
|
3
12
|
# 4.0.0 (Sep, 2023)
|
4
13
|
* Deprecate `SlaveLag` throttler class name. Use `ReplicaLag` instead (https://github.com/Shopify/lhm/pull/144)
|
5
14
|
* Deprecate `slave_lag_throttler` throttler config value. Use `replica_lag_throttler` instead (https://github.com/Shopify/lhm/pull/144)
|
data/Gemfile.lock
CHANGED
@@ -1,35 +1,47 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.1.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (7.
|
11
|
-
activesupport (= 7.
|
12
|
-
activerecord (7.
|
13
|
-
activemodel (= 7.
|
14
|
-
activesupport (= 7.
|
15
|
-
|
10
|
+
activemodel (7.1.1)
|
11
|
+
activesupport (= 7.1.1)
|
12
|
+
activerecord (7.1.1)
|
13
|
+
activemodel (= 7.1.1)
|
14
|
+
activesupport (= 7.1.1)
|
15
|
+
timeout (>= 0.4.0)
|
16
|
+
activesupport (7.1.1)
|
17
|
+
base64
|
18
|
+
bigdecimal
|
16
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
20
|
+
connection_pool (>= 2.2.5)
|
21
|
+
drb
|
17
22
|
i18n (>= 1.6, < 2)
|
18
23
|
minitest (>= 5.1)
|
24
|
+
mutex_m
|
19
25
|
tzinfo (~> 2.0)
|
20
26
|
after_do (0.4.0)
|
21
27
|
appraisal (2.5.0)
|
22
28
|
bundler
|
23
29
|
rake
|
24
30
|
thor (>= 0.14.0)
|
31
|
+
base64 (0.1.1)
|
32
|
+
bigdecimal (3.1.4)
|
25
33
|
byebug (11.1.3)
|
26
34
|
concurrent-ruby (1.2.2)
|
35
|
+
connection_pool (2.4.1)
|
27
36
|
docile (1.4.0)
|
37
|
+
drb (2.1.1)
|
38
|
+
ruby2_keywords
|
28
39
|
i18n (1.14.1)
|
29
40
|
concurrent-ruby (~> 1.0)
|
30
41
|
minitest (5.20.0)
|
31
42
|
mocha (2.1.0)
|
32
43
|
ruby2_keywords (>= 0.0.5)
|
44
|
+
mutex_m (0.1.2)
|
33
45
|
mysql2 (0.5.5)
|
34
46
|
rake (13.0.6)
|
35
47
|
retriable (3.1.2)
|
@@ -41,7 +53,9 @@ GEM
|
|
41
53
|
simplecov-html (0.12.3)
|
42
54
|
simplecov_json_formatter (0.1.4)
|
43
55
|
thor (1.2.2)
|
56
|
+
timeout (0.4.0)
|
44
57
|
toxiproxy (2.0.2)
|
58
|
+
trilogy (2.6.0)
|
45
59
|
tzinfo (2.0.6)
|
46
60
|
concurrent-ruby (~> 1.0)
|
47
61
|
|
@@ -63,6 +77,7 @@ DEPENDENCIES
|
|
63
77
|
rake
|
64
78
|
simplecov
|
65
79
|
toxiproxy
|
80
|
+
trilogy
|
66
81
|
|
67
82
|
BUNDLED WITH
|
68
83
|
2.2.22
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://github.com/Shopify/lhm/actions/workflows/test.yml)
|
4
4
|
|
5
|
-
This is the Shopify fork of [SoundCloud's LHM](https://github.com/soundcloud/lhm). The
|
5
|
+
This is the Shopify fork of [SoundCloud's LHM](https://github.com/soundcloud/lhm). The
|
6
6
|
following description, originally from SoundCloud (with minor updates by Shopify),
|
7
7
|
gives some of the flavor around its original creation, and its choice of name...
|
8
8
|
|
@@ -112,7 +112,7 @@ tables must be cleaned up.
|
|
112
112
|
### Usage with ProxySQL
|
113
113
|
LHM can recover from connection loss. However, when used in conjunction with ProxySQL, there are multiple ways that
|
114
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.
|
115
|
+
ensure that the MySQL host stays consistent across the schema migrations if the feature is enabled.
|
116
116
|
This is done by tagging every query with `/*maintenance:lhm*/`, which will be recognized by ProxySQL.
|
117
117
|
However, to get this feature working, a new ProxySQL query rule must be added.
|
118
118
|
```cnf
|
@@ -127,7 +127,7 @@ However, to get this feature working, a new ProxySQL query rule must be added.
|
|
127
127
|
This will ensure that all relevant queries are forwarded to the current writer.
|
128
128
|
|
129
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
|
130
|
+
Therefore, the following rules must be added to ensure that queries (even if tagged with `/*maintenance:lhm*/`) get
|
131
131
|
forwarded to the right target.
|
132
132
|
```cnf
|
133
133
|
{
|
@@ -144,7 +144,7 @@ forwarded to the right target.
|
|
144
144
|
}
|
145
145
|
```
|
146
146
|
|
147
|
-
Once these changes are added to the ProxySQL configuration (either through `.cnf` or dynamically through the admin interface),
|
147
|
+
Once these changes are added to the ProxySQL configuration (either through `.cnf` or dynamically through the admin interface),
|
148
148
|
the feature can be enabled. This is done by adding this flag when providing options to the migration:
|
149
149
|
```ruby
|
150
150
|
Lhm.change_table(..., options: {reconnect_with_consistent_host: true}) do |t|
|
@@ -285,7 +285,7 @@ To run the tests:
|
|
285
285
|
```bash
|
286
286
|
bundle exec rake unit # unit tests
|
287
287
|
bundle exec rake integration # integration tests
|
288
|
-
bundle exec rake
|
288
|
+
bundle exec rake specs # all tests
|
289
289
|
```
|
290
290
|
|
291
291
|
You can run an individual test as follows:
|
@@ -311,12 +311,12 @@ open coverage/index.html
|
|
311
311
|
```
|
312
312
|
|
313
313
|
### Merging for a new version
|
314
|
-
When creating a PR for a new version, make sure that th version has been bumped in `lib/lhm/version.rb`. Then run the following code snippet to ensure the everything is consistent, otherwise
|
314
|
+
When creating a PR for a new version, make sure that th version has been bumped in `lib/lhm/version.rb`. Then run the following code snippet to ensure the everything is consistent, otherwise
|
315
315
|
the gem will not publish.
|
316
316
|
```bash
|
317
317
|
bundle install
|
318
318
|
bundle update
|
319
|
-
bundle exec
|
319
|
+
bundle exec appraisal install
|
320
320
|
```
|
321
321
|
|
322
322
|
### Podman Compose
|
data/dev.yml
CHANGED
@@ -14,7 +14,7 @@ up:
|
|
14
14
|
meet: ":"
|
15
15
|
- custom:
|
16
16
|
name: Podman compose
|
17
|
-
met?: podman-compose
|
17
|
+
met?: podman-compose ps | grep -ioE -q "lhm.*running\(4\)"
|
18
18
|
meet: podman-compose up -d
|
19
19
|
- custom:
|
20
20
|
name: Waiting for DBs to be operational
|
@@ -41,6 +41,9 @@ commands:
|
|
41
41
|
run: podman-compose logs -f
|
42
42
|
clear:
|
43
43
|
run: podman-compose down -v && podman-compose up -d && ./scripts/helpers/wait-for-dbs.sh
|
44
|
+
subcommands:
|
45
|
+
mysql-5.7: podman-compose down -v && podman-compose -f docker-compose-mysql-5.7.yml up -d && ./scripts/helpers/wait-for-dbs.sh
|
46
|
+
mysql-8.0: podman-compose down -v && podman-compose -f docker-compose-mysql-8.0.yml up -d && ./scripts/helpers/wait-for-dbs.sh
|
44
47
|
pre-publish:
|
45
48
|
# Ensures all Gemfile.lock are sync with the new version in `lhm/version.rb` and runs appraisals
|
46
49
|
run: bundle install && bundle exec appraisal install && bundle exec appraisal rake specs
|
@@ -0,0 +1 @@
|
|
1
|
+
docker-compose.yml
|
@@ -0,0 +1,63 @@
|
|
1
|
+
services:
|
2
|
+
# Writer
|
3
|
+
mysql-1:
|
4
|
+
container_name: mysql-1
|
5
|
+
image: percona:8.0
|
6
|
+
platform: linux/amd64
|
7
|
+
command:
|
8
|
+
--server-id=1
|
9
|
+
--log-bin
|
10
|
+
--log-slave-updates=ON
|
11
|
+
--gtid-mode=ON
|
12
|
+
--enforce-gtid-consistency=ON
|
13
|
+
--read-only=OFF
|
14
|
+
--max-connections=1000
|
15
|
+
--default-authentication-plugin=mysql_native_password
|
16
|
+
hostname: 'mysql-1'
|
17
|
+
volumes:
|
18
|
+
- ./scripts/mysql/writer:/docker-entrypoint-initdb.d
|
19
|
+
environment:
|
20
|
+
MYSQL_ROOT_PASSWORD: password
|
21
|
+
MYSQL_HOST: mysql-1
|
22
|
+
ports:
|
23
|
+
- "13006:3306"
|
24
|
+
# Reader
|
25
|
+
mysql-2:
|
26
|
+
container_name: mysql-2
|
27
|
+
image: percona:8.0
|
28
|
+
platform: linux/amd64
|
29
|
+
command:
|
30
|
+
--server-id=2
|
31
|
+
--log-bin
|
32
|
+
--log-slave-updates=ON
|
33
|
+
--gtid-mode=ON
|
34
|
+
--enforce-gtid-consistency=ON
|
35
|
+
--read-only=ON
|
36
|
+
--max-connections=1000
|
37
|
+
--default-authentication-plugin=mysql_native_password
|
38
|
+
hostname: 'mysql-2'
|
39
|
+
volumes:
|
40
|
+
- ./scripts/mysql/reader:/docker-entrypoint-initdb.d
|
41
|
+
environment:
|
42
|
+
MYSQL_ROOT_PASSWORD: password
|
43
|
+
MYSQL_HOST: mysql-2
|
44
|
+
ports:
|
45
|
+
- "13007:3306"
|
46
|
+
# Proxysql
|
47
|
+
proxysql:
|
48
|
+
container_name: proxysql
|
49
|
+
image: proxysql/proxysql:2.0.11
|
50
|
+
platform: linux/amd64
|
51
|
+
volumes:
|
52
|
+
- ./scripts/proxysql/proxysql.cnf:/etc/proxysql.cnf
|
53
|
+
command: "proxysql -c /etc/proxysql.cnf -f --idle-threads"
|
54
|
+
ports:
|
55
|
+
- "13005:3306"
|
56
|
+
- "6032:6032"
|
57
|
+
toxiproxy:
|
58
|
+
container_name: toxiproxy
|
59
|
+
image: "ghcr.io/shopify/toxiproxy"
|
60
|
+
ports:
|
61
|
+
- "8474:8474"
|
62
|
+
- "22220:22220"
|
63
|
+
- "22222:22222"
|
data/docker-compose.yml
CHANGED
@@ -19,7 +19,7 @@ services:
|
|
19
19
|
MYSQL_ROOT_PASSWORD: password
|
20
20
|
MYSQL_HOST: mysql-1
|
21
21
|
ports:
|
22
|
-
- "
|
22
|
+
- "13006:3306"
|
23
23
|
# Reader
|
24
24
|
mysql-2:
|
25
25
|
container_name: mysql-2
|
@@ -40,7 +40,7 @@ services:
|
|
40
40
|
MYSQL_ROOT_PASSWORD: password
|
41
41
|
MYSQL_HOST: mysql-2
|
42
42
|
ports:
|
43
|
-
- "
|
43
|
+
- "13007:3306"
|
44
44
|
# Proxysql
|
45
45
|
proxysql:
|
46
46
|
container_name: proxysql
|
@@ -49,7 +49,7 @@ services:
|
|
49
49
|
- ./scripts/proxysql/proxysql.cnf:/etc/proxysql.cnf
|
50
50
|
command: "proxysql -c /etc/proxysql.cnf -f --idle-threads"
|
51
51
|
ports:
|
52
|
-
- "
|
52
|
+
- "13005:3306"
|
53
53
|
- "6032:6032"
|
54
54
|
toxiproxy:
|
55
55
|
container_name: toxiproxy
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.1.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -12,6 +12,9 @@ GEM
|
|
12
12
|
activerecord (6.1.0)
|
13
13
|
activemodel (= 6.1.0)
|
14
14
|
activesupport (= 6.1.0)
|
15
|
+
activerecord-trilogy-adapter (3.1.2)
|
16
|
+
activerecord (>= 6.0.a, < 7.1.a)
|
17
|
+
trilogy (>= 2.4.0)
|
15
18
|
activesupport (6.1.0)
|
16
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
20
|
i18n (>= 1.6, < 2)
|
@@ -43,9 +46,10 @@ GEM
|
|
43
46
|
simplecov_json_formatter (0.1.4)
|
44
47
|
thor (1.2.2)
|
45
48
|
toxiproxy (2.0.2)
|
49
|
+
trilogy (2.6.0)
|
46
50
|
tzinfo (2.0.6)
|
47
51
|
concurrent-ruby (~> 1.0)
|
48
|
-
zeitwerk (2.6.
|
52
|
+
zeitwerk (2.6.12)
|
49
53
|
|
50
54
|
PLATFORMS
|
51
55
|
arm64-darwin-21
|
@@ -55,6 +59,7 @@ PLATFORMS
|
|
55
59
|
|
56
60
|
DEPENDENCIES
|
57
61
|
activerecord (= 6.1.0)
|
62
|
+
activerecord-trilogy-adapter
|
58
63
|
after_do
|
59
64
|
appraisal
|
60
65
|
byebug
|
@@ -65,6 +70,7 @@ DEPENDENCIES
|
|
65
70
|
rake
|
66
71
|
simplecov
|
67
72
|
toxiproxy
|
73
|
+
trilogy
|
68
74
|
|
69
75
|
BUNDLED WITH
|
70
76
|
2.2.22
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.1.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -12,6 +12,9 @@ GEM
|
|
12
12
|
activerecord (7.0.8)
|
13
13
|
activemodel (= 7.0.8)
|
14
14
|
activesupport (= 7.0.8)
|
15
|
+
activerecord-trilogy-adapter (3.1.2)
|
16
|
+
activerecord (>= 6.0.a, < 7.1.a)
|
17
|
+
trilogy (>= 2.4.0)
|
15
18
|
activesupport (7.0.8)
|
16
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
17
20
|
i18n (>= 1.6, < 2)
|
@@ -42,6 +45,7 @@ GEM
|
|
42
45
|
simplecov_json_formatter (0.1.4)
|
43
46
|
thor (1.2.2)
|
44
47
|
toxiproxy (2.0.2)
|
48
|
+
trilogy (2.6.0)
|
45
49
|
tzinfo (2.0.6)
|
46
50
|
concurrent-ruby (~> 1.0)
|
47
51
|
|
@@ -53,6 +57,7 @@ PLATFORMS
|
|
53
57
|
|
54
58
|
DEPENDENCIES
|
55
59
|
activerecord (= 7.0.8)
|
60
|
+
activerecord-trilogy-adapter
|
56
61
|
after_do
|
57
62
|
appraisal
|
58
63
|
byebug
|
@@ -63,6 +68,7 @@ DEPENDENCIES
|
|
63
68
|
rake
|
64
69
|
simplecov
|
65
70
|
toxiproxy
|
71
|
+
trilogy
|
66
72
|
|
67
73
|
BUNDLED WITH
|
68
74
|
2.2.22
|
@@ -1,19 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.1.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (7.1.
|
11
|
-
activesupport (= 7.1.
|
12
|
-
activerecord (7.1.
|
13
|
-
activemodel (= 7.1.
|
14
|
-
activesupport (= 7.1.
|
10
|
+
activemodel (7.1.1)
|
11
|
+
activesupport (= 7.1.1)
|
12
|
+
activerecord (7.1.1)
|
13
|
+
activemodel (= 7.1.1)
|
14
|
+
activesupport (= 7.1.1)
|
15
15
|
timeout (>= 0.4.0)
|
16
|
-
activesupport (7.1.
|
16
|
+
activesupport (7.1.1)
|
17
17
|
base64
|
18
18
|
bigdecimal
|
19
19
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
@@ -55,6 +55,7 @@ GEM
|
|
55
55
|
thor (1.2.2)
|
56
56
|
timeout (0.4.0)
|
57
57
|
toxiproxy (2.0.2)
|
58
|
+
trilogy (2.6.0)
|
58
59
|
tzinfo (2.0.6)
|
59
60
|
concurrent-ruby (~> 1.0)
|
60
61
|
|
@@ -65,7 +66,7 @@ PLATFORMS
|
|
65
66
|
x86_64-linux
|
66
67
|
|
67
68
|
DEPENDENCIES
|
68
|
-
activerecord (= 7.1.
|
69
|
+
activerecord (= 7.1.1)
|
69
70
|
after_do
|
70
71
|
appraisal
|
71
72
|
byebug
|
@@ -76,6 +77,7 @@ DEPENDENCIES
|
|
76
77
|
rake
|
77
78
|
simplecov
|
78
79
|
toxiproxy
|
80
|
+
trilogy
|
79
81
|
|
80
82
|
BUNDLED WITH
|
81
83
|
2.2.22
|
data/lhm.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_development_dependency 'after_do'
|
32
32
|
s.add_development_dependency 'rake'
|
33
33
|
s.add_development_dependency 'mysql2'
|
34
|
+
s.add_development_dependency 'trilogy'
|
34
35
|
s.add_development_dependency 'simplecov'
|
35
36
|
s.add_development_dependency 'toxiproxy'
|
36
37
|
s.add_development_dependency 'appraisal'
|
data/lib/lhm/atomic_switcher.rb
CHANGED
@@ -26,14 +26,14 @@ module Lhm
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def atomic_switch
|
29
|
-
"
|
30
|
-
"`#{ @destination.name }`
|
29
|
+
"RENAME TABLE `#{ @origin.name }` TO `#{ @migration.archive_name }`, " \
|
30
|
+
"`#{ @destination.name }` TO `#{ @origin.name }`"
|
31
31
|
end
|
32
32
|
|
33
33
|
def validate
|
34
34
|
unless @connection.data_source_exists?(@origin.name) &&
|
35
35
|
@connection.data_source_exists?(@destination.name)
|
36
|
-
error "`#{ @origin.name }`
|
36
|
+
error "`#{ @origin.name }` AND `#{ @destination.name }` MUST EXIST"
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
data/lib/lhm/chunker.rb
CHANGED
@@ -23,6 +23,7 @@ module Lhm
|
|
23
23
|
@chunk_finder = ChunkFinder.new(migration, connection, options)
|
24
24
|
@options = options
|
25
25
|
@raise_on_warnings = options.fetch(:raise_on_warnings, false)
|
26
|
+
@pk_duplicate_warning_regexp ||= /Duplicate entry .+ for key '(#{@migration.destination_name}\.)?PRIMARY'/
|
26
27
|
@verifier = options[:verifier]
|
27
28
|
if @throttler = options[:throttler]
|
28
29
|
@throttler.connection = @connection if @throttler.respond_to?(:connection=)
|
@@ -79,12 +80,12 @@ module Lhm
|
|
79
80
|
private
|
80
81
|
|
81
82
|
def raise_on_non_pk_duplicate_warning
|
82
|
-
@connection.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
@connection.select_all("SHOW WARNINGS", should_retry: true, log_prefix: LOG_PREFIX).each do |row|
|
84
|
+
next if row["Message"].match?(@pk_duplicate_warning_regexp)
|
85
|
+
|
86
|
+
m = "Unexpected warning found for inserted row: #{row["Message"]}"
|
87
|
+
Lhm.logger.warn(m)
|
88
|
+
raise Error.new(m) if @raise_on_warnings
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
@@ -100,7 +101,7 @@ module Lhm
|
|
100
101
|
end
|
101
102
|
|
102
103
|
def upper_id(next_id, stride)
|
103
|
-
sql = "
|
104
|
+
sql = "SELECT id FROM `#{ @migration.origin_name }` WHERE id >= #{ next_id } ORDER BY id LIMIT 1 OFFSET #{ stride - 1}"
|
104
105
|
top = @connection.select_value(sql, should_retry: true, log_prefix: LOG_PREFIX)
|
105
106
|
|
106
107
|
[top ? top.to_i : @limit, @limit].min
|
data/lib/lhm/connection.rb
CHANGED
@@ -75,6 +75,14 @@ module Lhm
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def select_all(query, should_retry: false, log_prefix: nil)
|
79
|
+
if should_retry
|
80
|
+
exec_with_retries(:select_all, query, log_prefix)
|
81
|
+
else
|
82
|
+
exec(:select_all, query)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
78
86
|
private
|
79
87
|
|
80
88
|
def exec(method, sql)
|
@@ -105,4 +113,4 @@ module Lhm
|
|
105
113
|
lhm_stack.at(first_candidate_index)
|
106
114
|
end
|
107
115
|
end
|
108
|
-
end
|
116
|
+
end
|