Skip to content

Commit

Permalink
DEV: Put a mutex around Upload.migrate_to_new_scheme.
Browse files Browse the repository at this point in the history
This ensures that only one migration is running at any given point in
time across the instances.
  • Loading branch information
tgxworld committed Apr 24, 2019
1 parent 55f406b commit 3c9495b
Showing 1 changed file with 90 additions and 82 deletions.
172 changes: 90 additions & 82 deletions app/models/upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,97 +205,105 @@ def rebake_posts_on_old_scheme
def self.migrate_to_new_scheme(limit: nil)
problems = []

if SiteSetting.migrate_to_new_scheme
max_file_size_kb = [SiteSetting.max_image_size_kb, SiteSetting.max_attachment_size_kb].max.kilobytes
local_store = FileStore::LocalStore.new
db = RailsMultisite::ConnectionManagement.current_db
DistributedMutex.synchronize("migrate_upload_to_new_scheme") do
if SiteSetting.migrate_to_new_scheme
max_file_size_kb = [
SiteSetting.max_image_size_kb,
SiteSetting.max_attachment_size_kb
].max.kilobytes

scope = Upload.by_users.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/#{db}%'").order(id: :desc)
local_store = FileStore::LocalStore.new
db = RailsMultisite::ConnectionManagement.current_db

scope = scope.limit(limit) if limit
scope = Upload.by_users
.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/#{db}%'")
.order(id: :desc)

if scope.count == 0
SiteSetting.migrate_to_new_scheme = false
return problems
end
scope = scope.limit(limit) if limit

remap_scope = nil

scope.each do |upload|
begin
# keep track of the url
previous_url = upload.url.dup
# where is the file currently stored?
external = previous_url =~ /^\/\//
# download if external
if external
url = SiteSetting.scheme + ":" + previous_url

begin
retries ||= 0

file = FileHelper.download(
url,
max_file_size: max_file_size_kb,
tmp_file_name: "discourse",
follow_redirect: true
)
rescue OpenURI::HTTPError
retry if (retires += 1) < 1
next
end
if scope.count == 0
SiteSetting.migrate_to_new_scheme = false
return problems
end

path = file.path
else
path = local_store.path_for(upload)
end
# compute SHA if missing
if upload.sha1.blank?
upload.sha1 = Upload.generate_digest(path)
end
remap_scope = nil

scope.each do |upload|
begin
# keep track of the url
previous_url = upload.url.dup
# where is the file currently stored?
external = previous_url =~ /^\/\//
# download if external
if external
url = SiteSetting.scheme + ":" + previous_url

begin
retries ||= 0

file = FileHelper.download(
url,
max_file_size: max_file_size_kb,
tmp_file_name: "discourse",
follow_redirect: true
)
rescue OpenURI::HTTPError
retry if (retires += 1) < 1
next
end

path = file.path
else
path = local_store.path_for(upload)
end
# compute SHA if missing
if upload.sha1.blank?
upload.sha1 = Upload.generate_digest(path)
end

# store to new location & update the filesize
File.open(path) do |f|
upload.url = Discourse.store.store_upload(f, upload)
upload.filesize = f.size
upload.save!(validate: false)
end
# remap the URLs
DbHelper.remap(UrlHelper.absolute(previous_url), upload.url) unless external

DbHelper.remap(
previous_url,
upload.url,
excluded_tables: %w{
posts
post_search_data
}
)

remap_scope ||= begin
Post.with_deleted
.where("raw ~ '/uploads/#{db}/\\d+/' OR raw ~ '/uploads/#{db}/original/\\d{1}/'")
.select(:raw, :cooked)
.all
end
# store to new location & update the filesize
File.open(path) do |f|
upload.url = Discourse.store.store_upload(f, upload)
upload.filesize = f.size
upload.save!(validate: false)
end
# remap the URLs
DbHelper.remap(UrlHelper.absolute(previous_url), upload.url) unless external

DbHelper.remap(
previous_url,
upload.url,
excluded_tables: %w{
posts
post_search_data
}
)

remap_scope ||= begin
Post.with_deleted
.where("raw ~ '/uploads/#{db}/\\d+/' OR raw ~ '/uploads/#{db}/original/\\d{1}/'")
.select(:raw, :cooked)
.all
end

remap_scope.each do |post|
post.raw.gsub!(previous_url, upload.url)
post.cooked.gsub!(previous_url, upload.url)
post.save! if post.changed?
end
remap_scope.each do |post|
post.raw.gsub!(previous_url, upload.url)
post.cooked.gsub!(previous_url, upload.url)
post.save! if post.changed?
end

upload.optimized_images.find_each(&:destroy!)
upload.rebake_posts_on_old_scheme
# remove the old file (when local)
unless external
FileUtils.rm(path, force: true)
upload.optimized_images.find_each(&:destroy!)
upload.rebake_posts_on_old_scheme
# remove the old file (when local)
unless external
FileUtils.rm(path, force: true)
end
rescue => e
problems << { upload: upload, ex: e }
ensure
file&.unlink
file&.close
end
rescue => e
problems << { upload: upload, ex: e }
ensure
file&.unlink
file&.close
end
end
end
Expand Down

0 comments on commit 3c9495b

Please sign in to comment.