2016-09-22 3 views
1

상황 :AWS 간단한 워크 플로우 서비스 - 실행 장기 실행 프로세스 신뢰성

내가 오랫동안 실행 매뉴얼 활동을 조정하기 위해 AWS SWF를 사용하고 싶습니다. AWS에서 활동을 예약 할 때 대기중인 작업이 무엇인지 UI에 표시하기 위해 DB로 전송합니다. 이러한 작업을 완료하는 데 몇 주가 걸릴 수 있으므로 SWF에 시간 제한이 있습니다.

문제 : 내 응용 프로그램 DB 채우는 데 실패 (일시 중단 또는 오류를보고하지 않고 사망)의 경우

는 다음 작업이, 사람이 볼 만 주 후에 일어날 수있는 다시 시도하지 않을 때 활동 시간 초과 (이것은 분명히 받아 들일 수 없다).

질문 : 응용 프로그램이 해당 활동이 주로 설정 타임 아웃을 시작 지금되었는지 때

그래서 내가 작업을 "시작"할 수있는 능력을 가지고 싶은는 (30 초 타임 아웃을 가진 말)합니다. SWF를 사용하여 우아하게 처리 할 수 ​​있습니까?

(나는 의사와 몇 가지 예를 통해 읽은 여전히 ​​수동 작업을 실행하는 상상 방법이 무엇인지 이해하지 못하는)

답변

3

는 불행하게도 SWF 서비스가 지원 API 호출 "활동 작업을 시작"하지 않습니다. 내가 사용하는 임시 해결책은 DB에 레코드를 삽입하기 위해 짧은 시간 제한의 활동을 사용하는 것이 었습니다. 그런 다음 수동 작업 완료시 워크 플로 신호를 보냅니다. 수동 작업 제한 시간을 처리하려면 별도의 타이머가 필요했습니다. 이 모든 논리는 재사용을 위해 별도의 클래스로 캡슐화 될 수 있습니다.

신호를 사용하는 데 추가 된 이점은 수동 작업이 일반적으로 둘 이상의 상태를 갖는다는 것입니다. 예를 들어 작업 흐름을 주장하고 나중에 다시 릴리스 할 때 워크 플로에 신호를 보낼 수 있습니다. 각 상태는 다른 시간 초과를 가질 수 있습니다.

[편집 : 추가 strawman ManualActivityClient 예]

public class ManualActivityClient { 

    private final Map<String, Settable<Void>> outstandingManualActivities = new HashMap<>(); 

    private StartManualActivityClient startActivityClient; 
    private WorkflowClock clock; 

    public Promise<Void> invoke(String id, String activityArgs, long timeout) { 
     Promise<Void> started = startActivityClient.start(id, activityArgs); 
     Settable<Void> completionPromise = new Settable<>(); 
     outstandingManualActivities.put(id, completionPromise); 
     // TryFinally is used to define cancellation scope for automatic timer cancellation. 
     new TryFinally() { 
      @Override 
      protected void doTry() throws Throwable { 
       // Wrap timer invocation in Task(true) to give it daemon flag. Daemon tasks are automatically 
       // cancelled when all other tasks in the same scope (defined by doTry) are done. 
       new Task(true) { 
        @Override 
        protected void doExecute() throws Throwable { 
         Promise<Void> manualActivityTimeout = clock.createTimer(timeout); 
         new Task(manualActivityTimeout) { 
          @Override 
          protected void doExecute() throws Throwable  { 
           throw new TimeoutException("Manual activity " + id + " timed out"); 
          } 
         }; 
        } 
       }; 
       // This task is used to "wait" for manual task completion. Without it the timer would be 
       // immediately cancelled. 
       new Task(completionPromise) { 
        @Override 
        protected void doExecute() throws Throwable { 
         // Intentionally empty 
        } 
       }; 
      } 

      @Override 
      protected void doFinally() throws Throwable { 

      } 
     }; 
     return completionPromise; 
    } 

    public void signalManualActivityCompletion(String id) { 
     // Set completionPromise to ready state 
     outstandingManualActivities.get(id).set(null); 
    } 
} 

그리고이 클래스로 사용할 수 있습니다 : 위대한 답변

@Workflow(...) 
public class ManualActivityWorkflow { 

    private ManualActivityClient manualActivityClient; 

    @Execute(...) 
    public void execute() { 
     // ... 
     Promise<Void> activity1 = manualActivityClient.invoke("activity1", "someArgs1", 300); 
     Promise<Void> activity2 = manualActivityClient.invoke("activity2", "someArgs2", 300); 

     // ... 
    } 

    @Signal(...) 
    public void signalManualActivityCompletion(String id) { 
     manualActivityClient.signalManualActivityCompletion(id); 
    } 

}

+0

감사합니다! 불행히도이 해결 방법은 타이머 + 신호를 사용하여 여러 개의 병렬 수동 프로세스를 조정하는 것이 어려워서 제 경우에는 불편합니다. –

+0

복잡하지 않고 잘 정의 된 클래스로 캡슐화 될 수 있습니다. 그것을 구현하는 데 도움이 필요하면 직접 ping하십시오. –

+0

수동 작업으로 타이머 ID를 보내고 타이머 취소를 이런 방식으로 조정해야하므로 여러 수동 작업을 조정할 수 있다는 것을 알았습니다. –