2014-11-07 13 views
5

Niestety, nagroda została przyznana za odpowiedź, która nie rozwiązuje tego problemu, dla osób mających podobne problemy.Przesyłanie obrazów w tle w kolejce powodujące przekroczenie limitu czasu aplikacji

Mam formularz z przesłaniem obrazu (heroku do s3). Po przesłaniu formularza mój serwer szyn czeka na zadanie w tle, które przesyła obraz, aby zakończyć, zanim zwróci odpowiedź użytkownikowi. Powoduje to przekroczenie limitu czasu aplikacji za każdym razem, gdy przesyłany jest obraz.

Aktualna kolejność zdarzeń:

  1. użytkownik przesyła formularz
  2. Server otrzyma formularz
  3. Jeśli jest to obraz, serwer rozpoczyna pracę tła
  4. Jeśli rozpoczęto zadanie tła, serwer czeka na zakończenie (limit czasu szyn tutaj)
  5. Po uruchomieniu zadanie w tle kończy się
  6. Serwer przetwarza żądanie
  7. Serwer odpowiada użytkownikowi

żądanej kolejności wydarzeń:

  1. użytkownik przesyła formularz
  2. serwer otrzyma formularz
  3. Serwer przetwarza bez obrazu pola
  4. Jeśli istnieje obraz, serwer uruchamia zadanie w tle
  5. Serwer odpowiada użytkownikowi
  6. Zadanie tło uzupełnia i serwer przetwarza przesłany obraz (zapisuje URL)

kodu Uploader

class PhotoUploader < CarrierWave::Uploader::Base 
    include ::CarrierWave::Backgrounder::Delay 
    include CarrierWave::MimeTypes 
    process :set_content_type 
    storage :fog 
end 

Carrierwave :: Backgrounder inicjatora

CarrierWave::Backgrounder.configure do |c| 
    c.backend :sidekiq, queue: :carrierwave 
end 

modelu User

class User < ActiveRecord::Base 
    mount_uploader :photo, PhotoUploader, delayed: true 
    process_in_background :photo 
end 

Nie ma kod kontrolera, ponieważ forma jest obsługiwane przez ActiveAdmin. Mogę zastąpić wszędzie tam, gdzie jest to potrzebne, ale nie jestem w stanie dowiedzieć się, co należy zmienić.

Co muszę zmienić, aby uzyskać prawidłową kolejność zdarzeń?

+0

Przebaczam, jeśli całkowicie źle zrozumiałem ten problem, ale czy przesłanie nie będzie asynchroniczne, jeśli zostanie wykonane za pomocą standardowego formularza HTML? Czy to nie wymaga JavaScript do obsługi asynchronicznego przesyłania, coś w tym stylu? https://github.com/JangoSteve/remotipart – Ben

+0

Wszystkie samouczki i zasoby, których szukałem do przesyłania obrazów asynchronicznych, nie zmieniły wygenerowanego formularza HTML, tylko kontroler. Jak wspomniałem ** przesyłanie zdjęć działa dobrze **. Kontroler, który przetwarza formularz, nie musi czekać. – MishieMoo

+0

Przepraszamy, potrzebuję więcej kodu, aby zrozumieć, jak próbujesz to zaimplementować. Czy pracownik sidekiq obsługuje cały załadunek do S3, czy właśnie czeka w kolejce, kiedy przesyłanie jest wykonywane, aby obsłużyć aktualizację DB? Jak wygląda twój kontroler, który reaguje na przesłanie formularza? – Ben

Odpowiedz

6

Podstawową kwestią tutaj jest Heroku ma ścisłe ograniczenia dotyczące tego, jak długo żądanie może blokować bez wysyłania danych z powrotem do klienta. Jeśli osiągniesz ten limit (30 sekund na początkowy bajt), Heroku przekroczy limit czasu twojego żądania. Jeśli chcesz przesłać pliki, najprawdopodobniej osiągniesz ten limit.

Najlepszym rozwiązaniem jest, aby przeglądarka użytkownika bezpośrednio przesłała plik do S3.Jest jakaś dyskusja tutaj, że jest istotne, aby w ten sposób: Direct Uploads to S3 using Carrierwave

Jeśli używasz coś jak jQuery File Upload Plugin (https://github.com/blueimp/jQuery-File-Upload), przepływ byłoby coś jak:

  • Użytkownik dodaje jeden lub więcej plików do formularz przed kliknięciem przesłać.
  • Pliki są przesyłane bezpośrednio do S3 i do każdego pliku dodawany jest token przesyłania pliku do formularza.
  • Użytkownik przesyła formularz zawierający tokeny przesłanych plików, a nie zawartość plików.
  • Serwer może przenieść pliki do ich prawdziwego domu w S3 na podstawie przesłanego tokena.

Pozwala to serwerowi WWW skupić się tylko na obsłudze żądania i nie blokować przesyłania plików, co może zająć dużo czasu.

Wymaga to nieco więcej pracy ze względu na ograniczenia Heroku - ale ostatecznie uważam, że jest to jedyna możliwość uniknięcia limitów limitu czasu.

Zalecane jest również utworzenie zasobnika S3 do przesyłania, a następnie ustawienie zasad cyklu życia S3 w celu usuwania plików starszych niż niektóre przedziały. Kiedy robisz bezpośrednie przesyłanie plików, często niektóre pliki nie są przetwarzane z powodu rezygnacji przez użytkownika itp., Więc cykl życia zajmuje się czyszczeniem tych plików.

+0

Nie chcemy używać do tego javascript/jQuery. Idealnie możemy zmodyfikować przetwarzanie żądania, aby odpowiedzieć użytkownikowi, podczas gdy plik przesyła do s3 w tle. – MishieMoo

+0

Jeśli używasz serwera domyślne Rails na Heroku jest ograniczony do jednego wniosku na hamowni więc może być w stanie wykonać gwintowaną podejścia poprzez włączenie do Unicorn lub puma, które obsługują wiele procesów internetowych na hamowni. Najbezpieczniejszym podejściem na dłuższą metę jest jednak bezpośrednie przesyłanie plików. Zgadzam się, że nie jest to tak wygodne, ale to tylko jeden z minusów używania Heroku. Właśnie znalazłem ten artykuł przez nich, jak również - https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails – TomDavies

+0

Jesteśmy już przy użyciu Unicorn, więc limit żądania za dyno powinnaś t być problemem. Łączony artykuł używa rozwiązania jQuery = / – MishieMoo