不幸的是,SWF服務不支持「啓動活動任務」 API調用。我使用的解決方法是使用短超時的活動將記錄插入到數據庫中。然後根據手動任務完成信號工作流程。需要一個單獨的計時器來處理手動任務超時。所有這些邏輯都可以封裝在一個單獨的類中供重用。
使用信號增加的好處是手動任務通常具有多個狀態。例如,工作流可以在任務被聲明並且隨後被釋放時發信號通知。每個狀態可以有不同的超時時間。
[編輯:添加稻草人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);
}
}
感謝偉大的答案!不幸的是,我發現這種解決方法不便於我的情況,因爲使用定時器+信號很難協調多個並行手動過程。 –
它並不複雜,可以封裝在一個明確定義的類中。如果您在實施過程中需要幫助,請直接與我聯繫。 –
我意識到我需要發送一個手動任務的定時器ID,並以這種方式協調定時器取消,因此可以協調多個手動活動。 –