异步写入appengine blob并在所有任务完成时完成它

时间:2012-01-25 01:20:07

标签: google-app-engine mapreduce blobstore task-queue

我遇到了一个棘手的问题。

我正在迭代一组按日期参数化的URL并获取它们。例如,以下是一个示例:

somewebservice.com?start=01-01-2012&end=01-10-2012

有时,从URL返回的内容会被截断(缺少附加'截断错误'消息的随机结果),因为我已经定义了太大的范围,所以我必须将查询拆分为两个URL

somewebservice.com?start=01-01-2012&end=01-05-2012

somewebservice.com?start=01-06-2012&end=01-10-2012

我递归执行此操作,直到结果不再被截断,然后我写入一个允许并发写入的blob。

这些URL提取调用/ blob写入中的每一个都在单独的任务队列任务中处理。

问题是,我不能为我的生活设计一个方案来了解所有任务何时完成。我尝试过使用分片计数器,但递归使得它变得困难。有人建议我使用Pipeline API,所以我看了3次Slatkin谈话。它似乎不适用于递归(但我承认我仍然不完全理解lib)。

反正知道什么时候完成一组任务队列任务(以及递归生成的子项),所以我可以完成我的blob并用它做任何事情?

谢谢, 约翰

2 个答案:

答案 0 :(得分:2)

您是否阅读过Pipelines Getting Started个文档?管道可以创建其他管道并等待它们,所以做你想要的是相当简单的:

class RecursivePipeline(pipeline.Pipeline):
  def run(self, param):
    if some_condition: # Too big to process in one
      p1 = yield RecursivePipeline(param1)
      p2 = yield RecursivePipeline(param2)
      yield RecursiveCombiningPipeline(p1, p2)

其中RecursiveCombiningPipeline只是作为两个子管道值的接收器。

答案 1 :(得分:0)

好的,所以这就是我的所作所为。我不得不稍微修改Mitch的解决方案,但他确实让我朝着正确的方向前进,提出了返回未来价值的建议而不是直接的价值。

我必须创建一个intermidate DummyJob,它接受递归的输出

   public static class DummyJob extends Job1<Void, List<Void>> {
      @Override
      public Value<Void> run(List<Void> dummies) {
         return null;
      }
   }

然后,我将DummyJob的输出提交给waitFor

中的Blob Finalizer
List<FutureValue<Void>> dummies = new ArrayList<FutureValue<Void>>();
for (Interval in : ins) {
   dummies.add(futureCall(new DataFetcher(), immediate(file), immediate(in.getStart()),
         immediate(in.getEnd())));
}

FutureValue<Void> fv = futureCall(new DummyJob(), futureList(dummies));

return futureCall(new DataWriter(), immediate(file), waitFor(fv));

谢谢Mitch和Nick !!