facade.vote(datastoreRecordId, userId);
try{
facade.vote(datastoreRecordId, userId);
fail(); // Expect runtimeexception because voting twice is not allowed
} catch (RuntimeException ex) {}
hasVoted = facade.hasVoted(datastoreRecordId, userId);
我有一个单元测试,测试我的gae服务器的外观。 服务器在localhost上运行,每次在安装方法中擦除数据存储区。
我将一个实体放入数据存储区,然后我基本上检查它是否正确持久化!有时它会告诉我记录被发现,有时它告诉我它没有找到。 (所以hasVoted有时是真的,有时是假的,有时会抛出预期的运行时异常,有时不会抛出)
我尝试使用全局事务,本地同步和服务器端,并尝试使用单线程HttpClient。我甚至在打电话到我的门面之间睡了一些。我还尝试了appengine.xml中的线程切换。
我已经制作了一个方法,我连续100次运行测试,有时它可以工作,有时断言失败后有时在7次之后运行4次(16是记录wohoo)它是完全随机的。我只是无法找出问题所在。当我在远程appengine实例上运行测试时,一切正常,即使我在循环中运行100次。除格式c以外的任何想法:?
好吧,我发现了这个问题,我禁用了HRD并在本地转移到Master / Slave,现在一切正常!也许这篇文章可以帮助将来的某个人。任何人都理解HRD的这种行为吗?
答案 0 :(得分:2)
HRD为"eventually consistent",这意味着当您编写实体时,它会异步发生:写入方法在数据实际持久存储在数据存储区之前返回。因此,如果您在写入后立即查询实体,则可能找不到它。
为什么会这样?数据存储需要一段时间才能持久化并创建索引 - 请阅读Life of a Datastore Write。
注意:HRD的“最终一致性”仅影响查询。如果您put()
然后get()
,您应始终获得该实体。
因此,只有在使用查询时才会出现您遇到的问题。此外,此问题也应出现在生产服务器上(但您可能不会在测试设置下遇到它)。