繁体   English   中英

AWS Simple Workflow Service - 可靠地运行长时间运行的流程

[英]AWS Simple Workflow Service - run long running processes reliably

情况:

我想使用AWS SWF来协调长时间运行的手动活动。 在AWS中调度活动时,我将其传输到DB以在UI上显示哪些任务正在等待处理。 这些任务可能需要数周才能完成,因此它们在SWF中会有很长的时间。

问题:

如果我的应用程序无法填充数据库(挂起或死亡而没有报告任何错误),那么一个人看不到任务,并且只有在活动超时(这显然是不可接受的)数周之后才能进行重试。

题:

所以我希望能够“启动”任务(比如说超时为30秒),当应用程序确定活动现在已经开始时,将超时设置为几周。 是否真的可以使用SWF优雅地完成它?

(我已经阅读了doc和几个例子,但仍然不明白运行手动任务的设想方式是什么)

不幸的是,SWF服务不支持“启动活动任务”API调用。 我使用的解决方法是使用具有短超时的活动将记录插入到数据库中。 然后关于它的手动任务完成信号工作流程。 需要一个单独的计时器来处理手动任务超时。 所有这些逻辑都可以封装在一个单独的类中以供重用。

使用信号的附加好处是手动任务通常具有多个状态。 例如,可以在声明任务并稍后释放任务时发信号通知工作流。 每个州都可以有不同的超时。

[编辑:添加了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);
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM