对象化事务和多线程任务无法在本地开发服务器中正常工作

时间:2018-11-24 12:52:47

标签: java google-app-engine google-cloud-datastore objectify

在本地应用程序引擎dev-server上使用对象化事务和GAE任务时,我遇到了一个问题。

我想做的是以并行方式处理一个巨大的csv文件(将数据解析并写入其他地方)。为此,第一个servlet负责:

  • 在数据存储区上存储一个Job实体,该实体标识整个工作单元并跟踪总块和已处理块。
  • 将大型csv切成小块。对于每个对象,在以Job为父对象的数据存储区中存储一个Chunk实体(使用@parent注释)
  • 一旦拆分完成,servlet将启动与已创建的块一样多的任务。

每个任务都要处理其较小的csv块对象。

现在,出现问题。为了确定何时正确处理了所有块,我希望最后一个产生另一个任务,以完成一些工作。

这样做的目的是使用事务,以确保每个完成的块处理都增加Job实例上的计数器,以便最后一个实例可以启动最终任务。

但是,这不起作用。我已经尝试过将Job分成7个块,似乎最后两个块是同时处理的(很好!),但是它们两个都成功(使用不同的时间)。可以想象,这两个任务在处理的块数为5时开始执行,并且都尝试将6设置为处理的块。我期望发生的是,退出事务时,其中之一失败,并且只有一个应该能够更新父对象上的处理后的块值。因此,下次重试时,块计数从6开始,而不是从5开始。

因此,为方便起见,这是执行的代码。

items = []

categories = Category.objects.all()
for category in categories:
    items.extend(list(Item.objects.filter(category=category)[:10]))

以下是输出(仅具有Thread指示的相关部分):

// import static com.googlecode.objectify.ObjectifyService.ofy;
// ...
// ...
// Perform the data manipulation on the Chunk
// ...
// Load the parent job from Datastore
// job = ...

// Check if there still are valid chunks to process. If not, we are done!
ImportJob fctUpdatedJob = ofy().transact(() -> {
    long threadId = Thread.currentThread().getId();
    log.info("T{}: Transaction started", threadId);

    ImportJob updatedJob = ofy().load().key(Key.create(ImportJob.class, job.getId())).now();
    log.info("T{}: loaded job {}", threadId, updatedJob);

    int processedChunks = updatedJob.getProcessedChunks() + 1;
    updatedJob.setProcessedChunks(processedChunks);
    updatedJob.setTotalChunkSeconds(updatedJob.getTotalChunkSeconds() + seconds);

    // TODO Double check this stop condition
    if (processedChunks == updatedJob.getTotalChunks() && !updatedJob.isDisposing()) {
        updatedJob.setDisposing(true);
    }

    ofy().save().entity(updatedJob).now();
    log.info("T{}: job saved. Job: {}", threadId, updatedJob);

    return updatedJob;
});

if (job.getProcessedChunks()==job.getTotalChunks()) {
    // We are done!
    // Launch the final task
}

如您所见,T22以5个已处理的块开头,将其保存为6,然后T20从5再次开始,并将其保存为6。因此,处理条件unks == totalChunks永远不会发生。

我正在本地AppEngine开发服务器上使用objectify版本5.1.6,并且在我的appengine-web.xml中启用了该选项。

我在这里想念什么?

0 个答案:

没有答案