2016-11-08 4 views
0

ActiveJobsidekiq과 함께 레일을 백엔드로 사용합니다. 사용자가 페이지 sidekiq에 오면 장기 배경 작업을 생성합니다. 작업이 완료되면 어떻게 사용자를 알 수 있습니까 (웹 페이지의 렌더링 부분)?백그라운드 작업이 완료된 후 사용자에게 알리는 방법은 무엇입니까?

레일과 사이드 키는 다른 프로세스로 작동합니다. 이 사실은 혼란 스러웠습니다. 백그라운드 작업을 사용하여 완료 상태를 처리하는 방법을 이해하지 못합니다.

답변

3

ActiveJob이 문서에 따라 다음과 같이 작동 after_perform 콜백 제공

class VideoProcessJob < ActiveJob::Base 
    queue_as :default 

    after_perform do |job| 
    UserMailer.notify_video_processed(job.arguments.first) 
    end 

    def perform(video_id) 
    Video.find(video_id).process 
    end 
end 

그래서, 당신은 Sidekiq 또는 다른 대기 백엔드와 직접 통합 걱정하지 않아도을 ActiveJob :

이야기 이 상황에서
+0

Thx,하지만 웹 페이지에서 렌더링 부분으로 사용자에게 알리고 싶습니다. – mystdeim

+1

@mystdeim 문제는 웹 페이지입니다! 사용자는 누구에게나 갈 수 있었습니까? 가능할 수있는 모든 렌더링/리디렉션은 좋은 생각이 아닙니다. 대신'ActionCable' subscription에 의해 트리거 된 알림 모달을 사용하십시오. 코드를 게시하려고 시도하지만 어렵지 않아야합니다. 행운을 빌어 요 – Nimir

1

나의 접근 방식은 다음과 같습니다

  1. 그 backg에 너무 sidekiq-status 추가 라운드 작업은 ID로 추적 할 수 있습니다.
  2. 백그라운드 작업을 만드는 클라이언트 호출에서 새로 생성 된 작업 ID를 반환하십시오.

    class MyController < ApplicationController 
    
        def create 
        # sidekiq-status lets us retrieve a unique job ID when 
        # creating a job 
        job_id = Workers::MyJob.perform_async(...) 
    
        # tell the client where to find the progress of this job 
        return :json => { 
         :next => "/my/progress?job_id={job_id}" 
        } 
        end 
    
    end 
    
  3. 해당 작업 ID가있는 서버의 '진행'엔드 포인트를 폴하십시오. 이 엔드 포인트는 작업에 대한 작업 진행 정보를 가져 와서 클라이언트로 리턴합니다. 클라이언트가 작업이 완료되었음을보고하는 경우

    class MyController < ApplicationController 
    
        def progress 
        # fetch job status from sidekiq-status 
        status = Sidekiq::Status::get_all(params[:job_id]) 
    
        # in practice, status can be nil if the info has expired from 
        # Redis; I'm ignoring that for the purpose of this example 
    
        if status["complete"] 
         # job is complete; notify the client in some way 
         # perhaps by sending it a rendered partial 
         payload = { 
         :html => render_to_string({ 
          :partial => "my/job_finished", 
          :layout => nil 
         }) 
         } 
        else 
         # tell client to check back again later 
         payload = {:next => "/my/progress?job_id={params[:job_id]}"} 
        end 
    
        render :json => payload 
        end 
    
    end 
    
  4. , 그것은 다음 메시지를 표시하거나 필요합니다 다음 어떤 단계를 취할 수 있습니다.

    var getProgress = function(progress_url, poll_interval) { 
        $.get(progress_url).done(function(progress) { 
        if(progress.html) { 
         // job is complete; show HTML returned by server 
         $('#my-container').html(progress.html); 
        } else { 
         // job is not yet complete, try again later at the URL 
         // provided by the server 
         setTimeout(function() { 
         getProgress(progress.next, poll_interval); 
         }, poll_interval); 
        } 
        }); 
    }; 
    $("#my-button").on('click', function(e) { 
        $.post("/my").done(function(data) { 
        getProgress(data.next, 5000); 
        }); 
        e.preventDefault(); 
    }); 
    

주의 할의 위험 부담 : 그 코드를 예시하기위한 것입니다, 당신은 등 중복 제출 방지, 오류 처리 등의 돌봐해야하고 일이 없습니다.

+0

풀을 사용하면 더 이상 쓸모가 없으며 websocket 또는 SSE를 사용하여 push-notification을 선호합니다. – mystdeim

+0

@mystdeim websockets/SSE를 사용하여 좀 더 우아하게 예제를 공유 할 수 있습니까? (나는 이것을 달성하기위한 최선의 방법을 찾아 내려고 노력하고 있지만 불행히도 많은 예를 찾을 수는 없다) – gingerlime