strong_migrations 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bad0ba9c075a7c3eae98fc8835b9e56863b3573a381371d3b1affde769da0ad6
4
- data.tar.gz: 7d67dbdaf674414b43781dd45b60f1f0d11a6d811ffe9ce8235ffed2889d8383
3
+ metadata.gz: 140b74a0133d3db034a54fc178e4f95e53fbdec0c569dc2ade222efc96b83a6b
4
+ data.tar.gz: f4aadca5f15f85849b975630bdb937e3eef00498c0e806f6ca7cd8112d859fd4
5
5
  SHA512:
6
- metadata.gz: dc889f4d62bba08ae0d628e629dc37d7ecd53300ae92691118ca3db0707a416e7f043bbde41f2a0311acb9bd0f0b973175413f17a7c8aed2e134a6f29fc59b61
7
- data.tar.gz: b08c078f6591b4458fadf64c9d1b8e04c3323c8dc9036e88e4e5a7ddc4f8a38bfa39d8e3e0cce2dcda7b9b9fce2d9676140d0cf89b2d668f6e5f2389e825b225
6
+ metadata.gz: 2f79d4dbd4342e45af9799f4d303c8ad8af68e8aa24fc5e86667547ec2a4c8ce95e123a6b3f0eb1851573d7a1bebd89a6795f4afffd4a319a0a9f0d73293f3ee
7
+ data.tar.gz: a784f11afffd45d827d7135d1f8fb822979ba851f6d8b54e09025ff9144f32f5091dce8e080901bac51237be74894571c6d007eddf373e3007de4886f5391b54
@@ -1,3 +1,8 @@
1
+ ## 0.6.6 (2020-05-08)
2
+
3
+ - Added warnings for missing and long lock timeouts
4
+ - Added install generator
5
+
1
6
  ## 0.6.5 (2020-05-06)
2
7
 
3
8
  - Fixed deprecation warnings with Ruby 2.7
data/README.md CHANGED
@@ -18,7 +18,11 @@ Add this line to your application’s Gemfile:
18
18
  gem 'strong_migrations'
19
19
  ```
20
20
 
21
- We highly recommend [setting timeouts](#timeouts). You can [mark existing migrations as safe](#existing-migrations) as well.
21
+ And run:
22
+
23
+ ```sh
24
+ rails generate strong_migrations:install
25
+ ```
22
26
 
23
27
  ## Checks
24
28
 
@@ -621,20 +625,20 @@ Check the [source code](https://github.com/ankane/strong_migrations/blob/master/
621
625
 
622
626
  ## Timeouts
623
627
 
624
- It’s a good idea to set a long statement timeout and a short lock timeout for migrations. This way, migrations can run for a while, and if a migration can’t acquire a lock in a timely manner, other statements won’t be stuck behind it.
628
+ It’s extremely important to set a short lock timeout for migrations. This way, if a migration can’t acquire a lock in a timely manner, other statements won’t be stuck behind it. We also recommend setting a long statement timeout so migrations can run for a while.
625
629
 
626
630
  Create `config/initializers/strong_migrations.rb` with:
627
631
 
628
632
  ```ruby
629
- StrongMigrations.statement_timeout = 1.hour
630
633
  StrongMigrations.lock_timeout = 10.seconds
634
+ StrongMigrations.statement_timeout = 1.hour
631
635
  ```
632
636
 
633
637
  Or set the timeouts directly on the database user that runs migrations. For Postgres, use:
634
638
 
635
639
  ```sql
636
- ALTER ROLE myuser SET statement_timeout = '1h';
637
640
  ALTER ROLE myuser SET lock_timeout = '10s';
641
+ ALTER ROLE myuser SET statement_timeout = '1h';
638
642
  ```
639
643
 
640
644
  Note: If you use PgBouncer in transaction mode, you must set timeouts on the database user.
@@ -651,7 +655,7 @@ Use the version from your latest migration.
651
655
 
652
656
  ## Target Version
653
657
 
654
- If your development database version is different from production, you can specify the production version so the right checks are run in development.
658
+ If your development database version is different from production, you can specify the production version so the right checks run in development.
655
659
 
656
660
  ```ruby
657
661
  StrongMigrations.target_postgresql_version = "10"
@@ -0,0 +1,17 @@
1
+ require "rails/generators"
2
+
3
+ module StrongMigrations
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.join(__dir__, "templates")
7
+
8
+ def create_initializer
9
+ template "initializer.rb", "config/initializers/strong_migrations.rb"
10
+ end
11
+
12
+ def start_after
13
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # Mark existing migrations as safe
2
+ StrongMigrations.start_after = <%= start_after %>
3
+
4
+ # Set timeouts
5
+ # If you use PgBouncer in transaction mode, delete these lines and set timeouts on the database user
6
+ StrongMigrations.lock_timeout = 10.seconds
7
+ StrongMigrations.statement_timeout = 1.hour
8
+
9
+ # Analyze tables automatically (to update planner statistics) after an index is added
10
+ StrongMigrations.auto_analyze = true
11
+
12
+ # Add custom checks
13
+ # StrongMigrations.add_check do |method, args|
14
+ # if method == :add_index && args[0].to_s == "users"
15
+ # stop! "No more indexes on the users table"
16
+ # end
17
+ # end
@@ -19,6 +19,7 @@ module StrongMigrations
19
19
  attr_accessor :auto_analyze, :start_after, :checks, :error_messages,
