2013-08-23 16 views
6

Po utworzeniu obiektu w Railsach, chcę automatycznie przypisać mu obraz zapasowy z katalogu asset, który może zostać nadpisany później przez użytkownika."Errno :: EMFILE: Zbyt wiele otwartych plików" z lokalnymi obrazami przy tworzeniu

W efekcie mogę wykonać następującą metodę prywatną przy tworzeniu obiektu:

def save_stock_image 
    image_path = Dir.glob(<list-of-images-from-directory>).sample 

    File.open(image_path) do |file| 
    self.image = file 
    self.save! 
    end 
end 

Jednak po 6 testów RSpec, zaczynam pojawia się następujący błąd:

Failure/Error: let(:object) { create(:object) } 
Errno::EMFILE: 
    Too many open files - /tmp/16020130822-36578-q8j9v9.jpg 
# ./app/models/object.rb:502:in `block in save_stock_image' 
# ./app/models/object.rb:501:in `open' 
# ./app/models/object.rb:501:in `save_stock_image' 
# ./spec/controllers/object_controller_spec.rb:318:in `block (3 levels) in <top (required)>' 
# ./spec/controllers/object_controller_spec.rb:344:in `block (4 levels) in <top (required)>' 

powyższy błąd występuje w ~ 40 z 60 testów. Przyjrzałem się kilku pytaniom SO, a także https://github.com/thoughtbot/paperclip/issues/1122 i https://github.com/thoughtbot/paperclip/issues/1000. Najbliższą odpowiedzią, jaką mogłem znaleźć, było zapewnienie zamknięcia deskryptora pliku. Zanim użyłem File.open w bloku, jawnie zamknąłem plik file.close - to też nie działa.

Coś oczywistego, że robię źle? Czy istnieje lepszy sposób na zrealizowanie tego, co próbuję zrobić?

UPDATE

Wygląda na to, że ma coś wspólnego z plików tymczasowych, które Paperclip tworzy zanim zostaną one przesłane do S3. Czy jest coś, co zamyka te tymczasowe pliki, których mi brakuje?

Odpowiedz

0

Jeśli jest to rozwój/środowisko testowe i chcesz szybki rozdzielczość.

Spróbuj zidentyfikować identyfikator procesu resque, zabić go i ponownie uruchomić serwer resque.

Dodatkowo można spróbować poniżej

Redis.current.client.reconnect 
$redis = Redis.current 
0

Właśnie wpadł na to i ostatni kod mi nie pomoże. Więc delegowany pracę zamykając te pliki tymczasowe do systemu operacyjnego przez tarła proces dziecko:

def save_stock_image 
    ActiveRecord::Base.connection.disconnect! 
    Proces.fork do 
    image_path = Dir.glob(<list-of-images-from-directory>).sample 

    File.open(image_path) do |file| 
     self.image = file 
     self.save! 
    end 
    end 
    Process.wait  
    ActiveRecord::Base.establish_connection 
end 

także rozważyć umieszczenie timeout na Process.wait jak sugeruje tutaj: Waiting for Ruby child pid to exit