2011-12-12 7 views
5

Ho bisogno di un feedback sul design per il caricamento e l'elaborazione ritardata di un file usando heroku, paperclip, lavoro ritardato e, se necessario, s3. Parti di esso sono state discusse in altri luoghi ma non sono riuscito a trovare una discussione completa da nessuna parte.Paperclip, lavoro ritardato, S3, Heroku - progettazione per l'elaborazione ritardata di file caricati sensibili: db o s3?

Descrizione del compito:

  1. caricare il file (utilizzando graffetta per S3/db su Heroku). Il file deve essere privato in quanto contiene dati sensibili. file di
  2. coda per l'elaborazione (lavoro ritardato)
  3. lavoro viene eseguito in coda
  4. file viene recuperato (da S3/db), e la lavorazione è completata
  5. file viene eliminato (da S3/db)

Poiché utilizzo un lavoro in ritardo, devo decidere se memorizzare il file nel database o su s3. Suppongo che l'archiviazione del file sul server Web sia fuori questione poiché sto utilizzando heroku e il lavoro in ritardo. Il caricamento di file su s3 richiede molto tempo. Tuttavia, la memorizzazione dei file in db è più costosa. Idealmente, vorremmo che l'elaborazione finisse il più rapidamente possibile.

Qual è il motivo di progettazione più comune? Memorizza i file su s3? Memorizza i file in db? Qualche gemma particolare raccomandata utilizzata per recuperare ed elaborare i file memorizzati in s3 (aws-s3? S3?)?

risposta

4

Heroku ha un timeout di 30 secondi su qualsiasi richiesta del server (appresa nel modo più duro), quindi è assolutamente necessario archiviare i file su s3.

Prova carrierwave (carrierwave railscasts) invece di graffetta, come io preferisco gli assistenti aggiunti che arrivano a bordo, in più c'è un certo numero di grandi plugin, come carrierwave_direct per il caricamento di file di grandi dimensioni a S3, che si integrano perfettamente con carrierwave.

Delayed_job (railscast - delayed_job) funzionerà correttamente per l'eliminazione di file da s3 e qualsiasi altra elaborazione in background che potrebbe essere richiesta.

Il mio file gioiello include i seguenti:

gem 'delayed_job' 

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

gem 'fog' 

gem 'carrierwave' 

gem 'carrierwave_direct' 

nebbia gemma è un bel modo per avere tutti i vostri account di informazioni in un unico luogo e imposta a tutto abbastanza bene. Per la gemma AWS how-to, buona risorsa.

Ecco un controller di esempio al momento della presentazione di un modulo da caricare (ci sono sicuramente migliori modi di fare questo, ma a scopo illustrativo)

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 

Un sacco di codice non necessario, lo so (scritto questo quando ho stava iniziando con Rails). Speriamo che possa dare un'idea dei processi coinvolti nello scrivere questo tipo di app. Spero che sia d'aiuto.

3

Da parte mia sto usando:

  • Delayed Job
  • Paperclip
  • Delayed Paperclip che carica il file originale su S3 e creare un posto di lavoro in ritardo con la post-elaborazione personalizzata. È possibile aggiungere una colonna al modello affermando che il file viene elaborato .

Solo poche righe da impostare. E puoi fare molto con interpolazioni e generatori di graffette.