lhm 1.2.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +256 -0
  4. data/.travis.yml +5 -1
  5. data/CHANGELOG.md +26 -0
  6. data/README.md +87 -8
  7. data/Rakefile +6 -4
  8. data/bin/lhm-config.sh +7 -0
  9. data/bin/lhm-kill-queue +13 -15
  10. data/bin/lhm-spec-clobber.sh +5 -4
  11. data/bin/lhm-spec-grants.sh +2 -2
  12. data/bin/lhm-spec-setup-cluster.sh +2 -3
  13. data/gemfiles/ar-2.3_mysql.gemfile +2 -1
  14. data/gemfiles/ar-3.2_mysql.gemfile +1 -1
  15. data/gemfiles/ar-3.2_mysql2.gemfile +1 -1
  16. data/gemfiles/dm_mysql.gemfile +1 -1
  17. data/lhm.gemspec +7 -8
  18. data/lib/lhm/atomic_switcher.rb +2 -1
  19. data/lib/lhm/chunker.rb +51 -39
  20. data/lib/lhm/command.rb +4 -2
  21. data/lib/lhm/connection.rb +14 -2
  22. data/lib/lhm/entangler.rb +5 -5
  23. data/lib/lhm/intersection.rb +29 -16
  24. data/lib/lhm/invoker.rb +31 -10
  25. data/lib/lhm/locked_switcher.rb +6 -6
  26. data/lib/lhm/migration.rb +7 -5
  27. data/lib/lhm/migrator.rb +57 -9
  28. data/lib/lhm/printer.rb +54 -0
  29. data/lib/lhm/sql_helper.rb +4 -4
  30. data/lib/lhm/table.rb +12 -12
  31. data/lib/lhm/throttler/time.rb +29 -0
  32. data/lib/lhm/throttler.rb +32 -0
  33. data/lib/lhm/version.rb +1 -1
  34. data/lib/lhm.rb +71 -6
  35. data/spec/.lhm.example +1 -1
  36. data/spec/README.md +20 -13
  37. data/spec/fixtures/lines.ddl +7 -0
  38. data/spec/fixtures/permissions.ddl +5 -0
  39. data/spec/fixtures/tracks.ddl +5 -0
  40. data/spec/fixtures/users.ddl +4 -2
  41. data/spec/integration/atomic_switcher_spec.rb +7 -7
  42. data/spec/integration/chunker_spec.rb +11 -5
  43. data/spec/integration/cleanup_spec.rb +72 -0
  44. data/spec/integration/entangler_spec.rb +11 -11
  45. data/spec/integration/integration_helper.rb +49 -17
  46. data/spec/integration/lhm_spec.rb +157 -37
  47. data/spec/integration/locked_switcher_spec.rb +7 -7
  48. data/spec/integration/table_spec.rb +15 -17
  49. data/spec/test_helper.rb +28 -0
  50. data/spec/unit/atomic_switcher_spec.rb +6 -6
  51. data/spec/unit/chunker_spec.rb +95 -73
  52. data/spec/unit/datamapper_connection_spec.rb +1 -0
  53. data/spec/unit/entangler_spec.rb +19 -19
  54. data/spec/unit/intersection_spec.rb +27 -15
  55. data/spec/unit/lhm_spec.rb +29 -0
  56. data/spec/unit/locked_switcher_spec.rb +14 -14
  57. data/spec/unit/migration_spec.rb +10 -5
  58. data/spec/unit/migrator_spec.rb +53 -41
  59. data/spec/unit/printer_spec.rb +79 -0
  60. data/spec/unit/sql_helper_spec.rb +10 -10
  61. data/spec/unit/table_spec.rb +11 -11
  62. data/spec/unit/throttler_spec.rb +73 -0
  63. data/spec/unit/unit_helper.rb +1 -13
  64. metadata +63 -24
  65. 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 "should name index with a single column" do
9
+ it 'should name index with a single column' do
10
10
  Lhm::SqlHelper.
11
11
  idx_name(:users, :name).
12
- must_equal("index_users_on_name")
12
+ must_equal('index_users_on_name')
13
13
  end
14
14
 
15
- it "should name index with multiple columns" do
15
+ it 'should name index with multiple columns' do
16
16
  Lhm::SqlHelper.
17
17
  idx_name(:users, [:name, :firstname]).
18
- must_equal("index_users_on_name_and_firstname")
18
+ must_equal('index_users_on_name_and_firstname')
19
19
  end
20
20
 
21
- it "should name index with prefixed column" do
21
+ it 'should name index with prefixed column' do
22
22
  Lhm::SqlHelper.
23
- idx_name(:tracks, ["title(10)", "album"]).
24
- must_equal("index_tracks_on_title_and_album")
23
+ idx_name(:tracks, ['title(10)', 'album']).
24
+ must_equal('index_tracks_on_title_and_album')
25
25
  end
26
26
 
27
- it "should quote column names in index specification" do
27
+ it 'should quote column names in index specification' do
28
28
  Lhm::SqlHelper.
29
- idx_spec(["title(10)", "album"]).
30
- must_equal("`title`(10), `album`")
29
+ idx_spec(['title(10)', 'album']).
30
+ must_equal('`title`(10), `album`')
31
31
  end
32
32
  end
@@ -8,26 +8,26 @@ require 'lhm/table'
8
8
  describe Lhm::Table do
9
9
  include UnitHelper
10
10
 
11
- describe "names" do
12
- it "should name destination" do
13
- @table = Lhm::Table.new("users")
14
- @table.destination_name.must_equal "lhmn_users"
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 "constraints" do
19
- it "should be satisfied with a single column primary key called id" do
20
- @table = Lhm::Table.new("table", "id")
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 "should not be satisfied with a primary key unless called id" do
25
- @table = Lhm::Table.new("table", "uuid")
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 "should not be satisfied with multicolumn primary key" do
30
- @table = Lhm::Table.new("table", ["id", "secondary"])
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
@@ -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: 1.2.0
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: 2013-02-22 00:00:00.000000000 Z
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: 2.10.0
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: 2.10.0
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
- - .travis.yml
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/large-hadron-migrator
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: 1.8.24
141
+ rubygems_version: 2.2.2
136
142
  signing_key:
137
- specification_version: 3
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