2011-12-12 14 views
5

Necesito comentarios sobre el diseño para cargar y demorar el procesamiento de un archivo usando heroku, clip, trabajo retrasado y, si es necesario, s3. Algunas partes se han discutido en otros lugares pero no pude encontrar una discusión completa en ninguna parte.Paperclip, Delayed Job, S3, Heroku: diseño para el procesamiento diferido de archivos subidos confidenciales: ¿db o s3?

Descripción de la tarea:

  1. Subir archivo (utilizando clip para S3/db en heroku). El archivo debe ser privado, ya que contiene datos confidenciales. archivo
  2. cola para su procesamiento (trabajo retardada)
  3. trabajo se ejecuta en la cola
  4. del archivo se recupera (de s3/db), y el procesamiento se completa
  5. archivo se elimina (de s3/db)

Como uso el trabajo demorado, debo decidir entre almacenar el archivo en la base de datos o en s3. Estoy asumiendo que el almacenamiento del archivo en el servidor web está descartado ya que estoy usando heroku y trabajo retrasado. Cargar archivos en s3 lleva mucho tiempo. Pero, almacenar archivos en db es más caro. Idealmente, quisiéramos que el procesamiento termine lo más rápido posible.

¿Cuál es el patrón de diseño más común? Almacenar archivos en s3? Almacenar archivos en db? ¿Alguna gema recomendada en particular para recuperar y procesar archivos almacenados en s3 (aws-s3? S3?)?

Respuesta

4

Heroku tiene un tiempo de espera de 30 segundos en cualquier solicitud del servidor (aprendió por las malas), por lo que definitivamente el almacenamiento de archivos en s3 es obligatorio.

Trate carrierwave (carrierwave railscasts) en lugar de un clip, ya que prefiero los ayudantes adicionales que vienen a bordo, además de que hay un gran número de plugins, como carrierwave_direct para subir archivos de gran tamaño a s3, que se integran perfectamente con carrierwave.

Delayed_job (railscasts - delayed_job) funcionará muy bien para eliminar archivos de s3 y cualquier otro procesamiento de fondo que pueda ser necesario.

Mi archivo de la gema incluye lo siguiente:

gem 'delayed_job' 

gem "aws-s3", :require => 'aws/s3' 

gem 'fog' 

gem 'carrierwave' 

gem 'carrierwave_direct' 

joya niebla es una buena manera de tener toda la información de su cuenta en un solo lugar y configura todo bastante bien. Para la gema AWS how-to, buen recurso.

Aquí es un controlador de ejemplo al enviar un formulario para cargar (sin duda hay mejores maneras de hacer esto, pero para fines ilustrativos)

def create 
    @asset = Asset.new(:description => params[:description], :user_id => session[:id], :question_id => @question.id) 
    if @asset.save && @asset.update_attributes(:file_name => sanitize_filename(params[:uploadfile].original_filename, @asset.id)) 
     AWS::S3::S3Object.store(sanitize_filename(params[:uploadfile].original_filename, @asset.id), params[:uploadfile].read, 'bucket_name', :access => :private, :content_type => params[:uploadfile].content_type) 
      if object.content_length.to_i < @question.emailatt.to_i.megabytes && object.content_length.to_i < 5.megabytes 
       url = AWS::S3::S3Object.url_for(sanitize_filename(params[:uploadfile].original_filename, @asset.id), 'bucket_name') 
       if @asset.update_attributes(:download_link => 1) 
        if Usermailer.delay({:run_at => 5.minutes.from_now}).attachment_user_mailer_download_notification(@asset, @question) 
         process_attachment_user_mailer_download(params[:uploadfile], @asset.id, 24.hours.from_now, @question.id) 
         flash[:notice] = "Thank you for the upload, we will notify this posts author" 
        end 
       end 
      end 
    else 
     @asset.destroy 
     flash[:notice] = "There was an error in processing your upload, please try again" 
     redirect_to(:controller => "questions", :action => "show", :id => @question.id) 
    end 
end 


private 

    def sanitize_filename(file_name, id) 
     just_filename = File.basename(file_name) 
     just_filename.sub(/[^\w\.\-]/,'_') 
     new_id = id.to_s 
     new_filename = "#{new_id}" + just_filename 
    end 

    def delete_process(uploadfile, asset_id, time, question_id) 
     asset = Asset.find(:first, :conditions => ["id = ?", asset_id]) 
     if delete_file(uploadfile, asset_id, time) && asset.destroy 
      redirect_to(:controller => "questions", :action => "show", :id => question_id) 
     end 
    end 


def process_attachment_user_mailer_download(uploadfile, asset_id, time, question_id) 
     asset = Asset.find(:first, :conditions => ["id = ?", asset_id]) 
     if delete_file(uploadfile, asset_id, time) && @asset.delay({:run_at => time}).update_attributes(:download_link => 0) 
      redirect_to(:controller => "questions", :action => "show", :id => question_id) 
     end 
    end 

    #S3 METHODS FOR CREATE ACTION 

    #deletes the uploaded file from s3 
    def delete_file(uploadfile, asset_id, time) 
     AWS::S3::S3Object.delay({:run_at => time}).delete(sanitize_filename(uploadfile.original_filename, asset_id), 'bucket_name') 
    end 

porciones de código innecesario, lo sé (Escribe esto cuando estaba comenzando con Rails). Con suerte, dará una idea de los procesos involucrados en la escritura de este tipo de aplicación. Espero eso ayude.

3

Por mi parte estoy usando:

  • Delayed Job
  • Paperclip
  • Delayed Paperclip que carga el archivo original en S3 y crear un trabajo retrasado con el post-procesamiento personalizado. Es puede agregar una columna a su modelo que indica que el archivo está siendo procesado .

Solo unas líneas para configurar. Y puede hacer mucho con interpolaciones y generadores de clips.

Cuestiones relacionadas