lhm 1.2.0 → 2.2.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 +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +256 -0
- data/.travis.yml +5 -1
- data/CHANGELOG.md +26 -0
- data/README.md +87 -8
- data/Rakefile +6 -4
- data/bin/lhm-config.sh +7 -0
- data/bin/lhm-kill-queue +13 -15
- data/bin/lhm-spec-clobber.sh +5 -4
- data/bin/lhm-spec-grants.sh +2 -2
- data/bin/lhm-spec-setup-cluster.sh +2 -3
- data/gemfiles/ar-2.3_mysql.gemfile +2 -1
- data/gemfiles/ar-3.2_mysql.gemfile +1 -1
- data/gemfiles/ar-3.2_mysql2.gemfile +1 -1
- data/gemfiles/dm_mysql.gemfile +1 -1
- data/lhm.gemspec +7 -8
- data/lib/lhm/atomic_switcher.rb +2 -1
- data/lib/lhm/chunker.rb +51 -39
- data/lib/lhm/command.rb +4 -2
- data/lib/lhm/connection.rb +14 -2
- data/lib/lhm/entangler.rb +5 -5
- data/lib/lhm/intersection.rb +29 -16
- data/lib/lhm/invoker.rb +31 -10
- data/lib/lhm/locked_switcher.rb +6 -6
- data/lib/lhm/migration.rb +7 -5
- data/lib/lhm/migrator.rb +57 -9
- data/lib/lhm/printer.rb +54 -0
- data/lib/lhm/sql_helper.rb +4 -4
- data/lib/lhm/table.rb +12 -12
- data/lib/lhm/throttler/time.rb +29 -0
- data/lib/lhm/throttler.rb +32 -0
- data/lib/lhm/version.rb +1 -1
- data/lib/lhm.rb +71 -6
- data/spec/.lhm.example +1 -1
- data/spec/README.md +20 -13
- data/spec/fixtures/lines.ddl +7 -0
- data/spec/fixtures/permissions.ddl +5 -0
- data/spec/fixtures/tracks.ddl +5 -0
- data/spec/fixtures/users.ddl +4 -2
- data/spec/integration/atomic_switcher_spec.rb +7 -7
- data/spec/integration/chunker_spec.rb +11 -5
- data/spec/integration/cleanup_spec.rb +72 -0
- data/spec/integration/entangler_spec.rb +11 -11
- data/spec/integration/integration_helper.rb +49 -17
- data/spec/integration/lhm_spec.rb +157 -37
- data/spec/integration/locked_switcher_spec.rb +7 -7
- data/spec/integration/table_spec.rb +15 -17
- data/spec/test_helper.rb +28 -0
- data/spec/unit/atomic_switcher_spec.rb +6 -6
- data/spec/unit/chunker_spec.rb +95 -73
- data/spec/unit/datamapper_connection_spec.rb +1 -0
- data/spec/unit/entangler_spec.rb +19 -19
- data/spec/unit/intersection_spec.rb +27 -15
- data/spec/unit/lhm_spec.rb +29 -0
- data/spec/unit/locked_switcher_spec.rb +14 -14
- data/spec/unit/migration_spec.rb +10 -5
- data/spec/unit/migrator_spec.rb +53 -41
- data/spec/unit/printer_spec.rb +79 -0
- data/spec/unit/sql_helper_spec.rb +10 -10
- data/spec/unit/table_spec.rb +11 -11
- data/spec/unit/throttler_spec.rb +73 -0
- data/spec/unit/unit_helper.rb +1 -13
- metadata +63 -24
- data/spec/bootstrap.rb +0 -13
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
2
|
+
|
3
|
+
require 'lhm/printer'
|
4
|
+
|
5
|
+
describe Lhm::Printer do
|
6
|
+
include UnitHelper
|
7
|
+
|
8
|
+
describe 'percentage printer' do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@printer = Lhm::Printer::Percentage.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'prints the percentage' do
|
15
|
+
mock = MiniTest::Mock.new
|
16
|
+
10.times do |i|
|
17
|
+
mock.expect(:write, :return_value) do |message|
|
18
|
+
assert_match /^\r/, message.first
|
19
|
+
assert_match /#{i}\/10/, message.first
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@printer.instance_variable_set(:@output, mock)
|
24
|
+
10.times { |i| @printer.notify(i, 10) }
|
25
|
+
mock.verify
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'always print a bigger message' do
|
29
|
+
@length = 0
|
30
|
+
mock = MiniTest::Mock.new
|
31
|
+
3.times do |i|
|
32
|
+
mock.expect(:write, :return_value) do |message|
|
33
|
+
assert message.first.length >= @length
|
34
|
+
@length = message.first.length
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@printer.instance_variable_set(:@output, mock)
|
39
|
+
@printer.notify(10, 100)
|
40
|
+
@printer.notify(0, 100)
|
41
|
+
@printer.notify(1, 1000000)
|
42
|
+
@printer.notify(0, 0)
|
43
|
+
@printer.notify(0, nil)
|
44
|
+
|
45
|
+
mock.verify
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'prints the end message' do
|
49
|
+
mock = MiniTest::Mock.new
|
50
|
+
mock.expect(:write, :return_value, [String])
|
51
|
+
mock.expect(:write, :return_value, ["\n"])
|
52
|
+
|
53
|
+
@printer.instance_variable_set(:@output, mock)
|
54
|
+
@printer.end
|
55
|
+
|
56
|
+
mock.verify
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'dot printer' do
|
61
|
+
|
62
|
+
before(:each) do
|
63
|
+
@printer = Lhm::Printer::Dot.new
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'prints the dots' do
|
67
|
+
mock = MiniTest::Mock.new
|
68
|
+
10.times do
|
69
|
+
mock.expect(:write, :return_value, ['.'])
|
70
|
+
end
|
71
|
+
|
72
|
+
@printer.instance_variable_set(:@output, mock)
|
73
|
+
10.times { @printer.notify }
|
74
|
+
|
75
|
+
mock.verify
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -6,27 +6,27 @@ require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
|
6
6
|
require 'lhm/sql_helper'
|
7
7
|
|
8
8
|
describe Lhm::SqlHelper do
|
9
|
-
it
|
9
|
+
it 'should name index with a single column' do
|
10
10
|
Lhm::SqlHelper.
|
11
11
|
idx_name(:users, :name).
|
12
|
-
must_equal(
|
12
|
+
must_equal('index_users_on_name')
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'should name index with multiple columns' do
|
16
16
|
Lhm::SqlHelper.
|
17
17
|
idx_name(:users, [:name, :firstname]).
|
18
|
-
must_equal(
|
18
|
+
must_equal('index_users_on_name_and_firstname')
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
21
|
+
it 'should name index with prefixed column' do
|
22
22
|
Lhm::SqlHelper.
|
23
|
-
idx_name(:tracks, [
|
24
|
-
must_equal(
|
23
|
+
idx_name(:tracks, ['title(10)', 'album']).
|
24
|
+
must_equal('index_tracks_on_title_and_album')
|
25
25
|
end
|
26
26
|
|
27
|
-
it
|
27
|
+
it 'should quote column names in index specification' do
|
28
28
|
Lhm::SqlHelper.
|
29
|
-
idx_spec([
|
30
|
-
must_equal(
|
29
|
+
idx_spec(['title(10)', 'album']).
|
30
|
+
must_equal('`title`(10), `album`')
|
31
31
|
end
|
32
32
|
end
|
data/spec/unit/table_spec.rb
CHANGED
@@ -8,26 +8,26 @@ require 'lhm/table'
|
|
8
8
|
describe Lhm::Table do
|
9
9
|
include UnitHelper
|
10
10
|
|
11
|
-
describe
|
12
|
-
it
|
13
|
-
@table = Lhm::Table.new(
|
14
|
-
@table.destination_name.must_equal
|
11
|
+
describe 'names' do
|
12
|
+
it 'should name destination' do
|
13
|
+
@table = Lhm::Table.new('users')
|
14
|
+
@table.destination_name.must_equal 'lhmn_users'
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
describe
|
19
|
-
it
|
20
|
-
@table = Lhm::Table.new(
|
18
|
+
describe 'constraints' do
|
19
|
+
it 'should be satisfied with a single column primary key called id' do
|
20
|
+
@table = Lhm::Table.new('table', 'id')
|
21
21
|
@table.satisfies_primary_key?.must_equal true
|
22
22
|
end
|
23
23
|
|
24
|
-
it
|
25
|
-
@table = Lhm::Table.new(
|
24
|
+
it 'should not be satisfied with a primary key unless called id' do
|
25
|
+
@table = Lhm::Table.new('table', 'uuid')
|
26
26
|
@table.satisfies_primary_key?.must_equal false
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
30
|
-
@table = Lhm::Table.new(
|
29
|
+
it 'should not be satisfied with multicolumn primary key' do
|
30
|
+
@table = Lhm::Table.new('table', ['id', 'secondary'])
|
31
31
|
@table.satisfies_primary_key?.must_equal false
|
32
32
|
end
|
33
33
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/unit_helper'
|
2
|
+
|
3
|
+
require 'lhm/throttler'
|
4
|
+
|
5
|
+
describe Lhm::Throttler do
|
6
|
+
include UnitHelper
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@mock = Class.new do
|
10
|
+
extend Lhm::Throttler
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#setup_throttler' do
|
15
|
+
describe 'when passing a key' do
|
16
|
+
before do
|
17
|
+
@mock.setup_throttler(:time_throttler, :delay => 2)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'instantiates the time throttle' do
|
21
|
+
@mock.throttler.class.must_equal Lhm::Throttler::Time
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns 2 seconds as time' do
|
25
|
+
@mock.throttler.timeout_seconds.must_equal 2
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'when passing an instance' do
|
30
|
+
|
31
|
+
before do
|
32
|
+
@instance = Class.new(Lhm::Throttler::Time) do
|
33
|
+
def timeout_seconds
|
34
|
+
0
|
35
|
+
end
|
36
|
+
end.new
|
37
|
+
|
38
|
+
@mock.setup_throttler(@instance)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the instace given' do
|
42
|
+
@mock.throttler.must_equal @instance
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns 0 seconds as time' do
|
46
|
+
@mock.throttler.timeout_seconds.must_equal 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'when passing a class' do
|
51
|
+
|
52
|
+
before do
|
53
|
+
@klass = Class.new(Lhm::Throttler::Time)
|
54
|
+
@mock.setup_throttler(@klass)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'has the same class as given' do
|
58
|
+
@mock.throttler.class.must_equal @klass
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#throttler' do
|
64
|
+
|
65
|
+
it 'returns the default Time based' do
|
66
|
+
@mock.throttler.class.must_equal Lhm::Throttler::Time
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should default to 100 milliseconds' do
|
70
|
+
@mock.throttler.timeout_seconds.must_equal 0.1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/spec/unit/unit_helper.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
# Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
|
2
2
|
# Schmidt
|
3
|
-
|
4
|
-
require File.expand_path(File.dirname(__FILE__)) + "/../bootstrap"
|
5
|
-
|
6
|
-
begin
|
7
|
-
require 'active_record'
|
8
|
-
begin
|
9
|
-
require 'mysql2'
|
10
|
-
rescue LoadError
|
11
|
-
require 'mysql'
|
12
|
-
end
|
13
|
-
rescue LoadError
|
14
|
-
require 'dm-core'
|
15
|
-
end
|
3
|
+
require 'test_helper'
|
16
4
|
|
17
5
|
module UnitHelper
|
18
6
|
def fixture(name)
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- SoundCloud
|
@@ -12,38 +11,34 @@ authors:
|
|
12
11
|
autorequire:
|
13
12
|
bindir: bin
|
14
13
|
cert_chain: []
|
15
|
-
date:
|
14
|
+
date: 2015-01-16 00:00:00.000000000 Z
|
16
15
|
dependencies:
|
17
16
|
- !ruby/object:Gem::Dependency
|
18
17
|
name: minitest
|
19
18
|
requirement: !ruby/object:Gem::Requirement
|
20
|
-
none: false
|
21
19
|
requirements:
|
22
|
-
- -
|
20
|
+
- - "~>"
|
23
21
|
- !ruby/object:Gem::Version
|
24
|
-
version:
|
22
|
+
version: 5.0.8
|
25
23
|
type: :development
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
26
|
requirements:
|
30
|
-
- -
|
27
|
+
- - "~>"
|
31
28
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
29
|
+
version: 5.0.8
|
33
30
|
- !ruby/object:Gem::Dependency
|
34
31
|
name: rake
|
35
32
|
requirement: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
33
|
requirements:
|
38
|
-
- -
|
34
|
+
- - ">="
|
39
35
|
- !ruby/object:Gem::Version
|
40
36
|
version: '0'
|
41
37
|
type: :development
|
42
38
|
prerelease: false
|
43
39
|
version_requirements: !ruby/object:Gem::Requirement
|
44
|
-
none: false
|
45
40
|
requirements:
|
46
|
-
- -
|
41
|
+
- - ">="
|
47
42
|
- !ruby/object:Gem::Version
|
48
43
|
version: '0'
|
49
44
|
description: Migrate large tables without downtime by copying to a temporary table
|
@@ -55,12 +50,14 @@ executables:
|
|
55
50
|
extensions: []
|
56
51
|
extra_rdoc_files: []
|
57
52
|
files:
|
58
|
-
- .gitignore
|
59
|
-
- .
|
53
|
+
- ".gitignore"
|
54
|
+
- ".rubocop.yml"
|
55
|
+
- ".travis.yml"
|
60
56
|
- CHANGELOG.md
|
61
57
|
- LICENSE
|
62
58
|
- README.md
|
63
59
|
- Rakefile
|
60
|
+
- bin/lhm-config.sh
|
64
61
|
- bin/lhm-kill-queue
|
65
62
|
- bin/lhm-spec-clobber.sh
|
66
63
|
- bin/lhm-spec-grants.sh
|
@@ -82,23 +79,30 @@ files:
|
|
82
79
|
- lib/lhm/locked_switcher.rb
|
83
80
|
- lib/lhm/migration.rb
|
84
81
|
- lib/lhm/migrator.rb
|
82
|
+
- lib/lhm/printer.rb
|
85
83
|
- lib/lhm/sql_helper.rb
|
86
84
|
- lib/lhm/table.rb
|
85
|
+
- lib/lhm/throttler.rb
|
86
|
+
- lib/lhm/throttler/time.rb
|
87
87
|
- lib/lhm/version.rb
|
88
88
|
- spec/.lhm.example
|
89
89
|
- spec/README.md
|
90
|
-
- spec/bootstrap.rb
|
91
90
|
- spec/fixtures/destination.ddl
|
91
|
+
- spec/fixtures/lines.ddl
|
92
92
|
- spec/fixtures/origin.ddl
|
93
|
+
- spec/fixtures/permissions.ddl
|
93
94
|
- spec/fixtures/small_table.ddl
|
95
|
+
- spec/fixtures/tracks.ddl
|
94
96
|
- spec/fixtures/users.ddl
|
95
97
|
- spec/integration/atomic_switcher_spec.rb
|
96
98
|
- spec/integration/chunker_spec.rb
|
99
|
+
- spec/integration/cleanup_spec.rb
|
97
100
|
- spec/integration/entangler_spec.rb
|
98
101
|
- spec/integration/integration_helper.rb
|
99
102
|
- spec/integration/lhm_spec.rb
|
100
103
|
- spec/integration/locked_switcher_spec.rb
|
101
104
|
- spec/integration/table_spec.rb
|
105
|
+
- spec/test_helper.rb
|
102
106
|
- spec/unit/active_record_connection_spec.rb
|
103
107
|
- spec/unit/atomic_switcher_spec.rb
|
104
108
|
- spec/unit/chunker_spec.rb
|
@@ -106,34 +110,69 @@ files:
|
|
106
110
|
- spec/unit/datamapper_connection_spec.rb
|
107
111
|
- spec/unit/entangler_spec.rb
|
108
112
|
- spec/unit/intersection_spec.rb
|
113
|
+
- spec/unit/lhm_spec.rb
|
109
114
|
- spec/unit/locked_switcher_spec.rb
|
110
115
|
- spec/unit/migration_spec.rb
|
111
116
|
- spec/unit/migrator_spec.rb
|
117
|
+
- spec/unit/printer_spec.rb
|
112
118
|
- spec/unit/sql_helper_spec.rb
|
113
119
|
- spec/unit/table_spec.rb
|
120
|
+
- spec/unit/throttler_spec.rb
|
114
121
|
- spec/unit/unit_helper.rb
|
115
|
-
homepage: http://github.com/soundcloud/
|
122
|
+
homepage: http://github.com/soundcloud/lhm
|
116
123
|
licenses: []
|
124
|
+
metadata: {}
|
117
125
|
post_install_message:
|
118
126
|
rdoc_options: []
|
119
127
|
require_paths:
|
120
128
|
- lib
|
121
129
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
130
|
requirements:
|
124
|
-
- -
|
131
|
+
- - ">="
|
125
132
|
- !ruby/object:Gem::Version
|
126
133
|
version: '0'
|
127
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
-
none: false
|
129
135
|
requirements:
|
130
|
-
- -
|
136
|
+
- - ">="
|
131
137
|
- !ruby/object:Gem::Version
|
132
138
|
version: '0'
|
133
139
|
requirements: []
|
134
140
|
rubyforge_project:
|
135
|
-
rubygems_version:
|
141
|
+
rubygems_version: 2.2.2
|
136
142
|
signing_key:
|
137
|
-
specification_version:
|
143
|
+
specification_version: 4
|
138
144
|
summary: online schema changer for mysql
|
139
|
-
test_files:
|
145
|
+
test_files:
|
146
|
+
- spec/README.md
|
147
|
+
- spec/fixtures/destination.ddl
|
148
|
+
- spec/fixtures/lines.ddl
|
149
|
+
- spec/fixtures/origin.ddl
|
150
|
+
- spec/fixtures/permissions.ddl
|
151
|
+
- spec/fixtures/small_table.ddl
|
152
|
+
- spec/fixtures/tracks.ddl
|
153
|
+
- spec/fixtures/users.ddl
|
154
|
+
- spec/integration/atomic_switcher_spec.rb
|
155
|
+
- spec/integration/chunker_spec.rb
|
156
|
+
- spec/integration/cleanup_spec.rb
|
157
|
+
- spec/integration/entangler_spec.rb
|
158
|
+
- spec/integration/integration_helper.rb
|
159
|
+
- spec/integration/lhm_spec.rb
|
160
|
+
- spec/integration/locked_switcher_spec.rb
|
161
|
+
- spec/integration/table_spec.rb
|
162
|
+
- spec/test_helper.rb
|
163
|
+
- spec/unit/active_record_connection_spec.rb
|
164
|
+
- spec/unit/atomic_switcher_spec.rb
|
165
|
+
- spec/unit/chunker_spec.rb
|
166
|
+
- spec/unit/connection_spec.rb
|
167
|
+
- spec/unit/datamapper_connection_spec.rb
|
168
|
+
- spec/unit/entangler_spec.rb
|
169
|
+
- spec/unit/intersection_spec.rb
|
170
|
+
- spec/unit/lhm_spec.rb
|
171
|
+
- spec/unit/locked_switcher_spec.rb
|
172
|
+
- spec/unit/migration_spec.rb
|
173
|
+
- spec/unit/migrator_spec.rb
|
174
|
+
- spec/unit/printer_spec.rb
|
175
|
+
- spec/unit/sql_helper_spec.rb
|
176
|
+
- spec/unit/table_spec.rb
|
177
|
+
- spec/unit/throttler_spec.rb
|
178
|
+
- spec/unit/unit_helper.rb
|
data/spec/bootstrap.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
|
2
|
-
# Schmidt
|
3
|
-
|
4
|
-
require 'minitest/spec'
|
5
|
-
require 'minitest/autorun'
|
6
|
-
require 'minitest/mock'
|
7
|
-
require "pathname"
|
8
|
-
|
9
|
-
$project = Pathname.new(File.dirname(__FILE__) + '/..').cleanpath
|
10
|
-
$spec = $project.join("spec")
|
11
|
-
$fixtures = $spec.join("fixtures")
|
12
|
-
|
13
|
-
$: << $project.join("lib").to_s
|