AWS SWF在特定条件下重新启动工作流程

时间:2016-08-22 20:54:54

标签: java amazon-web-services amazon-swf

我有一个SWF工作流程和活动。以下是结构:

WorkflowClientImpl类:

const userReducer = function(userInfo = {}, action){
  switch(action.type){
    case 'UPDATE_FIRST_NAME':
      return {
        ...userInfo,
        firstName: action.firstName
      }

    case 'UPDATE_LAST_NAME':
      return {
        ...userInfo,
        lastName: action.lastName
      }

    case 'UPDATE_BIRTH_MONTH':
      return {
        ...userInfo,
        birthMonth: action.birthMonth
      }

    case 'UPDATE_BIRTH_DAY':
      return {
        ...userInfo,
        birthDay: action.birthDay
      }

    case 'UPDATE_BIRTH_YEAR':
      return {
        ...userInfo,
        birthYear: action.birthyear
      }

    default:
      return userInfo
  }
}

export default userReducer

ActivityClientImpl类:

 class TempWorkflowImpl() {
     @Override 
     public void execute() {
           new TryCatchFinallly {
                 @Override
                 protected void doTry() throws Throwable {
                        activityClient.invoke();
                 }
                 @Override
                 protected void doFinally() throws Throwable {
                        // Clean up code
                 }
                 @Override
                 protected void doCatch() throws Throwable {
                        // Handle Exception
                 }                    
           }
     } 
 }

activity类进行API调用,这是一个异步方法。 API调用中定义的操作大约需要一个小时才能完成。有时,由于某些原因,操作在执行时可能会失败。此API调用是在我无权访问的服务上定义的。 有没有办法让我可以睡觉活动,这样它可以在一小时后检查动作是否成功。如果不成功,我将重新调用API调用。让我们假设这次操作将成功,我们不会在API调用尝试的无限循环中结束。

class TempActivityImpl() { @Override public void invoke() { // Perform some logic // Check if API call (API_Call_A) is made previously // If not Invoke API_Call_A. // If yes, throw exception } } 似乎是单向的,但我不确定这是最合适的方式。我还发现我们可以使用

重新启动整个工作流程
Thread.sleep()

要使用上述内容,我可以在API调用后从activity方法返回 Promise<Void> timer = decisionContextProvider.getDecisionContext().getWorkflowClock().createTimer(TimeUnit.MINUTES.toSeconds(TimeinMinutes)); continueAsNew(timer); 的值,然后在一小时后重新启动工作流。

上述方法最合适吗?或者有更好的方法吗?

由于

1 个答案:

答案 0 :(得分:1)

除非您的工作流程历史很长(例如在调用活动100次后),否则无需调用continueAsNew。只需使用@Asynchronous方法或Task来等待promises。我将您的工作流建模为两个活动:invoke和checkResult并在延迟后执行checkResult并使用@ExponentialResult重试它直到结果可用。

class TempWorkflowImpl() {
   private final WorkflowClock clock = decisionContextProvider.getDecisionContext().getWorkflowClock()
   @Override 
   public void execute() {
       new TryCatchFinallly {
             @Override
             protected void doTry() throws Throwable {
                   invoke();
             }
             @Override
             protected void doFinally() throws Throwable {
                    // Clean up code
             }
             @Override
             protected void doCatch() throws Throwable {
                    // Handle Exception
             }                    
       }
   } 

   @Asynchronous
   // On ServiceFailureException retry from the beginning
   @ExponentialRetry(initialRetryIntervalSeconds=300, exceptionsToRetry=ServiceFailureException.class) 
   private Promise<ResultType>  invoke() {
                    Promise<Void> invoked = activityClient.invoke();
                    Promise<ResultType> result = checkResultAfterDelay(invoked);
                    processResult(result);
   }

   @Asynchronous
   private Promise<ResultType>  checkResultAfterDelay(Promise<Void> invoked) {
      Promise<Void> timer = clock.createTimer(TimeUnit.MINUTES.toSeconds(60));
      return checkResult(timer);
   }

   @Asynchronous
   // Automatically retry on ResultUnavailableException
   @ExponentialRetry(initialRetryIntervalSeconds=300, exceptionsToRetry=ResultUnavailableException.class) 
   private Promise<ResultType> checkResult(Promise<Void> timer) {
      return activityClient.checkResult();
   }

   @Asynchronous
   private processResult(Promise<ResultType>  result) {
     ....
   }

}