2012-11-24 16 views
0

我已經得到了這個工作,但是對於一打甚至十幾個文件來說,它很慢(到了超時的時候)。將Dropbox filelist與Ruby on Rails 3中的表內容進行比較的最快速最有效的方式是什麼?

它從保管箱抓取目錄列表,並將其與表格內容進行比較。我想優化它,以便儘可能快速和高效地運行。我知道每次查詢都不是最佳的,但我認爲主要的延遲是Photo.create方法,因爲這是將文件從保管箱文件夾複製到Amazon S3(通過carrierwave gem)的地方。我正在考慮在操作上花時間看看延遲來自何處。對於包含10個文件的文件夾,加載該頁面需要一分多鐘。奇怪的是,即使它跳過這些文件也需要很長時間,因爲它們已經存在,這對我來說沒有意義。

這裏是我的控制器代碼:

def sync 
    photo_size = 1024 
    @event = Event.find(params[:id]) 

    @client = Dropbox::API::Client.new(:token => 'derp', :secret => 'herp') 
    @dropbox_files = @client.ls "images/#{@event.keyword}/#{photo_size}/" 

    @existing_photos = @event.photos.all 
    @data = [] 

    # TODO: need to make it not add files multiple times 


    @dropbox_files.each do |f| 


     photo_exists = Photo.where(:dropbox_path => f.direct_url.url).count 
     if photo_exists == 0 
     @photo = Photo.create(:remote_filename_url => f.direct_url.url, 
           :dropbox_path => f.direct_url.url, 
           :event_id => @event.id) 
     @data << "Added: #{f.direct_url.url.split('/').last}" 
     else 
     @data << "Skipped: #{f.direct_url.url.split('/').last}" 
     end 
    end 
    end 

理想的情況下,我想每個Photo.create呼叫分成一個異步請求,但是這可能是一個整體「notha事情。現在,如果能夠處理從100個列表中添加5張照片而不超時,我會很高興。

這樣做的最好方法是什麼?我是一名剛剛接觸RoR3的PHP程序員。請幫忙。謝謝!

一個注意:現在,這輸出到一個屏幕,但最終它將是一個後臺操作。

回答

1

我有幾件事情可以嘗試。我對Dropbox API並不熟悉,但您應該能夠弄清楚這一點:

存儲上次同步的日期,並且只檢索新的或更改的文件。

將您的sync方法提取到一個新的類 - 控制器可能不是這個責任的最佳選擇。這裏是你如何能做到這一點的例子:

class EventSync 
    attr_reader :event 

    def initialize(event_or_id) 
    @event = Event.find(event_or_id) 
    end 

    def sync 
    dropbox_files.each do |f| 
     process_file(f) 
    end 
    end 

    private 
    def photo_size 
     1024 
    end 

    def process_file(file) 
     event.photos.where(dropbox_path: file.direct_url.url).first_or_create do |file| 
     file.remote_filename_url = file.direct_url.url 
     end 
    end 

    def client 
     @client ||= Dropbox::API::Client.new(:token => 'derp', :secret => 'herp') 
    end 

    def dropbox_files 
     @dropbox_files ||= client.ls "images/#{event.keyword}/#{photo_size}/" 
    end 

end 

這將是這樣使用:EventSync.new(params[:event_id]).sync

通過將其分解爲許多較小的方法,基準測試將變得更加簡單(您可以單獨測試每種方法),這意味着您可以更好地識別放緩的位置。

+0

哇......好的。這與我的想法有所不同。我沒有機會嘗試和實施這一點,所以我現在就投票。我有更多的基於PHP的思維模式,所以很高興看到'ruby way'來做事情。我正確地認爲這個類只是位於/lib/eventsync.rb,並且會包含在'require'eventsync''中? – afxjzs

+1

你可以把它放在那裏,但一個很好的做法是隻將代碼放在'lib'中,以便在其他應用程序中重用。這個用例看起來相當具體,所以我可能會把它們放到'app'文件夾中。閱讀Yehuda Katz的[這個問題]的答案(http://stackoverflow.com/questions/1068558/oo-design-in-rails-where-to-put-stuff)瞭解更多信息。 –

+0

印象深刻。這幾乎是直接工作。一個問題:爲'event'和'photo'對象使用'file'引起了一些混淆。非常感謝你的幫助......這很好。 – afxjzs

0

這是我現在工作的方式,在我嘗試扎克的方法之前。

在控制器:

def syncall 
    #TODO: Refactor sync and syncall 
    photo_size = 1024 
    @event = Event.find(params[:id]) 

    new_image_dir = "images/#{@event.keyword}/#{photo_size}/" 
    @client = Dropbox::API::Client.new(:token => 'uuzpqar2m5839eo', :secret => 'nr9tmx0vc8qh892') 
    @dropbox_files = @client.ls new_image_dir 
    start = Time.now 

    existing_photos = @event.photos.all 
    @data = [] 
    photo_list = [] 

    existing_photos.each do |ep| 
     filename = URI.unescape(ep.dropbox_path.split('/').last) #dropbox_path is url encoded... 
     photo_list << filename 
    end 
    @data << photo_list 

    skipped_files = 0 

    @dropbox_files.each do |f| 
     sql_start = Time.now 
     db_filename = f.path.split('/').last 

     if photo_list.include? db_filename 
     skipped_files += 1 
     else 
     pc_start = Time.now 
     if db_filename.split('.').last == 'jpg' 
      db_path = f.direct_url.url 
      @photo = Photo.create(:remote_filename_url => db_path, 
           :dropbox_path => db_path, 
           :event_id => @event.id) 
      @data << "#{db_filename} added in #{Time.now - pc_start} seconds" 
     else 
      @data << "#{db_filename} was skipped in #{Time.now - pc_start} seconds" 
     end 
     end 
    end  
    @data << "Total Time: #{Time.now - start} (#{skipped_files} skipped.)" 
    end 

這樣一來,如果沒有文件添加,只有一個查詢運行。另一個問題是direct_url.url調用非常繁重,因爲每次調用它時都會連接到Dropbox。

從每張圖片跳過大約2秒到0.01秒,每張圖片上傳5-7秒到2-4秒。我仍然喜歡扎克的方法更好,所以我現在要嘗試一下。

相關問題