4

以下简单的模式是否足以确保即使在应用程序更新或硬的、“不稳定的”谷歌故障之后任务序列也不会停止。

def do_work():
    ... .... 

    deferred.defer(do_work, _countdown=..in 7 days..)

我可以安排这样一个自我调度的工人并且永不回头吗?

4

2 回答 2

2

两个答案:

是的,任务最终会执行,并且在任务执行出错的情况下也会重试执行。定义任务时设置重试选项。

不,任务队列不是调度程序,因此您不能安排任务在特定时间运行。放入任务队列的任务会立即以 FIFO 方式提供服务。

正如@Jesse 所指出的,对于安排作业,您应该查看 GAE cron。

于 2012-09-08T14:00:12.400 回答
1

如果一个任务成功排队,它最终会执行。(只要需要,App Engine 将继续尝试。)

不过,您展示的模式可能会更好地使用cron jobs来实现,它会定期运行任务。我使用的一个常见模式是让每日 cron 作业在任务队列上启动一个任务,重试次数很少(这样如果出现临时故障,它将立即重试)。

如果你确实想使用上面的方法,而不是 cron,还有另一件事需要担心:因为你的方法可能会因为它失败或其他系统问题(例如运行它的实例宕机)而被重试,你应该确保你不要以两个任务结束。想象一下,如果它运行了,注册了下一个任务,然后节点宕机了;App Engine 将重试,开始第二个任务。为了防止这种情况,您可以使用数据存储(在事务中)来测试并查看下一个任务是否已经入队。就像是:

def do_work(counter):
    ...

    @db.transactional
    def start_next():
        # fetch myModel from the data store here
        if myModel.counter == counter:
            return # already started next job
        myModel.counter = counter
        myModel.put()
        deferred.defer(do_work, counter + 1, _transactional=True, _countdown=...)

    start_next()

注意 defer 调用中的“事务”参数;这确保了当且仅当下一个任务入队时才会更新 MyModel 实例。

您可能还想考虑在一定次数的重试失败后向管理员发送电子邮件。(您可以在请求 HTTP 标头中找到它,但如果您想这样做,则不能使用延迟库;您必须直接使用任务队列 API。)

于 2012-09-08T13:39:01.100 回答