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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +9 -5
- data/lib/generators/strong_migrations/install_generator.rb +17 -0
- data/lib/generators/strong_migrations/templates/initializer.rb.tt +17 -0
- data/lib/strong_migrations.rb +13 -0
- data/lib/strong_migrations/checker.rb +44 -1
- data/lib/strong_migrations/version.rb +1 -1
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 140b74a0133d3db034a54fc178e4f95e53fbdec0c569dc2ade222efc96b83a6b
         | 
| 4 | 
            +
              data.tar.gz: f4aadca5f15f85849b975630bdb937e3eef00498c0e806f6ca7cd8112d859fd4
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2f79d4dbd4342e45af9799f4d303c8ad8af68e8aa24fc5e86667547ec2a4c8ce95e123a6b3f0eb1851573d7a1bebd89a6795f4afffd4a319a0a9f0d73293f3ee
         | 
| 7 | 
            +
              data.tar.gz: a784f11afffd45d827d7135d1f8fb822979ba851f6d8b54e09025ff9144f32f5091dce8e080901bac51237be74894571c6d007eddf373e3007de4886f5391b54
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        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 | 
            -
             | 
| 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  | 
| 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  | 
| 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
         | 
    
        data/lib/strong_migrations.rb
    CHANGED
    
    | @@ -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 &&  | 
| 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
         | 
    
        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. | 
| 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- | 
| 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
         |