残念ながら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);
}
}
ありがとう!残念ながら、この回避策は私の場合は不便ですが、タイマー+シグナルを使用して複数の並列マニュアルプロセスを調整するのは難しいでしょう。 –
複雑ではなく、よく定義されたクラスにカプセル化することができます。あなたがそれを実装する際に助けが必要な場合は、私に直接pingしてください。 –
私は、手動タスクでタイマーIDを送信し、タイマーキャンセルをこのように調整する必要があることに気が付いたので、複数の手動アクティビティを調整することができます。 –