online_migrations 0.25.0 → 0.27.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 +31 -0
- data/README.md +18 -73
- data/docs/0.27-upgrade.md +24 -0
- data/docs/background_data_migrations.md +200 -101
- data/docs/background_schema_migrations.md +2 -2
- data/docs/configuring.md +8 -0
- data/lib/generators/online_migrations/{background_migration_generator.rb → data_migration_generator.rb} +4 -4
- data/lib/generators/online_migrations/templates/add_sharding_to_online_migrations.rb.tt +1 -1
- data/lib/generators/online_migrations/templates/add_timestamps_to_background_migrations.rb.tt +1 -1
- data/lib/generators/online_migrations/templates/background_schema_migrations_change_unique_index.rb.tt +1 -1
- data/lib/generators/online_migrations/templates/change_background_data_migrations.rb.tt +34 -0
- data/lib/generators/online_migrations/templates/{background_data_migration.rb.tt → data_migration.rb.tt} +8 -9
- data/lib/generators/online_migrations/templates/initializer.rb.tt +22 -25
- data/lib/generators/online_migrations/templates/install_migration.rb.tt +9 -40
- data/lib/generators/online_migrations/upgrade_generator.rb +16 -8
- data/lib/online_migrations/active_record_batch_enumerator.rb +8 -0
- data/lib/online_migrations/background_data_migrations/backfill_column.rb +50 -0
- data/lib/online_migrations/background_data_migrations/config.rb +62 -0
- data/lib/online_migrations/{background_migrations → background_data_migrations}/copy_column.rb +15 -28
- data/lib/online_migrations/{background_migrations → background_data_migrations}/delete_associated_records.rb +9 -5
- data/lib/online_migrations/{background_migrations → background_data_migrations}/delete_orphaned_records.rb +5 -9
- data/lib/online_migrations/background_data_migrations/migration.rb +312 -0
- data/lib/online_migrations/{background_migrations → background_data_migrations}/migration_helpers.rb +72 -61
- data/lib/online_migrations/background_data_migrations/migration_job.rb +158 -0
- data/lib/online_migrations/background_data_migrations/migration_status_validator.rb +65 -0
- data/lib/online_migrations/{background_migrations → background_data_migrations}/perform_action_on_relation.rb +5 -5
- data/lib/online_migrations/{background_migrations → background_data_migrations}/reset_counters.rb +5 -5
- data/lib/online_migrations/background_data_migrations/scheduler.rb +78 -0
- data/lib/online_migrations/background_data_migrations/ticker.rb +62 -0
- data/lib/online_migrations/background_schema_migrations/config.rb +2 -2
- data/lib/online_migrations/background_schema_migrations/migration.rb +57 -127
- data/lib/online_migrations/background_schema_migrations/migration_helpers.rb +26 -47
- data/lib/online_migrations/background_schema_migrations/migration_runner.rb +43 -97
- data/lib/online_migrations/background_schema_migrations/scheduler.rb +2 -2
- data/lib/online_migrations/batch_iterator.rb +7 -4
- data/lib/online_migrations/change_column_type_helpers.rb +75 -14
- data/lib/online_migrations/command_checker.rb +32 -20
- data/lib/online_migrations/config.rb +12 -4
- data/lib/online_migrations/data_migration.rb +127 -0
- data/lib/online_migrations/error_messages.rb +16 -0
- data/lib/online_migrations/index_definition.rb +1 -1
- data/lib/online_migrations/lock_retrier.rb +5 -2
- data/lib/online_migrations/migration.rb +8 -1
- data/lib/online_migrations/schema_cache.rb +0 -78
- data/lib/online_migrations/schema_statements.rb +18 -74
- data/lib/online_migrations/shard_aware.rb +44 -0
- data/lib/online_migrations/utils.rb +1 -20
- data/lib/online_migrations/verbose_sql_logs.rb +1 -7
- data/lib/online_migrations/version.rb +1 -1
- data/lib/online_migrations.rb +19 -19
- metadata +25 -24
- data/lib/online_migrations/background_migration.rb +0 -64
- data/lib/online_migrations/background_migrations/backfill_column.rb +0 -54
- data/lib/online_migrations/background_migrations/background_migration_class_validator.rb +0 -29
- data/lib/online_migrations/background_migrations/config.rb +0 -74
- data/lib/online_migrations/background_migrations/migration.rb +0 -329
- data/lib/online_migrations/background_migrations/migration_job.rb +0 -109
- data/lib/online_migrations/background_migrations/migration_job_runner.rb +0 -66
- data/lib/online_migrations/background_migrations/migration_job_status_validator.rb +0 -29
- data/lib/online_migrations/background_migrations/migration_runner.rb +0 -161
- data/lib/online_migrations/background_migrations/migration_status_validator.rb +0 -48
- data/lib/online_migrations/background_migrations/scheduler.rb +0 -42
@@ -3,7 +3,7 @@
|
|
3
3
|
module OnlineMigrations
|
4
4
|
module SchemaStatements
|
5
5
|
include ChangeColumnTypeHelpers
|
6
|
-
include
|
6
|
+
include BackgroundDataMigrations::MigrationHelpers
|
7
7
|
include BackgroundSchemaMigrations::MigrationHelpers
|
8
8
|
|
9
9
|
# Updates the value of a column in batches.
|
@@ -568,8 +568,8 @@ module OnlineMigrations
|
|
568
568
|
#
|
569
569
|
def add_text_limit_constraint(table_name, column_name, limit, name: nil, validate: true)
|
570
570
|
column = column_for(table_name, column_name)
|
571
|
-
if column.type != :text
|
572
|
-
raise "add_text_limit_constraint must be used only with :text columns"
|
571
|
+
if column.type != :text && column.type != :string
|
572
|
+
raise "add_text_limit_constraint must be used only with :text or :string columns"
|
573
573
|
end
|
574
574
|
|
575
575
|
name ||= __text_limit_constraint_name(table_name, column_name)
|
@@ -710,16 +710,12 @@ module OnlineMigrations
|
|
710
710
|
index_name = (options[:name] || index_name(table_name, column_name)).to_s
|
711
711
|
indexes(table_name).find { |i| i.name == index_name }
|
712
712
|
else
|
713
|
-
|
714
|
-
# See https://github.com/rails/rails/pull/45160.
|
715
|
-
indexes(table_name).find { |i| __index_defined_for?(i, column_name, **options) }
|
713
|
+
indexes(table_name).find { |i| i.defined_for?(column_name, **options) }
|
716
714
|
end
|
717
715
|
|
718
716
|
if index
|
719
|
-
|
720
|
-
|
721
|
-
if __index_valid?(index.name, schema: schema)
|
722
|
-
Utils.say("Index was not created because it already exists.")
|
717
|
+
if index.valid?
|
718
|
+
Utils.say("Index #{index.name} was not created because it already exists.")
|
723
719
|
return
|
724
720
|
else
|
725
721
|
Utils.say("Recreating invalid index: table_name: #{table_name}, column_name: #{column_name}")
|
@@ -764,22 +760,6 @@ module OnlineMigrations
|
|
764
760
|
end
|
765
761
|
end
|
766
762
|
|
767
|
-
# @private
|
768
|
-
# From ActiveRecord. Will not be needed for ActiveRecord >= 7.1.
|
769
|
-
def index_name(table_name, options)
|
770
|
-
if options.is_a?(Hash)
|
771
|
-
if options[:column]
|
772
|
-
Utils.index_name(table_name, options[:column])
|
773
|
-
elsif options[:name]
|
774
|
-
options[:name]
|
775
|
-
else
|
776
|
-
raise ArgumentError, "You must specify the index name"
|
777
|
-
end
|
778
|
-
else
|
779
|
-
index_name(table_name, column: options)
|
780
|
-
end
|
781
|
-
end
|
782
|
-
|
783
763
|
# Extends default method to be idempotent.
|
784
764
|
#
|
785
765
|
# @see https://edgeapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_foreign_key
|
@@ -833,7 +813,7 @@ module OnlineMigrations
|
|
833
813
|
# @see https://edgeapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_check_constraint
|
834
814
|
#
|
835
815
|
def add_check_constraint(table_name, expression, **options)
|
836
|
-
if
|
816
|
+
if check_constraint_exists?(table_name, expression: expression, **options)
|
837
817
|
Utils.say(<<~MSG.squish)
|
838
818
|
Check constraint was not created because it already exists (this may be due to an aborted migration or similar).
|
839
819
|
table_name: #{table_name}, expression: #{expression}
|
@@ -864,7 +844,7 @@ module OnlineMigrations
|
|
864
844
|
# @see https://edgeapi.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-remove_check_constraint
|
865
845
|
#
|
866
846
|
def remove_check_constraint(table_name, expression = nil, **options)
|
867
|
-
if
|
847
|
+
if check_constraint_exists?(table_name, expression: expression, **options)
|
868
848
|
super
|
869
849
|
else
|
870
850
|
Utils.say(<<~MSG.squish)
|
@@ -874,16 +854,14 @@ module OnlineMigrations
|
|
874
854
|
end
|
875
855
|
end
|
876
856
|
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
super
|
886
|
-
end
|
857
|
+
def add_exclusion_constraint(table_name, expression, **options)
|
858
|
+
if __exclusion_constraint_exists?(table_name, expression: expression, **options)
|
859
|
+
Utils.say(<<~MSG.squish)
|
860
|
+
Exclusion constraint was not created because it already exists (this may be due to an aborted migration or similar).
|
861
|
+
table_name: #{table_name}, expression: #{expression}
|
862
|
+
MSG
|
863
|
+
else
|
864
|
+
super
|
887
865
|
end
|
888
866
|
end
|
889
867
|
|
@@ -932,20 +910,9 @@ module OnlineMigrations
|
|
932
910
|
end
|
933
911
|
end
|
934
912
|
|
935
|
-
# Will not be needed for Active Record >= 7.1
|
936
|
-
def __index_defined_for?(index, columns = nil, name: nil, unique: nil, valid: nil, include: nil, nulls_not_distinct: nil, **options)
|
937
|
-
columns = options[:column] if columns.blank?
|
938
|
-
(columns.nil? || Array(index.columns) == Array(columns).map(&:to_s)) &&
|
939
|
-
(name.nil? || index.name == name.to_s) &&
|
940
|
-
(unique.nil? || index.unique == unique) &&
|
941
|
-
(valid.nil? || index.valid == valid) &&
|
942
|
-
(include.nil? || Array(index.include) == Array(include).map(&:to_s)) &&
|
943
|
-
(nulls_not_distinct.nil? || index.nulls_not_distinct == nulls_not_distinct)
|
944
|
-
end
|
945
|
-
|
946
913
|
def __not_null_constraint_exists?(table_name, column_name, name: nil)
|
947
914
|
name ||= __not_null_constraint_name(table_name, column_name)
|
948
|
-
|
915
|
+
check_constraint_exists?(table_name, name: name)
|
949
916
|
end
|
950
917
|
|
951
918
|
def __not_null_constraint_name(table_name, column_name)
|
@@ -958,21 +925,7 @@ module OnlineMigrations
|
|
958
925
|
|
959
926
|
def __text_limit_constraint_exists?(table_name, column_name, name: nil)
|
960
927
|
name ||= __text_limit_constraint_name(table_name, column_name)
|
961
|
-
|
962
|
-
end
|
963
|
-
|
964
|
-
# Can use index validity attribute for Active Record >= 7.1.
|
965
|
-
def __index_valid?(index_name, schema:)
|
966
|
-
select_value(<<~SQL)
|
967
|
-
SELECT indisvalid
|
968
|
-
FROM pg_index i
|
969
|
-
JOIN pg_class c
|
970
|
-
ON i.indexrelid = c.oid
|
971
|
-
JOIN pg_namespace n
|
972
|
-
ON c.relnamespace = n.oid
|
973
|
-
WHERE n.nspname = #{schema}
|
974
|
-
AND c.relname = #{quote(index_name)}
|
975
|
-
SQL
|
928
|
+
check_constraint_exists?(table_name, name: name)
|
976
929
|
end
|
977
930
|
|
978
931
|
def __copy_foreign_key(fk, to_column, **options)
|
@@ -996,15 +949,6 @@ module OnlineMigrations
|
|
996
949
|
end
|
997
950
|
end
|
998
951
|
|
999
|
-
# Can be replaced by native method in Active Record >= 7.1.
|
1000
|
-
def __check_constraint_exists?(table_name, **options)
|
1001
|
-
if !options.key?(:name) && !options.key?(:expression)
|
1002
|
-
raise ArgumentError, "At least one of :name or :expression must be supplied"
|
1003
|
-
end
|
1004
|
-
|
1005
|
-
check_constraint_for(table_name, **options).present?
|
1006
|
-
end
|
1007
|
-
|
1008
952
|
def __exclusion_constraint_exists?(table_name, **options)
|
1009
953
|
if !options.key?(:name) && !options.key?(:expression)
|
1010
954
|
raise ArgumentError, "At least one of :name or :expression must be supplied"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlineMigrations
|
4
|
+
module ShardAware
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_validation :set_connection_class_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def on_shard_if_present(&block)
|
12
|
+
if shard
|
13
|
+
connection_class.connected_to(shard: shard.to_sym, role: :writing, &block)
|
14
|
+
else
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def connection_class_name=(value)
|
20
|
+
if value && (klass = value.safe_constantize)
|
21
|
+
if !(klass <= ActiveRecord::Base)
|
22
|
+
raise ArgumentError, "connection_class_name is not an ActiveRecord::Base child class"
|
23
|
+
end
|
24
|
+
|
25
|
+
connection_class = Utils.find_connection_class(klass)
|
26
|
+
super(connection_class.name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# @private
|
31
|
+
def connection_class
|
32
|
+
if connection_class_name && (klass = connection_class_name.safe_constantize)
|
33
|
+
Utils.find_connection_class(klass)
|
34
|
+
else
|
35
|
+
ActiveRecord::Base
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def set_connection_class_name
|
41
|
+
self.connection_class_name ||= "ActiveRecord::Base"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -69,23 +69,6 @@ module OnlineMigrations
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
# Implementation is from ActiveRecord.
|
73
|
-
# This is not needed for ActiveRecord >= 7.1 (https://github.com/rails/rails/pull/47753).
|
74
|
-
def index_name(table_name, column_name)
|
75
|
-
max_index_name_size = 62
|
76
|
-
name = "index_#{table_name}_on_#{Array(column_name) * '_and_'}"
|
77
|
-
return name if name.bytesize <= max_index_name_size
|
78
|
-
|
79
|
-
# Fallback to short version, add hash to ensure uniqueness
|
80
|
-
hashed_identifier = "_#{OpenSSL::Digest::SHA256.hexdigest(name).first(10)}"
|
81
|
-
name = "idx_on_#{Array(column_name) * '_'}"
|
82
|
-
|
83
|
-
short_limit = max_index_name_size - hashed_identifier.bytesize
|
84
|
-
short_name = name[0, short_limit]
|
85
|
-
|
86
|
-
"#{short_name}#{hashed_identifier}"
|
87
|
-
end
|
88
|
-
|
89
72
|
# Returns estimated rows count for a table.
|
90
73
|
# https://www.citusdata.com/blog/2016/10/12/count-performance/
|
91
74
|
def estimated_count(connection, table_name)
|
@@ -144,9 +127,7 @@ module OnlineMigrations
|
|
144
127
|
# This is the way that currently is used in ActiveRecord tests themselves.
|
145
128
|
pool_manager = ActiveRecord::Base.connection_handler.send(:get_pool_manager, ancestor.name)
|
146
129
|
|
147
|
-
|
148
|
-
# See https://github.com/rails/rails/pull/49284.
|
149
|
-
return pool_manager.shard_names.uniq if pool_manager
|
130
|
+
return pool_manager.shard_names if pool_manager
|
150
131
|
end
|
151
132
|
end
|
152
133
|
|
@@ -14,13 +14,7 @@ module OnlineMigrations
|
|
14
14
|
stdout_logger.level = @activerecord_logger_was.level
|
15
15
|
stdout_logger = ActiveSupport::TaggedLogging.new(stdout_logger)
|
16
16
|
|
17
|
-
combined_logger =
|
18
|
-
# Broadcasting logs API was changed in https://github.com/rails/rails/pull/48615.
|
19
|
-
if Utils.ar_version >= 7.1
|
20
|
-
ActiveSupport::BroadcastLogger.new(stdout_logger, @activerecord_logger_was)
|
21
|
-
else
|
22
|
-
stdout_logger.extend(ActiveSupport::Logger.broadcast(@activerecord_logger_was))
|
23
|
-
end
|
17
|
+
combined_logger = ActiveSupport::BroadcastLogger.new(stdout_logger, @activerecord_logger_was)
|
24
18
|
|
25
19
|
ActiveRecord::Base.logger = combined_logger
|
26
20
|
ActiveRecord.verbose_query_logs = false
|
data/lib/online_migrations.rb
CHANGED
@@ -6,7 +6,8 @@ require "online_migrations/version"
|
|
6
6
|
require "online_migrations/utils"
|
7
7
|
require "online_migrations/background_schema_migrations/migration_helpers"
|
8
8
|
require "online_migrations/change_column_type_helpers"
|
9
|
-
require "online_migrations/
|
9
|
+
require "online_migrations/background_data_migrations/migration_helpers"
|
10
|
+
require "online_migrations/active_record_batch_enumerator"
|
10
11
|
require "online_migrations/schema_statements"
|
11
12
|
require "online_migrations/schema_cache"
|
12
13
|
require "online_migrations/migration"
|
@@ -29,7 +30,8 @@ module OnlineMigrations
|
|
29
30
|
autoload :ForeignKeysCollector
|
30
31
|
autoload :IndexDefinition
|
31
32
|
autoload :CommandChecker
|
32
|
-
autoload :
|
33
|
+
autoload :DataMigration
|
34
|
+
autoload :ShardAware
|
33
35
|
|
34
36
|
autoload_at "online_migrations/lock_retrier" do
|
35
37
|
autoload :LockRetrier
|
@@ -40,24 +42,21 @@ module OnlineMigrations
|
|
40
42
|
|
41
43
|
autoload :CopyTrigger
|
42
44
|
|
43
|
-
module
|
45
|
+
module BackgroundDataMigrations
|
44
46
|
extend ActiveSupport::Autoload
|
45
47
|
|
46
48
|
autoload :Config
|
47
49
|
autoload :MigrationStatusValidator
|
48
|
-
autoload :MigrationJobStatusValidator
|
49
|
-
autoload :BackgroundMigrationClassValidator
|
50
50
|
autoload :BackfillColumn
|
51
51
|
autoload :CopyColumn
|
52
52
|
autoload :DeleteAssociatedRecords
|
53
53
|
autoload :DeleteOrphanedRecords
|
54
54
|
autoload :PerformActionOnRelation
|
55
55
|
autoload :ResetCounters
|
56
|
-
autoload :MigrationJob
|
57
56
|
autoload :Migration
|
58
|
-
autoload :
|
59
|
-
autoload :MigrationRunner
|
57
|
+
autoload :MigrationJob
|
60
58
|
autoload :Scheduler
|
59
|
+
autoload :Ticker
|
61
60
|
end
|
62
61
|
|
63
62
|
module BackgroundSchemaMigrations
|
@@ -70,6 +69,10 @@ module OnlineMigrations
|
|
70
69
|
autoload :Scheduler
|
71
70
|
end
|
72
71
|
|
72
|
+
# Make aliases for less typing.
|
73
|
+
DataMigrations = BackgroundDataMigrations
|
74
|
+
SchemaMigrations = BackgroundSchemaMigrations
|
75
|
+
|
73
76
|
class << self
|
74
77
|
# @private
|
75
78
|
attr_accessor :current_migration
|
@@ -87,10 +90,10 @@ module OnlineMigrations
|
|
87
90
|
# @option options [String, Symbol, nil] :shard The name of the shard to run
|
88
91
|
# background data migrations on. By default runs on all shards.
|
89
92
|
#
|
90
|
-
def
|
91
|
-
|
93
|
+
def run_background_data_migrations(**options)
|
94
|
+
BackgroundDataMigrations::Scheduler.run(**options)
|
92
95
|
end
|
93
|
-
alias run_background_data_migrations
|
96
|
+
alias run_background_migrations run_background_data_migrations
|
94
97
|
|
95
98
|
# Run background schema migrations
|
96
99
|
#
|
@@ -102,12 +105,7 @@ module OnlineMigrations
|
|
102
105
|
end
|
103
106
|
|
104
107
|
def deprecator
|
105
|
-
@deprecator ||=
|
106
|
-
if Utils.ar_version >= 7.1
|
107
|
-
ActiveSupport::Deprecation.new(nil, "online_migrations")
|
108
|
-
else
|
109
|
-
ActiveSupport::Deprecation
|
110
|
-
end
|
108
|
+
@deprecator ||= ActiveSupport::Deprecation.new(nil, "online_migrations")
|
111
109
|
end
|
112
110
|
|
113
111
|
# @private
|
@@ -124,11 +122,13 @@ module OnlineMigrations
|
|
124
122
|
|
125
123
|
if OnlineMigrations::Utils.ar_version >= 7.2
|
126
124
|
ActiveRecord::ConnectionAdapters::SchemaCache.prepend(OnlineMigrations::SchemaCache72)
|
127
|
-
elsif OnlineMigrations::Utils.ar_version >= 7.1
|
128
|
-
ActiveRecord::ConnectionAdapters::SchemaCache.prepend(OnlineMigrations::SchemaCache71)
|
129
125
|
else
|
130
126
|
ActiveRecord::ConnectionAdapters::SchemaCache.prepend(OnlineMigrations::SchemaCache)
|
131
127
|
end
|
128
|
+
|
129
|
+
if !ActiveRecord::Batches::BatchEnumerator.method_defined?(:use_ranges)
|
130
|
+
ActiveRecord::Batches::BatchEnumerator.include(OnlineMigrations::ActiveRecordBatchEnumerator)
|
131
|
+
end
|
132
132
|
end
|
133
133
|
end
|
134
134
|
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.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fatkodima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '7.
|
19
|
+
version: '7.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '7.
|
26
|
+
version: '7.1'
|
27
27
|
description:
|
28
28
|
email:
|
29
29
|
- fatkodima123@gmail.com
|
@@ -34,39 +34,38 @@ files:
|
|
34
34
|
- CHANGELOG.md
|
35
35
|
- LICENSE.txt
|
36
36
|
- README.md
|
37
|
+
- docs/0.27-upgrade.md
|
37
38
|
- docs/background_data_migrations.md
|
38
39
|
- docs/background_schema_migrations.md
|
39
40
|
- docs/configuring.md
|
40
|
-
- lib/generators/online_migrations/
|
41
|
+
- lib/generators/online_migrations/data_migration_generator.rb
|
41
42
|
- lib/generators/online_migrations/install_generator.rb
|
42
43
|
- lib/generators/online_migrations/templates/add_sharding_to_online_migrations.rb.tt
|
43
44
|
- lib/generators/online_migrations/templates/add_timestamps_to_background_migrations.rb.tt
|
44
|
-
- lib/generators/online_migrations/templates/background_data_migration.rb.tt
|
45
45
|
- lib/generators/online_migrations/templates/background_schema_migrations_change_unique_index.rb.tt
|
46
|
+
- lib/generators/online_migrations/templates/change_background_data_migrations.rb.tt
|
46
47
|
- lib/generators/online_migrations/templates/create_background_schema_migrations.rb.tt
|
48
|
+
- lib/generators/online_migrations/templates/data_migration.rb.tt
|
47
49
|
- lib/generators/online_migrations/templates/initializer.rb.tt
|
48
50
|
- lib/generators/online_migrations/templates/install_migration.rb.tt
|
49
51
|
- lib/generators/online_migrations/templates/migration.rb.tt
|
50
52
|
- lib/generators/online_migrations/upgrade_generator.rb
|
51
53
|
- lib/online_migrations.rb
|
54
|
+
- lib/online_migrations/active_record_batch_enumerator.rb
|
52
55
|
- lib/online_migrations/application_record.rb
|
53
|
-
- lib/online_migrations/
|
54
|
-
- lib/online_migrations/
|
55
|
-
- lib/online_migrations/
|
56
|
-
- lib/online_migrations/
|
57
|
-
- lib/online_migrations/
|
58
|
-
- lib/online_migrations/
|
59
|
-
- lib/online_migrations/
|
60
|
-
- lib/online_migrations/
|
61
|
-
- lib/online_migrations/
|
62
|
-
- lib/online_migrations/
|
63
|
-
- lib/online_migrations/
|
64
|
-
- lib/online_migrations/
|
65
|
-
- lib/online_migrations/
|
66
|
-
- lib/online_migrations/background_migrations/migration_status_validator.rb
|
67
|
-
- lib/online_migrations/background_migrations/perform_action_on_relation.rb
|
68
|
-
- lib/online_migrations/background_migrations/reset_counters.rb
|
69
|
-
- lib/online_migrations/background_migrations/scheduler.rb
|
56
|
+
- lib/online_migrations/background_data_migrations/backfill_column.rb
|
57
|
+
- lib/online_migrations/background_data_migrations/config.rb
|
58
|
+
- lib/online_migrations/background_data_migrations/copy_column.rb
|
59
|
+
- lib/online_migrations/background_data_migrations/delete_associated_records.rb
|
60
|
+
- lib/online_migrations/background_data_migrations/delete_orphaned_records.rb
|
61
|
+
- lib/online_migrations/background_data_migrations/migration.rb
|
62
|
+
- lib/online_migrations/background_data_migrations/migration_helpers.rb
|
63
|
+
- lib/online_migrations/background_data_migrations/migration_job.rb
|
64
|
+
- lib/online_migrations/background_data_migrations/migration_status_validator.rb
|
65
|
+
- lib/online_migrations/background_data_migrations/perform_action_on_relation.rb
|
66
|
+
- lib/online_migrations/background_data_migrations/reset_counters.rb
|
67
|
+
- lib/online_migrations/background_data_migrations/scheduler.rb
|
68
|
+
- lib/online_migrations/background_data_migrations/ticker.rb
|
70
69
|
- lib/online_migrations/background_schema_migrations/config.rb
|
71
70
|
- lib/online_migrations/background_schema_migrations/migration.rb
|
72
71
|
- lib/online_migrations/background_schema_migrations/migration_helpers.rb
|
@@ -79,6 +78,7 @@ files:
|
|
79
78
|
- lib/online_migrations/command_recorder.rb
|
80
79
|
- lib/online_migrations/config.rb
|
81
80
|
- lib/online_migrations/copy_trigger.rb
|
81
|
+
- lib/online_migrations/data_migration.rb
|
82
82
|
- lib/online_migrations/database_tasks.rb
|
83
83
|
- lib/online_migrations/error_messages.rb
|
84
84
|
- lib/online_migrations/foreign_keys_collector.rb
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/online_migrations/schema_cache.rb
|
90
90
|
- lib/online_migrations/schema_dumper.rb
|
91
91
|
- lib/online_migrations/schema_statements.rb
|
92
|
+
- lib/online_migrations/shard_aware.rb
|
92
93
|
- lib/online_migrations/utils.rb
|
93
94
|
- lib/online_migrations/verbose_sql_logs.rb
|
94
95
|
- lib/online_migrations/version.rb
|
@@ -107,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
108
|
requirements:
|
108
109
|
- - ">="
|
109
110
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
111
|
+
version: '3.1'
|
111
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
113
|
requirements:
|
113
114
|
- - ">="
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OnlineMigrations
|
4
|
-
# Base class that is inherited by the host application's background migration classes.
|
5
|
-
class BackgroundMigration
|
6
|
-
class NotFoundError < NameError; end
|
7
|
-
|
8
|
-
class << self
|
9
|
-
# Finds a Background Migration with the given name.
|
10
|
-
#
|
11
|
-
# @param name [String] the name of the Background Migration to be found.
|
12
|
-
#
|
13
|
-
# @return [BackgroundMigration] the Background Migration with the given name.
|
14
|
-
#
|
15
|
-
# @raise [NotFoundError] if a Background Migration with the given name does not exist.
|
16
|
-
#
|
17
|
-
def named(name)
|
18
|
-
namespace = OnlineMigrations.config.background_migrations.migrations_module.constantize
|
19
|
-
internal_namespace = ::OnlineMigrations::BackgroundMigrations
|
20
|
-
|
21
|
-
migration = "#{namespace}::#{name}".safe_constantize ||
|
22
|
-
"#{internal_namespace}::#{name}".safe_constantize
|
23
|
-
|
24
|
-
raise NotFoundError.new("Background Migration #{name} not found", name) if migration.nil?
|
25
|
-
if !(migration.is_a?(Class) && migration < self)
|
26
|
-
raise NotFoundError.new("#{name} is not a Background Migration", name)
|
27
|
-
end
|
28
|
-
|
29
|
-
migration
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# The relation to be iterated over.
|
34
|
-
#
|
35
|
-
# @return [ActiveRecord::Relation]
|
36
|
-
#
|
37
|
-
# @raise [NotImplementedError] with a message advising subclasses to
|
38
|
-
# implement an override for this method.
|
39
|
-
#
|
40
|
-
def relation
|
41
|
-
raise NotImplementedError, "#{self.class.name} must implement a 'relation' method"
|
42
|
-
end
|
43
|
-
|
44
|
-
# Processes one batch.
|
45
|
-
#
|
46
|
-
# @param _relation [ActiveRecord::Relation] the current batch from the enumerator being iterated
|
47
|
-
# @return [void]
|
48
|
-
#
|
49
|
-
# @raise [NotImplementedError] with a message advising subclasses to
|
50
|
-
# implement an override for this method.
|
51
|
-
#
|
52
|
-
def process_batch(_relation)
|
53
|
-
raise NotImplementedError, "#{self.class.name} must implement a 'process_batch' method"
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns the count of rows that will be iterated over (optional, to be able to show progress).
|
57
|
-
#
|
58
|
-
# @return [Integer, nil, :no_count]
|
59
|
-
#
|
60
|
-
def count
|
61
|
-
:no_count
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OnlineMigrations
|
4
|
-
module BackgroundMigrations
|
5
|
-
# @private
|
6
|
-
class BackfillColumn < BackgroundMigration
|
7
|
-
attr_reader :table_name, :updates, :model_name
|
8
|
-
|
9
|
-
def initialize(table_name, updates, model_name = nil)
|
10
|
-
@table_name = table_name
|
11
|
-
@updates = updates
|
12
|
-
@model_name = model_name
|
13
|
-
end
|
14
|
-
|
15
|
-
def relation
|
16
|
-
column, value = updates.first
|
17
|
-
|
18
|
-
if updates.size == 1 && !value.nil?
|
19
|
-
# If value is nil, the generated SQL is correct (`WHERE column IS NOT NULL`).
|
20
|
-
# Otherwise, the SQL is `WHERE column != value`. This condition ignores column
|
21
|
-
# with NULLs in it, so we need to also manually check for NULLs.
|
22
|
-
quoted_column = connection.quote_column_name(column)
|
23
|
-
model.unscoped.where("#{quoted_column} != ? OR #{quoted_column} IS NULL", value)
|
24
|
-
else
|
25
|
-
model.unscoped.where.not(updates)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def process_batch(relation)
|
30
|
-
relation.update_all(updates)
|
31
|
-
end
|
32
|
-
|
33
|
-
def count
|
34
|
-
# Exact counts are expensive on large tables, since PostgreSQL
|
35
|
-
# needs to do a full scan. An estimated count should give a pretty decent
|
36
|
-
# approximation of rows count in this case.
|
37
|
-
Utils.estimated_count(connection, table_name)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def model
|
42
|
-
@model ||= if model_name.present?
|
43
|
-
Object.const_get(model_name, false)
|
44
|
-
else
|
45
|
-
Utils.define_model(table_name)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def connection
|
50
|
-
model.connection
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module OnlineMigrations
|
4
|
-
module BackgroundMigrations
|
5
|
-
# @private
|
6
|
-
class BackgroundMigrationClassValidator < ActiveModel::Validator
|
7
|
-
def validate(record)
|
8
|
-
relation = record.migration_relation
|
9
|
-
migration_name = record.migration_name
|
10
|
-
|
11
|
-
if !relation.is_a?(ActiveRecord::Relation)
|
12
|
-
record.errors.add(
|
13
|
-
:migration_name,
|
14
|
-
"#{migration_name}#relation must return an ActiveRecord::Relation object"
|
15
|
-
)
|
16
|
-
return
|
17
|
-
end
|
18
|
-
|
19
|
-
if relation.arel.orders.present? || relation.arel.taken.present?
|
20
|
-
record.errors.add(
|
21
|
-
:migration_name,
|
22
|
-
"#{migration_name}#relation cannot use ORDER BY or LIMIT due to the way how iteration with a cursor is designed. " \
|
23
|
-
"You can use other ways to limit the number of rows, e.g. a WHERE condition on the primary key column."
|
24
|
-
)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|