2016-09-22 17 views
1

状況:AWSシンプルなワークフローサービス - 実行長い実行中のプロセスに確実

私は長い間実行されているマニュアルの活動を調整するためにAWS SWFを使用します。 AWSでアクティビティがスケジュールされているとき、私はどのタスクが保留中であるかをUIに示すためにDBに転送します。これらのタスクには数週間かかることがあり、SWFには大きなタイムアウトがあります。

問題:とき外活動時間

私のアプリケーションは、DB(ハングやエラーを報告せずに死ぬ)を投入するために失敗した場合は、その後、タスクは、人と再試行によって見られていないだけで、数週間後に発生する可能性があります(これは明らかに容認できない)。

質問:

だから私は、タスクを「開始」(30秒のタイムアウトを持つと言う)と、アプリケーションが活動が今週にタイムアウトを設定開始されていることを確認したときにする能力を持っているしたいと思います。 SWFを使ってエレガントにすることは本当に可能ですか?

(私はDOCといくつかの例を読んできたし、今でも手作業を実行しているの想定方法が何であるかを理解していない)

答えて

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を送信し、タイマーキャンセルをこのように調整する必要があることに気が付いたので、複数の手動アクティビティを調整することができます。 –

関連する問題