strong_migrations 0.6.5 → 0.6.6

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 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