online_migrations 0.17.1 → 0.19.0
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 +11 -0
- data/docs/background_data_migrations.md +21 -0
- data/docs/background_schema_migrations.md +21 -0
- data/lib/online_migrations/background_migrations/migration.rb +44 -26
- data/lib/online_migrations/background_migrations/migration_job.rb +19 -10
- data/lib/online_migrations/background_migrations/migration_job_status_validator.rb +3 -3
- data/lib/online_migrations/background_migrations/migration_runner.rb +3 -2
- data/lib/online_migrations/background_migrations/migration_status_validator.rb +6 -4
- data/lib/online_migrations/background_schema_migrations/migration.rb +23 -3
- data/lib/online_migrations/background_schema_migrations/migration_runner.rb +12 -3
- data/lib/online_migrations/background_schema_migrations/migration_status_validator.rb +3 -3
- data/lib/online_migrations/background_schema_migrations/scheduler.rb +16 -2
- data/lib/online_migrations/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57661cb5e096da3eaed31d4dbe5cda862f9f75271b59c28045412642acaf786b
|
4
|
+
data.tar.gz: 50ed46eaa89a4ee95ecd8b249b0fce616047006c91339dbc1069e572a96f0454
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be91a43493896dbf0787cf9045c0ac187920a55946b98b0c653b8a50604031aee1bba3b59591fd4c22f7996af05254c71001e098289ded180eec9cdd8ae47d43
|
7
|
+
data.tar.gz: 840c35a008b4b949d1d686222d0722f98aa579fb31ccb14ffe3f6bd80147100bbcb323a9bdba657f230efbd3b2a97f799385e21f43218d8dbf19ab9a484d1147
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## master (unreleased)
|
2
2
|
|
3
|
+
## 0.19.0 (2024-05-21)
|
4
|
+
|
5
|
+
- Add ability to cancel background migrations
|
6
|
+
|
7
|
+
## 0.18.0 (2024-05-07)
|
8
|
+
|
9
|
+
- Fix setting `started_at`/`finished_at` for parents of sharded background schema migrations
|
10
|
+
- Improve retrying of failed sharded background migrations
|
11
|
+
- Fix a bug when retried background data migration can not start
|
12
|
+
- Do not run multiple background schema migrations on the same table at the same time
|
13
|
+
|
3
14
|
## 0.17.1 (2024-04-28)
|
4
15
|
|
5
16
|
- Fix raising in development when using sharding and background index creation/removal was not enqueued
|
@@ -237,6 +237,7 @@ Background Migrations can be in various states during its execution:
|
|
237
237
|
Note: In normal circumstances, this should not be used since background migrations should be run and finished by the scheduler.
|
238
238
|
* **failed**: A migration raises an exception when running.
|
239
239
|
* **succeeded**: A migration finished without error.
|
240
|
+
* **cancelled**: A migration was cancelled by the user.
|
240
241
|
|
241
242
|
To get the progress (assuming `#count` method on background migration class was defined):
|
242
243
|
|
@@ -247,6 +248,26 @@ migration.progress # value from 0 to 100.0
|
|
247
248
|
|
248
249
|
**Note**: It will be easier to work with background migrations through some kind of Web UI, but until it is implemented, we can work with them only manually.
|
249
250
|
|
251
|
+
## Retrying a failed migration
|
252
|
+
|
253
|
+
To retry a failed migration, run:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
migration = OnlineMigrations::BackgroundMigrations::Migration.find(id)
|
257
|
+
migration.retry # => `true` if scheduled to be retried, `false` - if not
|
258
|
+
```
|
259
|
+
|
260
|
+
The migration will be retried on the next Scheduler run.
|
261
|
+
|
262
|
+
## Cancelling a migration
|
263
|
+
|
264
|
+
To cancel an existing migration from future performing, run:
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
migration = OnlineMigrations::BackgroundMigrations::Migration.find(id)
|
268
|
+
migration.cancel
|
269
|
+
```
|
270
|
+
|
250
271
|
## Configuring
|
251
272
|
|
252
273
|
There are a few configurable options for the Background Migrations. Custom configurations should be placed in a `online_migrations.rb` initializer.
|
@@ -66,6 +66,26 @@ end
|
|
66
66
|
|
67
67
|
You shouldn't depend on the schema until the background schema migration is finished. If having the schema migrated is a requirement, then the `ensure_background_schema_migration_succeeded` helper can be used to guarantee that the migration succeeded and the schema change applied.
|
68
68
|
|
69
|
+
## Retrying a failed migration
|
70
|
+
|
71
|
+
To retry a failed migration, run:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
migration = OnlineMigrations::BackgroundSchemaMigrations::Migration.find(id)
|
75
|
+
migration.retry # => `true` if scheduled to be retried, `false` - if not
|
76
|
+
```
|
77
|
+
|
78
|
+
The migration will be retried on the next Scheduler run.
|
79
|
+
|
80
|
+
## Cancelling a migration
|
81
|
+
|
82
|
+
To cancel an existing migration from future performing, run:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
migration = OnlineMigrations::BackgroundSchemaMigrations::Migration.find(id)
|
86
|
+
migration.cancel
|
87
|
+
```
|
88
|
+
|
69
89
|
## Instrumentation
|
70
90
|
|
71
91
|
Background schema migrations use the [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) API.
|
@@ -110,6 +130,7 @@ Background Schema Migrations can be in various states during its execution:
|
|
110
130
|
* **running**: A migration is being performed by a migration executor.
|
111
131
|
* **failed**: A migration raises an exception when running.
|
112
132
|
* **succeeded**: A migration finished without error.
|
133
|
+
* **cancelled**: A migration was cancelled by the user.
|
113
134
|
|
114
135
|
## Configuring
|
115
136
|
|
@@ -15,6 +15,7 @@ module OnlineMigrations
|
|
15
15
|
:finishing, # The migration is being manually finishing inline by the user.
|
16
16
|
:failed, # The migration raises an exception when running.
|
17
17
|
:succeeded, # The migration finished without error.
|
18
|
+
:cancelled, # The migration was cancelled by the user.
|
18
19
|
]
|
19
20
|
|
20
21
|
self.table_name = :background_migrations
|
@@ -38,9 +39,9 @@ module OnlineMigrations
|
|
38
39
|
enum status: STATUSES.index_with(&:to_s)
|
39
40
|
end
|
40
41
|
|
41
|
-
belongs_to :parent, class_name: name, optional: true
|
42
|
-
has_many :children, class_name: name, foreign_key: :parent_id, dependent: :delete_all
|
43
|
-
has_many :migration_jobs, dependent: :delete_all
|
42
|
+
belongs_to :parent, class_name: name, optional: true, inverse_of: :children
|
43
|
+
has_many :children, class_name: name, foreign_key: :parent_id, dependent: :delete_all, inverse_of: :parent
|
44
|
+
has_many :migration_jobs, dependent: :delete_all, inverse_of: :migration
|
44
45
|
|
45
46
|
validates :migration_name, :batch_column_name, presence: true
|
46
47
|
|
@@ -98,12 +99,19 @@ module OnlineMigrations
|
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
101
|
-
|
102
|
-
|
102
|
+
# Overwrite enum's generated method to correctly work for composite migrations.
|
103
|
+
def cancelled!
|
104
|
+
return super if !composite?
|
105
|
+
|
106
|
+
transaction do
|
107
|
+
super
|
108
|
+
children.each { |child| child.cancelled! if !child.succeeded? }
|
109
|
+
end
|
103
110
|
end
|
111
|
+
alias cancel cancelled!
|
104
112
|
|
105
|
-
def
|
106
|
-
migration_jobs.
|
113
|
+
def last_job
|
114
|
+
migration_jobs.order(:max_value).last
|
107
115
|
end
|
108
116
|
|
109
117
|
# Returns the progress of the background migration.
|
@@ -115,10 +123,13 @@ module OnlineMigrations
|
|
115
123
|
def progress
|
116
124
|
if succeeded?
|
117
125
|
100.0
|
126
|
+
elsif enqueued?
|
127
|
+
0.0
|
118
128
|
elsif composite?
|
119
129
|
rows_counts = children.to_a.pluck(:rows_count)
|
120
130
|
if rows_counts.none?(nil)
|
121
131
|
total_rows_count = rows_counts.sum
|
132
|
+
return 100.0 if total_rows_count == 0
|
122
133
|
|
123
134
|
progresses = children.map do |child|
|
124
135
|
child.progress * child.rows_count / total_rows_count # weighted progress
|
@@ -126,11 +137,15 @@ module OnlineMigrations
|
|
126
137
|
|
127
138
|
progresses.sum.round(2)
|
128
139
|
end
|
129
|
-
elsif rows_count
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
140
|
+
elsif rows_count
|
141
|
+
if rows_count > 0
|
142
|
+
jobs_rows_count = migration_jobs.succeeded.sum(:batch_size)
|
143
|
+
# The last migration job may need to process the amount of rows
|
144
|
+
# less than the batch size, so we can get a value > 1.0.
|
145
|
+
([jobs_rows_count.to_f / rows_count, 1.0].min * 100).round(2)
|
146
|
+
else
|
147
|
+
0.0
|
148
|
+
end
|
134
149
|
end
|
135
150
|
end
|
136
151
|
|
@@ -154,31 +169,34 @@ module OnlineMigrations
|
|
154
169
|
# @return [Boolean]
|
155
170
|
#
|
156
171
|
def interval_elapsed?
|
157
|
-
|
172
|
+
last_job = migration_jobs.order(:updated_at).last
|
173
|
+
return true if last_job.nil?
|
158
174
|
|
159
|
-
|
160
|
-
false
|
161
|
-
elsif batch_pause > 0 && (job = last_completed_job)
|
162
|
-
job.finished_at + batch_pause <= Time.current
|
163
|
-
else
|
164
|
-
true
|
165
|
-
end
|
175
|
+
last_job.enqueued? || (last_job.updated_at + batch_pause <= Time.current)
|
166
176
|
end
|
167
177
|
|
168
|
-
#
|
178
|
+
# Mark this migration as ready to be processed again.
|
169
179
|
#
|
170
180
|
# This method marks failed jobs as ready to be processed again, and
|
171
181
|
# they will be picked up on the next Scheduler run.
|
172
182
|
#
|
173
|
-
def
|
174
|
-
|
175
|
-
|
176
|
-
|
183
|
+
def retry
|
184
|
+
if composite? && failed?
|
185
|
+
children.failed.each(&:retry)
|
186
|
+
running!
|
187
|
+
true
|
188
|
+
elsif failed?
|
189
|
+
iterator = BatchIterator.new(migration_jobs.failed)
|
190
|
+
iterator.each_batch(of: 100) do |batch|
|
177
191
|
batch.each(&:retry)
|
178
|
-
enqueued!
|
179
192
|
end
|
193
|
+
running!
|
194
|
+
true
|
195
|
+
else
|
196
|
+
false
|
180
197
|
end
|
181
198
|
end
|
199
|
+
alias retry_failed_jobs retry
|
182
200
|
|
183
201
|
# Returns the time this migration started running.
|
184
202
|
def started_at
|
@@ -8,6 +8,7 @@ module OnlineMigrations
|
|
8
8
|
:running,
|
9
9
|
:failed,
|
10
10
|
:succeeded,
|
11
|
+
:cancelled,
|
11
12
|
]
|
12
13
|
|
13
14
|
self.table_name = :background_migration_jobs
|
@@ -47,7 +48,7 @@ module OnlineMigrations
|
|
47
48
|
delegate :migration_name, :migration_class, :migration_object, :migration_relation, :batch_column_name,
|
48
49
|
:arguments, :batch_pause, to: :migration
|
49
50
|
|
50
|
-
belongs_to :migration
|
51
|
+
belongs_to :migration, inverse_of: :migration_jobs
|
51
52
|
|
52
53
|
validates :min_value, :max_value, presence: true, numericality: { greater_than: 0 }
|
53
54
|
validate :values_in_migration_range, if: :min_value?
|
@@ -69,15 +70,23 @@ module OnlineMigrations
|
|
69
70
|
# This is used when retrying failed jobs.
|
70
71
|
#
|
71
72
|
def retry
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
if failed?
|
74
|
+
transaction do
|
75
|
+
update!(
|
76
|
+
status: self.class.statuses[:enqueued],
|
77
|
+
attempts: 0,
|
78
|
+
started_at: nil,
|
79
|
+
finished_at: nil,
|
80
|
+
error_class: nil,
|
81
|
+
error_message: nil,
|
82
|
+
backtrace: nil
|
83
|
+
)
|
84
|
+
migration.running! if migration.failed?
|
85
|
+
end
|
86
|
+
true
|
87
|
+
else
|
88
|
+
false
|
89
|
+
end
|
81
90
|
end
|
82
91
|
|
83
92
|
private
|
@@ -5,9 +5,9 @@ module OnlineMigrations
|
|
5
5
|
# @private
|
6
6
|
class MigrationJobStatusValidator < ActiveModel::Validator
|
7
7
|
VALID_STATUS_TRANSITIONS = {
|
8
|
-
"enqueued" => ["running"],
|
9
|
-
"running" => ["succeeded", "failed"],
|
10
|
-
"failed" => ["enqueued", "running"],
|
8
|
+
"enqueued" => ["running", "cancelled"],
|
9
|
+
"running" => ["succeeded", "failed", "cancelled"],
|
10
|
+
"failed" => ["enqueued", "running", "cancelled"],
|
11
11
|
}
|
12
12
|
|
13
13
|
def validate(record)
|
@@ -13,6 +13,7 @@ module OnlineMigrations
|
|
13
13
|
# Runs one background migration job.
|
14
14
|
def run_migration_job
|
15
15
|
raise "Should not be called on a composite (with sharding) migration" if migration.composite?
|
16
|
+
return if migration.cancelled?
|
16
17
|
|
17
18
|
mark_as_running if migration.enqueued?
|
18
19
|
migration_payload = notifications_payload(migration)
|
@@ -56,7 +57,7 @@ module OnlineMigrations
|
|
56
57
|
raise "This method is not intended for use in production environments"
|
57
58
|
end
|
58
59
|
|
59
|
-
return if migration.completed?
|
60
|
+
return if migration.completed? || migration.cancelled?
|
60
61
|
|
61
62
|
mark_as_running
|
62
63
|
|
@@ -77,7 +78,7 @@ module OnlineMigrations
|
|
77
78
|
# Keep running until the migration is finished.
|
78
79
|
#
|
79
80
|
def finish
|
80
|
-
return if migration.completed?
|
81
|
+
return if migration.completed? || migration.cancelled?
|
81
82
|
|
82
83
|
if migration.composite?
|
83
84
|
migration.children.each do |child_migration|
|
@@ -7,7 +7,7 @@ module OnlineMigrations
|
|
7
7
|
VALID_STATUS_TRANSITIONS = {
|
8
8
|
# enqueued -> running occurs when the migration starts performing.
|
9
9
|
# enqueued -> paused occurs when the migration is paused before starting.
|
10
|
-
"enqueued" => ["running", "paused"],
|
10
|
+
"enqueued" => ["running", "paused", "cancelled"],
|
11
11
|
# running -> paused occurs when a user pauses the migration as
|
12
12
|
# it's performing.
|
13
13
|
# running -> finishing occurs when a user manually finishes the migration.
|
@@ -18,14 +18,16 @@ module OnlineMigrations
|
|
18
18
|
"finishing",
|
19
19
|
"succeeded",
|
20
20
|
"failed",
|
21
|
+
"cancelled",
|
21
22
|
],
|
22
23
|
# finishing -> succeeded occurs when the migration completes successfully.
|
23
24
|
# finishing -> failed occurs when the migration raises an exception when running.
|
24
|
-
"finishing" => ["succeeded", "failed"],
|
25
|
+
"finishing" => ["succeeded", "failed", "cancelled"],
|
25
26
|
# paused -> running occurs when the migration is resumed after being paused.
|
26
|
-
"paused" => ["running"],
|
27
|
+
"paused" => ["running", "cancelled"],
|
27
28
|
# failed -> enqueued occurs when the failed migration jobs are retried after being failed.
|
28
|
-
|
29
|
+
# failed -> running occurs when the failed migration is retried.
|
30
|
+
"failed" => ["enqueued", "running", "cancelled"],
|
29
31
|
}
|
30
32
|
|
31
33
|
def validate(record)
|
@@ -13,6 +13,7 @@ module OnlineMigrations
|
|
13
13
|
:running, # The migration is being performed by a migration executor.
|
14
14
|
:failed, # The migration raises an exception when running.
|
15
15
|
:succeeded, # The migration finished without error.
|
16
|
+
:cancelled, # The migration was cancelled by the user.
|
16
17
|
]
|
17
18
|
|
18
19
|
MAX_IDENTIFIER_LENGTH = 63
|
@@ -55,8 +56,8 @@ module OnlineMigrations
|
|
55
56
|
enum status: STATUSES.index_with(&:to_s)
|
56
57
|
end
|
57
58
|
|
58
|
-
belongs_to :parent, class_name: name, optional: true
|
59
|
-
has_many :children, class_name: name, foreign_key: :parent_id
|
59
|
+
belongs_to :parent, class_name: name, optional: true, inverse_of: :children
|
60
|
+
has_many :children, class_name: name, foreign_key: :parent_id, inverse_of: :parent
|
60
61
|
|
61
62
|
validates :table_name, presence: true, length: { maximum: MAX_IDENTIFIER_LENGTH }
|
62
63
|
validates :definition, presence: true
|
@@ -82,6 +83,17 @@ module OnlineMigrations
|
|
82
83
|
succeeded? || failed?
|
83
84
|
end
|
84
85
|
|
86
|
+
# Overwrite enum's generated method to correctly work for composite migrations.
|
87
|
+
def cancelled!
|
88
|
+
return super if !composite?
|
89
|
+
|
90
|
+
transaction do
|
91
|
+
super
|
92
|
+
children.each { |child| child.cancelled! if !child.succeeded? }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
alias cancel cancelled!
|
96
|
+
|
85
97
|
# Returns the progress of the background schema migration.
|
86
98
|
#
|
87
99
|
# @return [Float] value in range from 0.0 to 100.0
|
@@ -109,8 +121,13 @@ module OnlineMigrations
|
|
109
121
|
# This is used to manually retrying failed migrations.
|
110
122
|
#
|
111
123
|
def retry
|
112
|
-
if composite?
|
124
|
+
if composite? && failed?
|
113
125
|
children.failed.each(&:retry)
|
126
|
+
update!(
|
127
|
+
status: self.class.statuses[:running],
|
128
|
+
finished_at: nil
|
129
|
+
)
|
130
|
+
true
|
114
131
|
elsif failed?
|
115
132
|
update!(
|
116
133
|
status: self.class.statuses[:enqueued],
|
@@ -121,6 +138,9 @@ module OnlineMigrations
|
|
121
138
|
error_message: nil,
|
122
139
|
backtrace: nil
|
123
140
|
)
|
141
|
+
true
|
142
|
+
else
|
143
|
+
false
|
124
144
|
end
|
125
145
|
end
|
126
146
|
|
@@ -11,6 +11,8 @@ module OnlineMigrations
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def run
|
14
|
+
return if migration.cancelled?
|
15
|
+
|
14
16
|
mark_as_running if migration.enqueued? || migration.failed?
|
15
17
|
|
16
18
|
if migration.composite?
|
@@ -27,7 +29,14 @@ module OnlineMigrations
|
|
27
29
|
def mark_as_running
|
28
30
|
Migration.transaction do
|
29
31
|
migration.running!
|
30
|
-
|
32
|
+
|
33
|
+
if (parent = migration.parent)
|
34
|
+
if parent.started_at
|
35
|
+
parent.update!(status: :running, finished_at: nil)
|
36
|
+
else
|
37
|
+
parent.update!(status: :running, started_at: Time.current, finished_at: nil)
|
38
|
+
end
|
39
|
+
end
|
31
40
|
end
|
32
41
|
end
|
33
42
|
|
@@ -90,10 +99,10 @@ module OnlineMigrations
|
|
90
99
|
parent.with_lock do
|
91
100
|
children = parent.children.select(:status)
|
92
101
|
if children.all?(&:succeeded?)
|
93
|
-
parent.succeeded
|
102
|
+
parent.update!(status: :succeeded, finished_at: Time.current)
|
94
103
|
completed = true
|
95
104
|
elsif children.any?(&:failed?)
|
96
|
-
parent.failed
|
105
|
+
parent.update!(status: :failed, finished_at: Time.current)
|
97
106
|
completed = true
|
98
107
|
end
|
99
108
|
end
|
@@ -6,13 +6,13 @@ module OnlineMigrations
|
|
6
6
|
class MigrationStatusValidator < ActiveModel::Validator
|
7
7
|
VALID_STATUS_TRANSITIONS = {
|
8
8
|
# enqueued -> running occurs when the migration starts performing.
|
9
|
-
"enqueued" => ["running"],
|
9
|
+
"enqueued" => ["running", "cancelled"],
|
10
10
|
# running -> succeeded occurs when the migration completes successfully.
|
11
11
|
# running -> failed occurs when the migration raises an exception when running and retry attempts exceeded.
|
12
|
-
"running" => ["succeeded", "failed"],
|
12
|
+
"running" => ["succeeded", "failed", "cancelled"],
|
13
13
|
# failed -> enqueued occurs when the failed migration is enqueued to be retried.
|
14
14
|
# failed -> running occurs when the failed migration is retried.
|
15
|
-
"failed" => ["enqueued", "running"],
|
15
|
+
"failed" => ["enqueued", "running", "cancelled"],
|
16
16
|
}
|
17
17
|
|
18
18
|
def validate(record)
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module OnlineMigrations
|
4
4
|
module BackgroundSchemaMigrations
|
5
5
|
# Class responsible for scheduling background schema migrations.
|
6
|
-
# It selects a single migration and runs it if there is no currently
|
6
|
+
# It selects a single migration and runs it if there is no currently
|
7
|
+
# running migration on the same table.
|
7
8
|
#
|
8
9
|
# Scheduler should be configured to run periodically, for example, via cron.
|
9
10
|
# @example Run via whenever
|
@@ -19,12 +20,25 @@ module OnlineMigrations
|
|
19
20
|
|
20
21
|
# Runs Scheduler
|
21
22
|
def run
|
22
|
-
migration =
|
23
|
+
migration = find_migration
|
23
24
|
if migration
|
24
25
|
runner = MigrationRunner.new(migration)
|
25
26
|
runner.run
|
26
27
|
end
|
27
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def find_migration
|
32
|
+
active_migrations = Migration.running.select(:table_name, :shard).to_a
|
33
|
+
runnable_migrations = Migration.runnable.enqueued.queue_order.to_a + Migration.retriable.queue_order.to_a
|
34
|
+
|
35
|
+
runnable_migrations.find do |runnable_migration|
|
36
|
+
active_migrations.none? do |active_migration|
|
37
|
+
active_migration.shard == runnable_migration.shard &&
|
38
|
+
active_migration.table_name == runnable_migration.table_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
28
42
|
end
|
29
43
|
end
|
30
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: online_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fatkodima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
113
|
- !ruby/object:Gem::Version
|
114
114
|
version: '0'
|
115
115
|
requirements: []
|
116
|
-
rubygems_version: 3.
|
116
|
+
rubygems_version: 3.4.19
|
117
117
|
signing_key:
|
118
118
|
specification_version: 4
|
119
119
|
summary: Catch unsafe PostgreSQL migrations in development and run them easier in
|