20
20
  :target_postgresql_version, :target_mysql_version, :target_mariadb_version,
21
21
  :enabled_checks, :lock_timeout, :statement_timeout, :helpers
22
+ attr_writer :lock_timeout_limit
22
23
  end
23
24
  self.auto_analyze = false
24
25
  self.start_after = 0
@@ -230,6 +231,18 @@ end",
230
231
  self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
231
232
  self.helpers = false
232
233
 
234
+ # private
235
+ def self.developer_env?
236
+ defined?(Rails) && (Rails.env.development? || Rails.env.test?)
237
+ end
238
+
239
+ def self.lock_timeout_limit
240
+ unless defined?(@lock_timeout_limit)
241
+ @lock_timeout_limit = developer_env? ? false : 10
242
+ end
243
+ @lock_timeout_limit
244
+ end
245
+
233
246
  def self.add_check(&block)
234
247
  checks << block
235
248
  end
@@ -7,6 +7,7 @@ module StrongMigrations
7
7
  @new_tables = []
8
8
  @safe = false
9
9
  @timeouts_set = false
10
+ @lock_timeout_checked = false
10
11
  end
11
12
 
12
13
  def safety_assured
@@ -21,6 +22,7 @@ module StrongMigrations
21
22
 
22
23
  def perform(method, *args)
23
24
  set_timeouts
25
+ check_lock_timeout
24
26
 
25
27
  unless safe?
26
28
  case method
@@ -259,6 +261,7 @@ Then add the foreign key in separate migrations."
259
261
  result
260
262
  end
261
263
 
264
+ # TODO allow string timeouts in 0.7.0
262
265
  def set_timeouts
263
266
  if !@timeouts_set
264
267
  if StrongMigrations.statement_timeout
@@ -350,7 +353,7 @@ Then add the foreign key in separate migrations."
350
353
 
351
354
  def target_version(target_version)
352
355
  version =
353
- if target_version && defined?(Rails) && (Rails.env.development? || Rails.env.test?)
356
+ if target_version && StrongMigrations.developer_env?
354
357
  target_version.to_s
355
358
  else
356
359
  yield
@@ -358,6 +361,46 @@ Then add the foreign key in separate migrations."
358
361
  Gem::Version.new(version)
359
362
  end
360
363
 
364
+ def check_lock_timeout
365
+ limit = StrongMigrations.lock_timeout_limit
366
+
367
+ if limit && !@lock_timeout_checked
368
+ if postgresql?
369
+ lock_timeout = connection.select_all("SHOW lock_timeout").first["lock_timeout"]
370
+ lock_timeout_sec = timeout_to_sec(lock_timeout)
371
+ if lock_timeout_sec == 0
372
+ warn "[strong_migrations] WARNING: No lock timeout set. This is dangerous."
373
+ elsif lock_timeout_sec > limit
374
+ warn "[strong_migrations] WARNING: Lock timeout is longer than #{limit} seconds: #{lock_timeout}. This is dangerous."
375
+ end
376
+ elsif mysql? || mariadb?
377
+ lock_timeout = connection.select_all("SHOW VARIABLES LIKE 'lock_wait_timeout'").first["Value"]
378
+ if lock_timeout.to_i > limit
379
+ warn "[strong_migrations] WARNING: Lock timeout is longer than #{limit} seconds: #{lock_timeout}. This is dangerous."
380
+ end
381
+ end
382
+ @lock_timeout_checked = true
383
+ end
384
+ end
385
+
386
+ def timeout_to_sec(timeout)
387
+ suffixes = {
388
+ "ms" => 1,
389
+ "s" => 1000,
390
+ "min" => 1000 * 60,
391
+ "h" => 1000 * 60 * 60,
392
+ "d" => 1000 * 60 * 60 * 24
393
+ }
394
+ timeout_ms = timeout.to_i
395
+ suffixes.each do |k, v|
396
+ if timeout.end_with?(k)
397
+ timeout_ms *= v
398
+ break
399
+ end
400
+ end
401
+ timeout_ms / 1000.0
402
+ end
403
+
361
404
  def helpers?
362
405
  StrongMigrations.helpers
363
406
  end
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "0.6.5"
2
+ VERSION = "0.6.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-05-06 00:00:00.000000000 Z
13
+ date: 2020-05-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -108,6 +108,8 @@ files:
108
108
  - CONTRIBUTING.md
109
109
  - LICENSE.txt
110
110
  - README.md
111
+ - lib/generators/strong_migrations/install_generator.rb
112
+ - lib/generators/strong_migrations/templates/initializer.rb.tt
111
113
  - lib/strong_migrations.rb
112
114
  - lib/strong_migrations/alphabetize_columns.rb
113
115
  - lib/strong_migrations/checker.rb