migration_timeouts 0.0.1
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/.editorconfig +22 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/README.md +98 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/migration_timeouts.rb +11 -0
- data/lib/migration_timeouts/config.rb +17 -0
- data/lib/migration_timeouts/migration_extensions.rb +33 -0
- data/lib/migration_timeouts/timeout_manager.rb +42 -0
- data/lib/migration_timeouts/version.rb +5 -0
- data/migration_timeouts.gemspec +29 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1b3919c73d8291c27d7a9e0c3709a332a8d9dde02d9839ec0f6ab46f21c85937
|
4
|
+
data.tar.gz: 01513e814fce20aa0c7ffc324fe069d94c911453dda646189dfd69ff89d77699
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4ba69c9eb637358b3b2c834e1650c3fc418f58a27c1ba804b3855c88288f6dd2f17c93148a12d760788cee203a7b25998552f0edc7e0c5f4e15cda173b9ec23d
|
7
|
+
data.tar.gz: 29e05d1f60b15de0d66251b70299e1e175a92bde915598ab33f4997b50355c127be346a4772ff7830dafe570f8522b83c4a8980e1f8d38332d10bb12e4b84523
|
data/.editorconfig
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# EditorConfig is awesome: http://EditorConfig.org
|
2
|
+
|
3
|
+
# top-most EditorConfig file
|
4
|
+
root = true
|
5
|
+
|
6
|
+
# Base rule, applies to everything
|
7
|
+
[*]
|
8
|
+
charset = utf-8
|
9
|
+
end_of_line = lf
|
10
|
+
insert_final_newline = true
|
11
|
+
indent_style = space
|
12
|
+
indent_size = 2
|
13
|
+
trim_trailing_whitespace = true
|
14
|
+
|
15
|
+
# some languages make syntactical use of trailing whitespace,
|
16
|
+
# so it should not be stripped
|
17
|
+
[*.md]
|
18
|
+
trim_trailing_whitespace = false
|
19
|
+
|
20
|
+
# Custom rules for specific file types:
|
21
|
+
# [*.ext]
|
22
|
+
# write some custom rules
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [1.2.0]
|
8
|
+
### Added
|
9
|
+
- Support for using with the [strong_migrations](https://github.com/ankane/strong_migrations) gem
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at opensource@procore.com All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Migration Timeouts
|
2
|
+
|
3
|
+
Migration Timeouts is a Ruby gem that adds timeouts, explicitly or implicitly, to ActiveRecord migrations.
|
4
|
+
|
5
|
+
A **lock_timeout** sets a timeout on how long PostgreSQL will wait to acquire a lock on tables being altered before failing and rolling back. This prevents lock contention, and long-running migrations.
|
6
|
+
|
7
|
+
A **statement_timeout** sets timeout on how long a single DB statement can run. If a badly constructed migration tries to lock a table for too long, this will fail the migration and trigger a rollback.
|
8
|
+
|
9
|
+
This gem provides config options for app-wide settings, and class methods for specifying or disabling timeouts for a single migration.
|
10
|
+
|
11
|
+
Migration Timeouts currently only supports [PostgreSQL](https://www.postgresql.org/)
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'migration_timeouts'
|
19
|
+
```
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Configure the default lock timeout in a Rails initializer
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
#config/initializers/migration_timeouts.rb
|
27
|
+
|
28
|
+
MigrationTimeouts.configure do |config|
|
29
|
+
config.default_lock_timeout = 3.seconds
|
30
|
+
config.default_statement_timeout = 5.seconds
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
And that's all! Now every `up` migration will execute
|
35
|
+
```psql
|
36
|
+
SET LOCAL statement_timeout = 5000;
|
37
|
+
SET LOCAL lock_timeout = 3000;
|
38
|
+
```
|
39
|
+
inside the migration transaction before your migration code runs. No lock
|
40
|
+
timeout will be used for the `down` migration.
|
41
|
+
|
42
|
+
## Disabling
|
43
|
+
|
44
|
+
If you set app-wide timeout settings, you can disable them for single migrations.
|
45
|
+
|
46
|
+
Here are the available helper methods:
|
47
|
+
```ruby
|
48
|
+
class AddFoo < ActiveRecord::Migration
|
49
|
+
|
50
|
+
disable_lock_timeout!
|
51
|
+
disable_statement_timeout!
|
52
|
+
disable_timeouts!
|
53
|
+
|
54
|
+
def change
|
55
|
+
create_table :foo do |t|
|
56
|
+
t.timestamps
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
## Custom lock timeout
|
63
|
+
|
64
|
+
You can change the duration of the timeouts by using:
|
65
|
+
```ruby
|
66
|
+
class AddBar < ActiveRecord::Migration
|
67
|
+
|
68
|
+
lock_timeout 10.seconds
|
69
|
+
statement_timeout 15.seconds
|
70
|
+
|
71
|
+
def change
|
72
|
+
create_table :bar do |t|
|
73
|
+
t.timestamps
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
Additionally, if you have not set app-wide timeouts, you can use this to
|
79
|
+
set a timeout for a particular migration.
|
80
|
+
|
81
|
+
## disable_ddl_transaction!
|
82
|
+
|
83
|
+
If you use `disable_ddl_transaction!`, no timeouts will occur
|
84
|
+
```ruby
|
85
|
+
class AddMonkey < ActiveRecord::Migration
|
86
|
+
|
87
|
+
disable_ddl_transaction!
|
88
|
+
|
89
|
+
def change
|
90
|
+
create_table :monkey do |t|
|
91
|
+
t.timestamps
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
## Thanks and alternatives
|
98
|
+
Originally forked from https://github.com/procore/migration-lock-timeout :heart:
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "migration_timeouts"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
module MigrationTimeouts
|
6
|
+
end
|
7
|
+
|
8
|
+
Dir[File.join(File.dirname(__FILE__), "migration_timeouts", "*.rb")].each { |file| require file }
|
9
|
+
|
10
|
+
::ActiveRecord::Migration.prepend(MigrationTimeouts::TimeoutManager)
|
11
|
+
::ActiveRecord::Migration.extend(MigrationTimeouts::MigrationExtensions)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MigrationTimeouts
|
4
|
+
class << self
|
5
|
+
def configure
|
6
|
+
yield config
|
7
|
+
end
|
8
|
+
|
9
|
+
def config
|
10
|
+
@config ||= Configurator.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Configurator
|
15
|
+
attr_accessor :default_lock_timeout, :default_statement_timeout
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MigrationTimeouts
|
4
|
+
module MigrationExtensions
|
5
|
+
attr_accessor(
|
6
|
+
:lock_timeout_disabled,
|
7
|
+
:statement_timeout_disabled,
|
8
|
+
:lock_timeout_override,
|
9
|
+
:statement_timeout_override,
|
10
|
+
)
|
11
|
+
|
12
|
+
def disable_lock_timeout!
|
13
|
+
self.lock_timeout_disabled = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def disable_statement_timeout!
|
17
|
+
self.statement_timeout_disabled = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def disable_timeouts!
|
21
|
+
self.lock_timeout_disabled = true
|
22
|
+
self.statement_timeout_disabled = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def lock_timeout(seconds)
|
26
|
+
self.lock_timeout_override = seconds
|
27
|
+
end
|
28
|
+
|
29
|
+
def statement_timeout(seconds)
|
30
|
+
self.statement_timeout_override = seconds
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/numeric"
|
4
|
+
|
5
|
+
module MigrationTimeouts
|
6
|
+
module TimeoutManager
|
7
|
+
def migrate(direction)
|
8
|
+
return super unless direction == :up && !disable_ddl_transaction
|
9
|
+
|
10
|
+
issue_lock_timeout if lock_timeout_configured?
|
11
|
+
issue_statement_timeout if statement_timeout_configured?
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def issue_lock_timeout
|
19
|
+
execute "SET LOCAL lock_timeout = #{lock_timeout.in_milliseconds}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def issue_statement_timeout
|
23
|
+
execute "SET LOCAL statement_timeout = #{statement_timeout.in_milliseconds}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def lock_timeout_configured?
|
27
|
+
!self.class.lock_timeout_disabled && lock_timeout&.try(:positive?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def statement_timeout_configured?
|
31
|
+
!self.class.statement_timeout_disabled && statement_timeout&.try(:positive?)
|
32
|
+
end
|
33
|
+
|
34
|
+
def lock_timeout
|
35
|
+
self.class.lock_timeout_override || MigrationTimeouts.config.default_lock_timeout
|
36
|
+
end
|
37
|
+
|
38
|
+
def statement_timeout
|
39
|
+
self.class.statement_timeout_override || MigrationTimeouts.config.default_statement_timeout
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "migration_timeouts/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "migration_timeouts"
|
9
|
+
spec.version = MigrationTimeouts::VERSION
|
10
|
+
spec.authors = [ "Jordan Minneti" ]
|
11
|
+
spec.email = [ "jordan.minneti@freshly.com" ]
|
12
|
+
|
13
|
+
spec.summary = "Ruby gem that adds configurable statement and lock timeouts to Active Record migrations"
|
14
|
+
spec.description = "Ruby gem that automatically adds configurable statement and lock timeouts to all Active Record migrations"
|
15
|
+
spec.homepage = "http://github.com/Freshly/migration_timeouts"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = [ "lib" ]
|
22
|
+
|
23
|
+
spec.add_development_dependency "pg", "< 1.0"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "rake", "~> 11.2.2"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
|
28
|
+
spec.add_runtime_dependency "activerecord", ">= 4.0", "< 7.0"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: migration_timeouts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jordan Minneti
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pg
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "<"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "<"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 11.2.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 11.2.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activerecord
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.0'
|
76
|
+
- - "<"
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '7.0'
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '4.0'
|
86
|
+
- - "<"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '7.0'
|
89
|
+
description: Ruby gem that automatically adds configurable statement and lock timeouts
|
90
|
+
to all Active Record migrations
|
91
|
+
email:
|
92
|
+
- jordan.minneti@freshly.com
|
93
|
+
executables: []
|
94
|
+
extensions: []
|
95
|
+
extra_rdoc_files: []
|
96
|
+
files:
|
97
|
+
- ".editorconfig"
|
98
|
+
- ".gitignore"
|
99
|
+
- ".rspec"
|
100
|
+
- ".rubocop.yml"
|
101
|
+
- ".travis.yml"
|
102
|
+
- CHANGELOG.md
|
103
|
+
- CODE_OF_CONDUCT.md
|
104
|
+
- Gemfile
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- bin/console
|
108
|
+
- bin/setup
|
109
|
+
- lib/migration_timeouts.rb
|
110
|
+
- lib/migration_timeouts/config.rb
|
111
|
+
- lib/migration_timeouts/migration_extensions.rb
|
112
|
+
- lib/migration_timeouts/timeout_manager.rb
|
113
|
+
- lib/migration_timeouts/version.rb
|
114
|
+
- migration_timeouts.gemspec
|
115
|
+
homepage: http://github.com/Freshly/migration_timeouts
|
116
|
+
licenses:
|
117
|
+
- MIT
|
118
|
+
metadata: {}
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
require_paths:
|
122
|
+
- lib
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
requirements: []
|
134
|
+
rubygems_version: 3.0.6
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Ruby gem that adds configurable statement and lock timeouts to Active Record
|
138
|
+
migrations
|
139
|
+
test_files: []
|