跨组事务需要在get_or_insert上明确指定异常

时间:2016-04-08 02:31:48

标签: google-app-engine transactions

我们正在从文件中加载电子邮件列表,同时为每个电子邮件地址同时放置大量数据存储区实体,并在表单中偶尔出现错误:

BadRequestError: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXG

失败的Python方法调用:

EmailObj.get_or_insert(key_name=email, source=source, reason=reason)

其中email是地址字符串,源和原因是StringProperties。

问题:get_or_insert调用如何为一个简单的数据存储模型启动事务(2个字符串属性)并获取涉及不同组的实体?我希望上面的方法应该读取匹配给定键的现有对象或存储新实体。

1 个答案:

答案 0 :(得分:2)

注意:我不知道确切的内部实现,这只是一个理论......

由于您没有指定父母,因此没有实体组可以从一开始就被锁定" /建立为 组,交易将仅限于。

get_or_insert操作通常是检查具有该键名的实体是否存在,如果不存在,则创建新实体。如果没有父母,这个新实体将在其自己的群组中,让我们称之为new_group

现在要完成与get_or_insert自动关联的事务,需要进行冲突检查。 冲突意味着具有相同键名的实体是由其中一个并发任务创建的(在我们检查此类实体存在但在我们的事务结束之前),哪个实体也有自己的不同的组,我们称之为other_group

此冲突检查仅在冲突真实的情况下才会有效地访问new_groupother_group,从而导致异常。

通过指定父级,问题不存在,因为new_groupother_group实际上都是同一个组 - 父组。 get_or_insert交易将仅限于此群组。

我认为,即使在生产中,这个理论也可以得到验证(如果理论是正确的,那么错误实际上是无害的 - 地址毕竟是重复的)

第一步是确认发生的事件与在短时间内插入两次的相同电子邮件地址有关 - 很简单。

包装在try /除异常之外并记录相应的电子邮件地址,然后根据输入文件进行检查 - 它们应该是重复的,我想在文件中彼此非常接近。

然后你可以强迫这种情况 - 故意每5-10封电子邮件(或你认为相关的其他速率)插入重复的地址。

根据应用程序的实际实现方式,您可以在输入文件中插入重复项,或者,如果使用任务 - 创建/排队重复任务,或者只需调用get_or_insert两次(不确定是否为最后一项)会有效,因为它可能发生在同一个线程/实例上)。最终记录或跟踪注入的重复地址

异常的出现率现在应该增加,可能与强制重复插入率成比例。大多数(如果不是全部)相应的记录地址应该与正在注入的跟踪重复项匹配。

如果你到目前为止确认了触发的重复条目。剩下要确认的是同一个电子邮件地址的不同实体组 - 我无法想出确切地检查这一点的方法,但我也无法想到与该重复相关的其他一些组电子邮件地址。

无论如何,只需在xg=True来电中添加get_or_insert即可。 context options如果我的理论是正确的,错误应该消失:)