以下简单的模式是否足以确保即使在应用程序更新或硬的、“不稳定的”谷歌故障之后任务序列也不会停止。
def do_work():
... ....
deferred.defer(do_work, _countdown=..in 7 days..)
我可以安排这样一个自我调度的工人并且永不回头吗?
以下简单的模式是否足以确保即使在应用程序更新或硬的、“不稳定的”谷歌故障之后任务序列也不会停止。
def do_work():
... ....
deferred.defer(do_work, _countdown=..in 7 days..)
我可以安排这样一个自我调度的工人并且永不回头吗?
两个答案:
是的,任务最终会执行,并且在任务执行出错的情况下也会重试执行。定义任务时设置重试选项。
不,任务队列不是调度程序,因此您不能安排任务在特定时间运行。放入任务队列的任务会立即以 FIFO 方式提供服务。
正如@Jesse 所指出的,对于安排作业,您应该查看 GAE cron。
如果一个任务成功排队,它最终会执行。(只要需要,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。)