Handle unexpected errors while exporting userdata or photos
Otherwise the export stays soft-locked and the podmin needs to reset it manually. Fixes #6225
This commit is contained in:
parent
9adcca2679
commit
172f80bcae
2 changed files with 51 additions and 22 deletions
|
|
@ -297,18 +297,22 @@ class User < ApplicationRecord
|
|||
mount_uploader :export, ExportedUser
|
||||
|
||||
def queue_export
|
||||
update exporting: true
|
||||
update exporting: true, export: nil, exported_at: nil
|
||||
Workers::ExportUser.perform_async(id)
|
||||
end
|
||||
|
||||
def perform_export!
|
||||
export = Tempfile.new([username, '.json.gz'], encoding: 'ascii-8bit')
|
||||
export = Tempfile.new([username, ".json.gz"], encoding: "ascii-8bit")
|
||||
export.write(compressed_export) && export.close
|
||||
if export.present?
|
||||
update exporting: false, export: export, exported_at: Time.zone.now
|
||||
else
|
||||
update exporting: false
|
||||
end
|
||||
rescue => error
|
||||
logger.error "Unexpected error while exporting user '#{username}': #{error.class}: #{error.message}\n" \
|
||||
"#{error.backtrace.first(15).join("\n")}"
|
||||
update exporting: false
|
||||
end
|
||||
|
||||
def compressed_export
|
||||
|
|
@ -319,12 +323,16 @@ class User < ApplicationRecord
|
|||
mount_uploader :exported_photos_file, ExportedPhotos
|
||||
|
||||
def queue_export_photos
|
||||
update exporting_photos: true
|
||||
update exporting_photos: true, exported_photos_file: nil, exported_photos_at: nil
|
||||
Workers::ExportPhotos.perform_async(id)
|
||||
end
|
||||
|
||||
def perform_export_photos!
|
||||
PhotoExporter.new(self).perform
|
||||
rescue => error
|
||||
logger.error "Unexpected error while exporting photos for '#{username}': #{error.class}: #{error.message}\n" \
|
||||
"#{error.backtrace.first(15).join("\n")}"
|
||||
update exporting_photos: false
|
||||
end
|
||||
|
||||
######### Mailer #######################
|
||||
|
|
|
|||
|
|
@ -981,63 +981,84 @@ describe User, :type => :model do
|
|||
|
||||
describe "queue_export" do
|
||||
it "queues up a job to perform the export" do
|
||||
user = FactoryGirl.create :user
|
||||
user = FactoryGirl.create(:user)
|
||||
user.update export: Tempfile.new([user.username, ".json.gz"]), exported_at: Time.zone.now
|
||||
expect(Workers::ExportUser).to receive(:perform_async).with(user.id)
|
||||
user.queue_export
|
||||
expect(user.exporting).to be_truthy
|
||||
expect(user.export).not_to be_present
|
||||
expect(user.exported_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "perform_export!" do
|
||||
let(:user) { FactoryGirl.create(:user, exporting: true) }
|
||||
|
||||
it "saves a json export to the user" do
|
||||
user = FactoryGirl.create :user, exporting: true
|
||||
user.perform_export!
|
||||
expect(user.export).to be_present
|
||||
expect(user.exported_at).to be_present
|
||||
expect(user.exporting).to be_falsey
|
||||
expect(user.export.filename).to match /.json/
|
||||
expect(user.export.filename).to match(/.json/)
|
||||
expect(ActiveSupport::Gzip.decompress(user.export.file.read)).to include user.username
|
||||
end
|
||||
|
||||
it "compresses the result" do
|
||||
user = FactoryGirl.create :user, exporting: true
|
||||
expect(ActiveSupport::Gzip).to receive :compress
|
||||
user.perform_export!
|
||||
end
|
||||
|
||||
it "resets exporting to false when failing" do
|
||||
expect_any_instance_of(Diaspora::Exporter).to receive(:execute).and_raise("Unexpected error!")
|
||||
user.perform_export!
|
||||
expect(user.exporting).to be_falsey
|
||||
expect(user.export).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
describe "queue_export_photos" do
|
||||
it "queues up a job to perform the export photos" do
|
||||
user = FactoryGirl.create :user
|
||||
user = FactoryGirl.create(:user)
|
||||
user.update exported_photos_file: Tempfile.new([user.username, ".zip"]), exported_photos_at: Time.zone.now
|
||||
expect(Workers::ExportPhotos).to receive(:perform_async).with(user.id)
|
||||
user.queue_export_photos
|
||||
expect(user.exporting_photos).to be_truthy
|
||||
expect(user.exported_photos_file).not_to be_present
|
||||
expect(user.exported_photos_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "perform_export_photos!" do
|
||||
let(:user) { FactoryGirl.create(:user_with_aspect, exporting: true) }
|
||||
|
||||
before do
|
||||
@user = alice
|
||||
filename = 'button.png'
|
||||
image = File.join(File.dirname(__FILE__), '..', 'fixtures', filename)
|
||||
@saved_image = @user.build_post(:photo, :user_file => File.open(image), :to => alice.aspects.first.id)
|
||||
image = File.join(File.dirname(__FILE__), "..", "fixtures", "button.png")
|
||||
@saved_image = user.build_post(:photo, user_file: File.open(image), to: user.aspects.first.id)
|
||||
@saved_image.save!
|
||||
end
|
||||
|
||||
it "saves a zip export to the user" do
|
||||
@user.perform_export_photos!
|
||||
expect(@user.exported_photos_file).to be_present
|
||||
expect(@user.exported_photos_at).to be_present
|
||||
expect(@user.exporting_photos).to be_falsey
|
||||
expect(@user.exported_photos_file.filename).to match /.zip/
|
||||
expect(Zip::File.open(@user.exported_photos_file.path).entries.count).to eq(1)
|
||||
user.perform_export_photos!
|
||||
expect(user.exported_photos_file).to be_present
|
||||
expect(user.exported_photos_at).to be_present
|
||||
expect(user.exporting_photos).to be_falsey
|
||||
expect(user.exported_photos_file.filename).to match(/.zip/)
|
||||
expect(Zip::File.open(user.exported_photos_file.path).entries.count).to eq(1)
|
||||
end
|
||||
|
||||
it "does not add empty entries when photo not found" do
|
||||
File.unlink @user.photos.first.unprocessed_image.path
|
||||
@user.perform_export_photos!
|
||||
expect(@user.exported_photos_file.filename).to match /.zip/
|
||||
expect(Zip::File.open(@user.exported_photos_file.path).entries.count).to eq(0)
|
||||
File.unlink user.photos.first.unprocessed_image.path
|
||||
user.perform_export_photos!
|
||||
expect(user.exporting_photos).to be_falsey
|
||||
expect(user.exported_photos_file.filename).to match(/.zip/)
|
||||
expect(Zip::File.open(user.exported_photos_file.path).entries.count).to eq(0)
|
||||
end
|
||||
|
||||
it "resets exporting_photos to false when failing" do
|
||||
expect_any_instance_of(PhotoExporter).to receive(:perform).and_raise("Unexpected error!")
|
||||
user.perform_export_photos!
|
||||
expect(user.exporting_photos).to be_falsey
|
||||
expect(user.exported_photos_file).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue