복붙노트

[RUBY-ON-RAILS] 긴 delayed_job 작업은 Heroku가에 다시 시작하면 잠금이 유지 실행

RUBY-ON-RAILS

긴 delayed_job 작업은 Heroku가에 다시 시작하면 잠금이 유지 실행

Heroku가 작업자 (명령이나 전개의 결과로서 어느) 다시 시작할 때 Heroku가 작업자 프로세스에 SIGTERM 보낸다. delayed_job의 경우 SIGTERM 신호를 잡은 후, 작업자는 중지 (있는 경우), 현재 작업 후에 실행하지 않습니다.

작업자가 작업이 오래 걸리는 경우, Heroku가는 SIGKILL을 보내드립니다. delayed_job의 경우,이 잎은 다른 노동자에 의해 선택되지 않습니다 데이터베이스에 작업을 잠금.

나는 (오류가 아니라면) 작업이 최종적으로 완료되었는지 확인하고 싶습니다. 그 감안할 때,이 접근하는 가장 좋은 방법은 무엇인가?

나는 두 가지 옵션을 참조하십시오. 하지만 다른 입력을 좀하고 싶습니다 :

이견있는 사람?

해결법

  1. ==============================

    1.TLDR :

    TLDR :

    작업 방법의 상단에 이것을 넣어 :

    begin
      term_now = false
      old_term_handler = trap 'TERM' do
        term_now = true
        old_term_handler.call
      end
    

    확실이 10 초마다 한 번 이상에서 호출되어 있는지 확인합니다 :

      if term_now
        puts 'told to terminate'
        return true
      end
    

    당신의 방법의 끝에서,이를 넣어 :

    ensure
      trap 'TERM', old_term_handler
    end
    

    설명:

    저도 같은 문제가이 Heroku가 기사에 온되었다.

    나는이 글을 따라 트랩 ( 'TERM')와 출구를 추가하므로 작업, 외부 루프가 포함되어 있습니다. 그러나 실패로 최대로는 SystemExit없이 마크와 함께 작업을 실패 픽 delayed_job.

    SIGTERM이 지금 우리 함정에 의해 갇혀로 작업자의 핸들러가 호출 대신 즉시 작업을 다시 시작하고 몇 초 후에 SIGKILL를 얻을 수 없습니다. 원점으로 돌아가다.

    나는 출구 몇 가지 대안을 시도했다 :

    내 최종 솔루션은 세 부분으로 구성되어, 내 대답의 상단에 주어진 하나 :

  2. ==============================

    2.훨씬 더 나은 솔루션은 이제 delayed_job에 내장되어 있습니다. 당신의 이니셜이 추가하여 TERM 신호에 예외를 throw하려면이 설정을 사용합니다 :

    훨씬 더 나은 솔루션은 이제 delayed_job에 내장되어 있습니다. 당신의 이니셜이 추가하여 TERM 신호에 예외를 throw하려면이 설정을 사용합니다 :

    Delayed::Worker.raise_signal_exceptions = :term
    

    이 설정을 사용하면 작업이 제대로 최종 KILL 신호가 비 협력 프로세스를 대상으로 발행 Heroku가 이전까지 종료 정리합니다 :

    raise_signal_exceptions에 대한 가능한 값은 다음과 같습니다

    버전 3.0.5부터 사용할 수 있습니다.

    이 도입 된 곳이 커밋을 참조하십시오.

  3. ==============================

    3.사이트에 새로운, 그래서 데이브의 게시물에 언급, 새로운 답을 추가 할 필요가 없습니다.

    사이트에 새로운, 그래서 데이브의 게시물에 언급, 새로운 답을 추가 할 필요가 없습니다.

    나는 데이브의 접근 방식이 문제는 내 작업 (분 8 시간까지) 긴, 모두에서 반복적 아니라는 것이다. 나는 10 초마다 "전화 확인"할 수 없다. 또한, 나는 데이브의 답변을 시도하고, 직업에 관계없이 항상 내가 돌아 무엇을 대기열에서 제거 - true 또는 false. 나는 큐에 작업을 유지하는 방법에 관해서는 불분명입니다.

    이이 풀 요청을 참조하십시오. 나는 이것이 나를 위해 작동 할 수있다 생각합니다. 그것은에 대한 의견 및 풀 요청을 지원 주시기 바랍니다.

    나는 현재 다음 종료 신호 ... 지금까지 운이 구출 함정을 실험하고있다.

  4. ==============================

    4.즉 max_run_time가 무엇인지입니다 : max_run_time이 작업이 잠겨 때부터 경과 한 후, 다른 프로세스가 잠금을 획득 할 수있을 것입니다.

    즉 max_run_time가 무엇인지입니다 : max_run_time이 작업이 잠겨 때부터 경과 한 후, 다른 프로세스가 잠금을 획득 할 수있을 것입니다.

    구글 그룹에서이 설명을 참조하십시오

  5. ==============================

    5.내가 lib에 스틱 / 다음 내 지연된 작업의 내부에서 ExitOnTermSignal.execute {긴 실행 작업을} 실행 블록을 수행하는 모듈을 생성, 그래서 나는 몇 군데에서이 작업을 수행 할 필요가 끝났다.

    내가 lib에 스틱 / 다음 내 지연된 작업의 내부에서 ExitOnTermSignal.execute {긴 실행 작업을} 실행 블록을 수행하는 모듈을 생성, 그래서 나는 몇 군데에서이 작업을 수행 할 필요가 끝났다.

    # Exits whatever is currently running when a SIGTERM is received. Needed since
    # Delayed::Job traps TERM, so it does not clean up a job properly if the
    # process receives a SIGTERM then SIGKILL, as happens on Heroku.
    module ExitOnTermSignal
      def self.execute(&block)
        original_term_handler = Signal.trap 'TERM' do
          original_term_handler.call
          # Easiest way to kill job immediately and having DJ mark it as failed:
          exit
        end
    
        begin
          yield
        ensure
          Signal.trap 'TERM', original_term_handler
        end
      end
    end
    
  6. ==============================

    6.나는 작업의 진행 상황을 추적, 나는 / 주어진 작업에서 수행 전화를 여러 번 반대하고 파괴적인 행동을 다시 적용되지 않습니다 확신 할 수 있도록 프로세스 나무 등을 할 수있는 상태 머신을 사용합니다. 그런 다음 TERM에 로그를 해제 레이크 작업 / delayed_job를 업데이트합니다.

    나는 작업의 진행 상황을 추적, 나는 / 주어진 작업에서 수행 전화를 여러 번 반대하고 파괴적인 행동을 다시 적용되지 않습니다 확신 할 수 있도록 프로세스 나무 등을 할 수있는 상태 머신을 사용합니다. 그런 다음 TERM에 로그를 해제 레이크 작업 / delayed_job를 업데이트합니다.

    프로세스가 다시 시작되면 의도 한대로는 계속 될 것이다.

  7. from https://stackoverflow.com/questions/10438100/long-running-delayed-job-jobs-stay-locked-after-a-restart-on-heroku by cc-by-sa and MIT license