diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/concerns/configurable.rb | 26 | ||||
| -rw-r--r-- | app/services/file_service.rb | 23 | ||||
| -rw-r--r-- | app/services/http_service.rb | 36 | ||||
| -rw-r--r-- | app/services/zip_service.rb | 55 | ||||
| -rw-r--r-- | app/workers/workbench_import_worker.rb | 21 |
5 files changed, 156 insertions, 5 deletions
diff --git a/app/concerns/configurable.rb b/app/concerns/configurable.rb new file mode 100644 index 000000000..c7d0f1fd9 --- /dev/null +++ b/app/concerns/configurable.rb @@ -0,0 +1,26 @@ +module Configurable + + module ClassMethods + def config &blk + blk ? blk.(configuration) : configuration + end + + private + def configuration + @__configuration__ ||= Rails::Application::Configuration.new + end + end + + module InstanceMethods + private + + def config + self.class.config + end + end + + def self.included(into) + into.extend ClassMethods + into.send :include, InstanceMethods + end +end diff --git a/app/services/file_service.rb b/app/services/file_service.rb new file mode 100644 index 000000000..efccbe24f --- /dev/null +++ b/app/services/file_service.rb @@ -0,0 +1,23 @@ +module FileService extend self + + def unique_filename( path, enum_with: with_ints ) + file_names = enum_with.map( &file_name_maker(path) ) + file_names + .drop_while( &File.method(:exists?) ) + .next + end + + def with_ints(format='%d') + (0..Float::INFINITY) + .lazy + .map{ |n| format % n } + end + + + private + + def file_name_maker path + ->(n){ [path, n].join('_') } + end + +end diff --git a/app/services/http_service.rb b/app/services/http_service.rb new file mode 100644 index 000000000..a3c4d2569 --- /dev/null +++ b/app/services/http_service.rb @@ -0,0 +1,36 @@ +class HTTPService + def self.get_resource(*args) + new.get_resource(*args) + end + + def get_resource(host:, path:, token: nil, params: {}, parse_json: false) + Faraday.new(url: host) do |c| + c.headers['Authorization'] = "Token token=#{token.inspect}" if token + c.adapter Faraday.default_adapter + + resp = c.get path, params + if resp.status == 200 + return parse_json ? JSON.parse(resp.body) : resp.body + else + raise "Error on api request status : #{resp.status} => #{resp.body}" + end + end + end + + def post_resource(host:, path:, resource_name:, token: nil, params: {}, upload: nil) + Faraday.new(url: host) do |c| + c.headers['Authorization'] = "Token token=#{token.inspect}" if token + c.request :multipart + c.request :url_encoded + c.adapter Faraday.default_adapter + + if upload + name = upload.keys.first + value, mime_type, as_name = upload.values.first + params.update( name => Faraday::UploadIO.new(value, mime_type, as_name ) ) + end + + c.post path, resource_name => params + end + end +end diff --git a/app/services/zip_service.rb b/app/services/zip_service.rb new file mode 100644 index 000000000..778bfd06d --- /dev/null +++ b/app/services/zip_service.rb @@ -0,0 +1,55 @@ +class ZipService + + attr_reader :current_entry, :zip_data + + def initialize data + @zip_data = data + @current_entry = nil + end + + class << self + def convert_entries entries + -> output_stream do + entries.each do |e| + output_stream.put_next_entry e.name + output_stream.write e.get_input_stream.read + end + end + end + + def entries input_stream + Enumerator.new do |enum| + loop{ enum << input_stream.get_next_entry } + end.lazy.take_while{ |e| e } + end + end + + def entry_groups + self.class.entries(input_stream).group_by(&method(:entry_key)) + end + + def entry_group_streams + entry_groups.map(&method(:make_stream)).to_h + end + + def entry_key entry + entry.name.split('/', -1)[-2] + end + + def make_stream pair + name, entries = pair + [name, make_stream_from( entries )] + end + + def make_stream_from entries + Zip::OutputStream.write_buffer(&self.class.convert_entries(entries)) + end + + def next_entry + @current_entry = input_stream.get_next_entry + end + + def input_stream + @__input_stream__ ||= Zip::InputStream.open(StringIO.new(zip_data)) + end +end diff --git a/app/workers/workbench_import_worker.rb b/app/workers/workbench_import_worker.rb index 18d3ae112..d1a381e0c 100644 --- a/app/workers/workbench_import_worker.rb +++ b/app/workers/workbench_import_worker.rb @@ -1,6 +1,7 @@ class WorkbenchImportWorker include Sidekiq::Worker include Rails.application.routes.url_helpers + include Configurable attr_reader :import, :downloaded @@ -17,18 +18,22 @@ class WorkbenchImportWorker path: import_path, params: {token: import.token_download}) - Tempfile.open( do | tmpfile | - tmpfile.write zipfile_data - @downloaded = tmpfile.path + path = File.join(config.dir, import.name.gsub(%r{\s+}, '-')) + unique_path = FileService.unique_filename path + Dir.mkdir unique_path + @downloaded = File.join(unique_path, import.name) + File.open(downloaded, 'wb') do | file | + file.write zipfile_data end - if one_entry? - upload(@downloaded) + if single_entry? + upload(downloaded) else split_zip.each(&method(:upload)) end end + def single_entry? true end @@ -40,6 +45,12 @@ class WorkbenchImportWorker def upload zip_file end + # Memoized Values + + def dirname + @__dirname__ ||= make_unique_dir + end + def import_host @__import_host__ ||= Rails.application.config.front_end_host end |
