我是AWS SWF的新手,我的任务是在第一次尝试活动失败时发出通知(通过电子邮件)。我使用Settable<Boolean>
作为我的标志但该值不可靠,因为工作流程正在运行异步。这是我的代码:
final AsyncExecutor asyncExecutor = new AsyncRetryingExecutor(retryPolicy, workflowClock);
final Settable<Boolean> notifyException = new Settable<>();
new TryCatch() {
@Override
protected void doTry() throws Throwable {
asyncExecutor.execute(() -> new TryCatch() {
@Override
protected void doTry() throws Throwable {
Promise<ActivityOne> activityOne = activityOneClient.performAction(activityOneRequest);
}
@Override
protected void doCatch(Throwable e) throws Throwable {
if (!notifyException.isReady()) {
// PERFORM notification service here!!
notifyException.set(true);
} else {
// DO NOTHING. Notification is already sent the first time :)
}
throw e;
}
});
}
@Override
protected void doCatch(Throwable e) throws Throwable {
System.out.println("======");
System.out.println("CATCH ALL!! " + e.getMessage());
System.out.println("======");
}
};
即使我在notifyException
内明确将其值设置为true
,if statement
的值也会一直在变化。我的代码的结果是它将执行notification service
以上的多个。
==== UPDATE ===
final AsyncExecutor asyncExecutor = new AsyncRetryingExecutor(retryPolicy, workflowClock);
final Settable<Boolean> notifyException = new Settable<>();
new TryCatch() {
@Override
protected void doTry() throws Throwable {
asyncExecutor.execute(() -> new TryCatch() {
@Override
protected void doTry() throws Throwable {
Promise<ActivityOne> activityOne = activityOneClient.performAction(activityOneRequest);
}
@Override
protected void doCatch(Throwable e) throws Throwable {
if (!notifyException.isReady()) {
activityOneClient.notify();
notifyException.set(true);
}
throw e;
}
});
}
@Override
protected void doCatch(Throwable e) throws Throwable {
System.out.println("======");
System.out.println("CATCH ALL!! " + e.getMessage());
System.out.println("======");
}
};
当我重新抛出异常时,activityOneClient.notify()
只会在asyncExecutor
的最后一次重试时执行,所以如果我不重新抛出,activityOneClient.notify()
将自动执行。我只需要在第一次发生异常时通知。
答案 0 :(得分:2)
代码看起来没问题(没有运行它)。
你的问题在别的地方。流框架的工作方式是每次有工作要做工作流工作者或活动工作人员接收任务,运行它并报告结果。报告结果意味着在工作流历史记录中捕获执行结果。
每当历史记录发生变化时,决策者(工作流程)工作人员就会运行,并决定接下来会发生什么。在封面下,决策者只需重播所有历史记录,并从一开始就作出所有决定。现在,它的决定与决策者在历史中所做的事情相匹配,直到它遇到新事物为止。
简单的例子。假设你有一个包含3个步骤的工作流程:
[请记住,乘法活动可以同时运行,如果活动输出和输入之间没有链接,流程框架将向前移动并并行安排多个事物。保持简单,以便你得到这个想法]
当T0工作流程开始时没有历史记录,决策程序运行并且activity1已安排。
在T1,activity1工作人员接收任务,执行并报告结果。
在T2作为activity1更新历史记录的结果,决定者被安排并运行+它读取历史记录。它看到activity1应该运行,它在历史记录中看到它,它看到它已完成,它会调度activity2
在T3,activity2工作人员接受任务,执行并报告结果。
在T4作为activity2更新历史记录的结果,决定者被安排并运行+它读取历史记录。它看到activity1应该运行,它在历史中看到它,它看到它完成了。它现在看到activity2应该运行,它在历史中看到它,它看到它已经完成并转移到activity3。它安排活动3。
等等。
你的问题是,每当决策程序运行(每个决定)时,决定流量的决策程序中的代码都会运行。因此,当决策程序到达该活动时,它将看到它已经运行并抛出异常,它将通过设置标志的代码+发送电子邮件。
当指数重试时,标志将被设置,但发送电子邮件的代码将在每个决策上运行(决策程序基本上是无状态的,状态是根据历史记录构建的)。
在这种特殊情况下你可以做的是移动发送电子邮件的部分进行自己的活动。通过这种方式,决策者将在历史中看到它并快进,而不是每次都运行它。
答案 1 :(得分:0)
要仅通知抛出的第一个异常,我所做的是:
@Override
protected void doTry() throws Throwable {
asyncExecutor.execute(() -> new TryCatchFinally() {
Throwable throwable = null;
@Override
protected void doTry() throws Throwable {
Promise<ActivityOne> activityOne = activityOneClient.performAction(activityOneRequest);
}
@Override
protected void doCatch(Throwable e) throws Throwable {
if (!notifyException.isReady()) {
activityOneClient.notify();
notifyException.set(true);
}
throwable = e;
}
@Override
protected void doFinally() throws Throwable {
if (throwable != null) {
throw throwable;
}
}
});
}