2012-11-14 12 views
6

Powiedzmy, że mam aplikację blogową z wpisami. Po utworzeniu postu tworzony jest pracownik obsługujący niektóre operacje w tle. Mój przypadek polega na tym, że po przesłaniu formularza pocztowego chcę wyświetlić jakiś komunikat o załadowaniu (ładowarka GIF lub podobna) i kiedy pracownik zakończy pracę, chcę ukryć wiadomość ładującą i wyświetlić dane dostarczone przez pracownika. Moje pytanie brzmi: jaki jest najlepszy sposób poinformowania, że ​​pracownik zakończył swoje zadanie i wyświetli go na interfejsie użytkownika. Pracownik zwrotna wyglądać takPracownicy w tle przeglądają komunikację w aplikacji szyny

def worker_finish 
    #message the user 
end 

Odpowiedz

11

myślę, że może być brakuje punktu posiadania pracowników w tle, w zasadzie, co próbujesz zrobić, to samozagłady. - Jeśli użytkownik przesyła formularz i umieszcza w kolejce zadanie w kontrolerze, tylko po to, aby użytkownik czekał na pracownika zarówno na początku, jak i na końcu, nie tylko dokonał dokładnie tego, co kontroler mógł wykonać sam, ale sprawił, że proces stał się o wiele bardziej skomplikowany (i ten typ funkcji nie jest wbudowany ani w resque, ani w sidekiq).

Podczas rozładunku zadania mają być przetwarzane przez kolejce chcesz powrócić odpowiedź do klienta niezwłocznie, tj

class PostsController < ApplicationController 
    def create 
    @post = Post.create(params[:post]) 
    BackgroundBlogOperation.enque(@post.id) 
    respond_with(@post) 
    end 
end 

Klasa BackgroundBlogOperation byłyby następnie umieszczane w kolejce, dla pracownika, aby przejść przez i pracować. Jeśli potrzebujesz, aby pracownik BackgroundBlogOperation zrobił coś jeszcze po jego zakończeniu, możesz to zrobić, ale powinno to nastąpić w samym zadaniu, aby pracownik mógł być za to odpowiedzialny.

Jeśli próbujesz wyświetlić i ukryć spinner po utworzeniu postu, bez przeładowywania strony, po prostu wyświetl spinacz javascript przed kliknięciem przycisku submit i upewnij się, że typem zapytania jest js (add: remote = > true to form). Następnie należy utworzyć javascript odpowiedź widok, który wygląda tak:

class PostsController < ApplicationController 
    respond_to :js, :only => [:create] 
    def create 
    @post = Post.create(params[:post]) 
    BackgroundBlogOperation.enque(@post.id) 
    respond_with(@post) 
    end 
end 

a create.js.erb, można również dołączyć wiadomość mówiąc im, że cokolwiek robisz w tle została w kolejce, jeśli jego bardziej skomplikowane niż tworzenie post lub cokolwiek innego.

$("#spinner").hide(); 

Teraz - Choć co pytali pierwotnie doesent bezcelowe (bo do wyświetlania i ukrywania tarczy po zakończeniu pracy wymagałoby czeka na kontrolerze, aby zakończyć operację) - Istnieją sytuacje, w których wyświetlanie klientowi, że zadanie zostało zakończone, jest użyteczne.

Najpierw określmy scenariusz, w którym przetwarzanie w tle jest rzeczywiście użyteczne. Powiedzmy, że masz przycisk, który po kliknięciu pobierze dane z jakiegoś zewnętrznego interfejsu API, a po pobraniu danych z witryny zewnętrznej wykonasz operację bazy danych na podstawie odpowiedzi. Byłby to dobry przykład wykorzystania procesu w tle. Zasadniczo w kontrolerze byś zrobił coś takiego:

class ApiController < ApplicationController 
    respond_to :js, :only => [:create] 

    def sync_tweets 
    TwitterApiJob.enque(current_user.twitter_username) 
    respond_with(message: 'Syncing Tweets') 
    end 

end 

Teraz, aby poinformować użytkownika, gdy tweets zakończeniu synchronizacji jest nieco bardziej skomplikowana, a masz 3 podstawowe opcje:

1) poinformować użytkowników za pośrednictwem poczty e-mail (najgorsza opcja imo) 2) Użyj jakiegoś serwera html5 lub serwera obsługującego WebSocket, aby uruchamiać szyny, i przesyłaj przez klienta websocket, który, choć bardzo fajny, jest w większości przypadków przesadą i poza zakresem tej odpowiedzi. Google szyny websocket naciskając, jeśli chcesz zobaczyć swoje opcje. 3) IMO najlepszym rozwiązaniem dla większości przypadków, Tworzenie modelu notifcations do obsługi wszelkiego rodzaju zgłoszeń użytkowników, aw swojej pracy, po zakończeniu pracy, zrobić coś

Notification.create(:user_id => user.id, :message => 'Sync has finished', type => 'sync_complete') 

Następnie następnej stronie na żądanie użytkownika , na pasku narzędzi nagłówka lub gdziekolwiek, chciałbym zauważyć, że użytkownik ma nieprzeczytane powiadomienia, aby ostrzec użytkownika, aby go kliknął.

--- Także myślę, że we wpisie wspomniałeś, że używasz resque. Próbowałem resque i było przyzwoite, ale znalazłem to zbyt skomplikowane do debugowania w produkcji, i używało zwariowanej pamięci - radziłbym sprawdzić sidekiq, jeśli jeszcze tego nie zrobiłeś, używa redis także, ale znacznie szybciej, ponieważ używa wątki:

https://github.com/mperham/sidekiq

To jest znacznie szybsze, czystsze i łatwe do uzyskania konfiguracji, imho.

+0

Chociaż przedstawiony przypadek użycia może nie być idealny, funkcja może być bardzo przydatna do generowania raportu na przykład. – aaandre

Powiązane problemy