Skip to content

Commit 82437c0

Browse files
committed
perf: export collection (#2756)
reduce memory usage and allow larger zip export by streaming attachments to zip file instead of buffer.
1 parent 506a9bf commit 82437c0

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

app/api/chemotion/collection_api.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ class CollectionAPI < Grape::API
470470
error!('401 Unauthorized', 401) unless collection
471471
end
472472
end
473-
ExportCollectionsJob.perform_now(collection_ids, params[:format].to_s, nested, current_user.id)
473+
ExportCollectionsJob.perform_later(collection_ids, params[:format].to_s, nested, current_user.id)
474474
status 204
475475
end
476476
end

lib/export/export_collections.rb

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ def to_file
5151
DESC
5252

5353
# create a zip buffer
54-
zip = Zip::OutputStream.write_buffer do |zipping| # rubocop:disable Metrics/BlockLength
54+
Zip.write_zip64_support = true
55+
Zip::OutputStream.open(@file_path) do |zipping| # rubocop:disable Metrics/BlockLength
5556
# write the json file into the zip file
5657
export_json = to_json_data
5758
export_json_checksum = Digest::SHA256.hexdigest(export_json)
@@ -66,18 +67,23 @@ def to_file
6667
zipping.write schema_json
6768
description += "#{schema_json_checksum} schema.json\n"
6869
# write all attachemnts into an attachments directory
70+
dir_path = Pathname.new('attachments')
6971
@attachments.each do |attachment|
70-
attachment_path = File.join('attachments', "#{attachment.identifier}#{File.extname(attachment.filename)}")
71-
next if attachment.attachment_attacher.file.blank?
72+
uploaded_file = attachment.attachment
73+
next unless uploaded_file.exists?
7274

73-
zipping.put_next_entry attachment_path
74-
zipping.write attachment.attachment_attacher.file.read if attachment.attachment_attacher.file.present?
75+
attachment_path = dir_path.join("#{attachment.identifier}#{File.extname(attachment.filename)}")
76+
zipping.put_next_entry attachment_path.to_s
77+
uploaded_file.stream(zipping)
7578
description += "#{attachment.checksum} #{attachment_path}\n"
7679
next unless attachment.annotated_image?
7780

78-
annotation_path = attachment.attachment(:annotation).url
81+
annotation = attachment.attachment(:annotation)
7982
zipping.put_next_entry "#{attachment_path}_annotation"
80-
zipping.write File.read(annotation_path)
83+
annotation.stream(zipping)
84+
ensure
85+
uploaded_file.to_io.close if uploaded_file.respond_to?(:to_io)
86+
annotation.to_io.close if annotation.respond_to?(:to_io)
8187
end
8288
# write all the images into an images directory
8389
@images.each do |file_path|
@@ -93,10 +99,6 @@ def to_file
9399
zipping.write description
94100
end
95101

96-
zip.set_encoding('UTF-8')
97-
zip.rewind
98-
# write the zip file to public/zip/
99-
File.write(@file_path, zip.read)
100102
@file_path
101103
end
102104
end

0 commit comments

Comments
 (0)