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  | 
