mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 10:20:58 -06:00
Ignore delay when first migration was < 10min ago
This commit is contained in:
parent
cd17f60952
commit
4ad401bac5
@ -33,7 +33,12 @@ module Migration
|
||||
SELECT 1
|
||||
FROM schema_migration_details
|
||||
WHERE name = :after_migration AND
|
||||
created_at <= (current_timestamp AT TIME ZONE 'UTC' - INTERVAL :delay)
|
||||
(created_at <= (current_timestamp AT TIME ZONE 'UTC' - INTERVAL :delay) OR
|
||||
(SELECT created_at
|
||||
FROM schema_migration_details
|
||||
ORDER BY id ASC
|
||||
LIMIT 1) > (current_timestamp AT TIME ZONE 'UTC' - INTERVAL '10 minutes')
|
||||
)
|
||||
)
|
||||
SQL
|
||||
end
|
||||
|
@ -4,49 +4,97 @@ require_dependency 'migration/column_dropper'
|
||||
RSpec.describe Migration::ColumnDropper do
|
||||
|
||||
def has_column?(table, column)
|
||||
Topic.exec_sql("SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
table_schema = 'public' AND
|
||||
table_name = :table AND
|
||||
column_name = :column
|
||||
",
|
||||
table: table, column: column
|
||||
).to_a.length == 1
|
||||
ActiveRecord::Base.exec_sql(<<~SQL, table: table, column: column).to_a.length == 1
|
||||
SELECT 1
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
table_schema = 'public' AND
|
||||
table_name = :table AND
|
||||
column_name = :column
|
||||
SQL
|
||||
end
|
||||
|
||||
it "can correctly drop columns after correct delay" do
|
||||
Topic.exec_sql "ALTER TABLE topics ADD COLUMN junk int"
|
||||
name = Topic
|
||||
.exec_sql("SELECT name FROM schema_migration_details LIMIT 1")
|
||||
.getvalue(0, 0)
|
||||
def update_first_migration_date(created_at)
|
||||
ActiveRecord::Base.exec_sql(<<~SQL, created_at: created_at)
|
||||
UPDATE schema_migration_details
|
||||
SET created_at = :created_at
|
||||
WHERE id = (SELECT MIN(id)
|
||||
FROM schema_migration_details)
|
||||
SQL
|
||||
end
|
||||
|
||||
Topic.exec_sql("UPDATE schema_migration_details SET created_at = :created_at WHERE name = :name",
|
||||
name: name, created_at: 15.minutes.ago)
|
||||
describe ".drop" do
|
||||
let(:migration_name) do
|
||||
ActiveRecord::Base
|
||||
.exec_sql("SELECT name FROM schema_migration_details ORDER BY id DESC LIMIT 1")
|
||||
.getvalue(0, 0)
|
||||
end
|
||||
|
||||
dropped_proc_called = false
|
||||
before do
|
||||
Topic.exec_sql "ALTER TABLE topics ADD COLUMN junk int"
|
||||
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: name,
|
||||
columns: ['junk'],
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
ActiveRecord::Base.exec_sql(<<~SQL, name: migration_name, created_at: 15.minutes.ago)
|
||||
UPDATE schema_migration_details
|
||||
SET created_at = :created_at
|
||||
WHERE name = :name
|
||||
SQL
|
||||
end
|
||||
|
||||
expect(has_column?('topics', 'junk')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
it "can correctly drop columns after correct delay" do
|
||||
dropped_proc_called = false
|
||||
update_first_migration_date(2.years.ago)
|
||||
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: name,
|
||||
columns: ['junk'],
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: migration_name,
|
||||
columns: ['junk'],
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(has_column?('topics', 'junk')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
expect(has_column?('topics', 'junk')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: migration_name,
|
||||
columns: ['junk'],
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(has_column?('topics', 'junk')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
|
||||
it "drops the columns immediately if the first migration was less than 10 minutes ago" do
|
||||
dropped_proc_called = false
|
||||
update_first_migration_date(11.minutes.ago)
|
||||
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: migration_name,
|
||||
columns: ['junk'],
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(has_column?('topics', 'junk')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
update_first_migration_date(9.minutes.ago)
|
||||
|
||||
Migration::ColumnDropper.drop(
|
||||
table: 'topics',
|
||||
after_migration: migration_name,
|
||||
columns: ['junk'],
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(has_column?('topics', 'junk')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.mark_readonly' do
|
||||
|
@ -14,83 +14,168 @@ describe Migration::TableDropper do
|
||||
ActiveRecord::Base.exec_sql(sql).to_a.length > 0
|
||||
end
|
||||
|
||||
def update_first_migration_date(created_at)
|
||||
ActiveRecord::Base.exec_sql(<<~SQL, created_at: created_at)
|
||||
UPDATE schema_migration_details
|
||||
SET created_at = :created_at
|
||||
WHERE id = (SELECT MIN(id)
|
||||
FROM schema_migration_details)
|
||||
SQL
|
||||
end
|
||||
|
||||
def create_new_table
|
||||
ActiveRecord::Base.exec_sql "CREATE TABLE table_with_new_name (topic_id INTEGER)"
|
||||
end
|
||||
|
||||
let(:migration_name) do
|
||||
ActiveRecord::Base
|
||||
.exec_sql("SELECT name FROM schema_migration_details LIMIT 1")
|
||||
.exec_sql("SELECT name FROM schema_migration_details ORDER BY id DESC LIMIT 1")
|
||||
.getvalue(0, 0)
|
||||
end
|
||||
|
||||
before do
|
||||
ActiveRecord::Base.exec_sql "CREATE TABLE table_with_old_name (topic_id INTEGER)"
|
||||
|
||||
Topic.exec_sql("UPDATE schema_migration_details SET created_at = :created_at WHERE name = :name",
|
||||
name: migration_name, created_at: 15.minutes.ago)
|
||||
ActiveRecord::Base.exec_sql(<<~SQL, name: migration_name, created_at: 15.minutes.ago)
|
||||
UPDATE schema_migration_details
|
||||
SET created_at = :created_at
|
||||
WHERE name = :name
|
||||
SQL
|
||||
end
|
||||
|
||||
describe "#delayed_rename" do
|
||||
it "can drop a table after correct delay and when new table exists" do
|
||||
dropped_proc_called = false
|
||||
context "first migration was a long time ago" do
|
||||
before do
|
||||
update_first_migration_date(2.years.ago)
|
||||
end
|
||||
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
describe ".delayed_rename" do
|
||||
it "can drop a table after correct delay and when new table exists" do
|
||||
dropped_proc_called = false
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
ActiveRecord::Base.exec_sql "CREATE TABLE table_with_new_name (topic_id INTEGER)"
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
create_new_table
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".delayed_drop" do
|
||||
it "can drop a table after correct delay" do
|
||||
dropped_proc_called = false
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#delayed_drop" do
|
||||
it "can drop a table after correct delay" do
|
||||
dropped_proc_called = false
|
||||
context "first migration was a less than 10 minutes ago" do
|
||||
describe ".delayed_rename" do
|
||||
it "can drop a table after correct delay and when new table exists" do
|
||||
dropped_proc_called = false
|
||||
update_first_migration_date(11.minutes.ago)
|
||||
create_new_table
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 20.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 10.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
update_first_migration_date(9.minutes.ago)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
described_class.delayed_rename(
|
||||
old_name: 'table_with_old_name',
|
||||
new_name: 'table_with_new_name',
|
||||
after_migration: migration_name,
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".delayed_drop" do
|
||||
it "immediately drops the table" do
|
||||
dropped_proc_called = false
|
||||
update_first_migration_date(11.minutes.ago)
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(true)
|
||||
expect(dropped_proc_called).to eq(false)
|
||||
|
||||
update_first_migration_date(9.minutes.ago)
|
||||
|
||||
described_class.delayed_drop(
|
||||
table_name: 'table_with_old_name',
|
||||
after_migration: migration_name,
|
||||
delay: 30.minutes,
|
||||
on_drop: ->() { dropped_proc_called = true }
|
||||
)
|
||||
|
||||
expect(table_exists?('table_with_old_name')).to eq(false)
|
||||
expect(dropped_proc_called).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user