setDefaultHighRepJobPolicyUnappliedJobPercentage(100)真的有效吗?

时间:2015-01-01 15:54:24

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

根据https://cloud.google.com/appengine/docs/java/tools/localunittesting#Writing_HRD_Datastore_Tests,“如果您的应用使用高复制数据存储(HRD),您可能需要编写测试来验证应用程序在最终一致性方面的行为.LocalDatastoreServiceTestConfig公开了使这一过程变得简单的选项。 “你应该设置setDefaultHighRepJobPolicyUnappliedJobPercentage(100),然后,“通过将未应用的作业百分比设置为100,我们指示本地数据存储区以最大的最终一致性进行操作。最大的最终一致性意味着写入将提交但总是失败要应用,所以全局(非祖先)查询将始终无法看到更改。“

但是,我认为setDefaultHighRepJobPolicyUnappliedJobPercentage(100)不起作用。

如果确实如此,那么我的下面的测试用例testEventualConsistency()应该通过,但它在第二个断言失败了。在第一个断言中,我使用Objectify ancestor()查询读回了我保存的对象。它的工作原理是因为检索了对象。但是,第二个断言失败了。在那个断言中我还读回了我保存的对象,但是我没有使用Objectify ancestor()查询,所以它不应该检索任何东西,因为我已经指定不应该完成任务(即{{1设置)。

EventualConsistencyTest测试用例

setDefaultHighRepJobPolicyUnappliedJobPercentage(100)

用户定义

import static com.googlecode.objectify.ObjectifyService.begin;
import static com.googlecode.objectify.ObjectifyService.ofy;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

import java.util.List;

import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.util.Closeable;
import com.netbase.followerdownloader.model.DownloadTask;
import com.netbase.followerdownloader.model.User;

public class EventualConsistencyTest {
    private final LocalServiceTestHelper helper =
            new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
                .setDefaultHighRepJobPolicyUnappliedJobPercentage(100));    

    @Test
    public void testEventualConsistency() {
        helper.setUp();
        ObjectifyRegistrar.registerDataModel();

        User user = new User();
        user.id = 1L;
        Closeable closeable1 = begin();
        ofy().save().entity(user);
        closeable1.close();

        Closeable closeable2 = begin();
        DownloadTask downloadTask = new DownloadTask();
        downloadTask.owner = Ref.create(user);
        ofy().save().entity(downloadTask);
        closeable2.close();

        Closeable closeable3 = ObjectifyService.begin();
        List<DownloadTask> downloadTasks1 = ofy().load().type(DownloadTask.class).ancestor(user).list();
        assertThat(downloadTasks1.size(), equalTo(1));
        closeable3.close();

        Closeable closeable4 = ObjectifyService.begin();
        List<DownloadTask> downloadTasks2 = ofy().load().type(DownloadTask.class).list();
        assertThat(downloadTasks2.size(), equalTo(0));  //  THIS SHOULD PASS IF setDefaultHighRepJobPolicyUnappliedJobPercentage(100) WORKED
        closeable4.close();

        helper.tearDown();
    }

}

DownloadTask定义

import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;

@Entity
public class User {
    @Id public Long id;

    public User () {

    }
}

环境:

  • 应用服务引擎的API-1.0-SDK-1.9.17.jar
  • 应用服务引擎测试-1.9.17.jar
  • 应用服务引擎的API存根-1.9.17.jar
  • 的junit-4.11.jar
  • 物化-5.1.3.jar

如果我错过了其他重要的事情,这里有一个更详尽的清单:

Environment

我的问题是:

  1. import com.googlecode.objectify.Ref; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Parent; @Entity public class DownloadTask { @Id public Long id; @Parent public Ref<User> owner; public DownloadTask() { } } 是否已损坏?

  2. setDefaultHighRepJobPolicyUnappliedJobPercentage(100)是否真的没有记录?它实际上是否适用于该工作,即使文档说它不应该?

  3. 传递给setDefaultHighRepJobPolicyUnappliedJobPercentage(100)的值是否真的应该是setDefaultHighRepJobPolicyUnappliedJobPercentage()而不是让我们说100

  4. Objectify祖先查询是否真的没有记录?

1 个答案:

答案 0 :(得分:1)

https://cloud.google.com/appengine/docs/java/tools/localunittesting#Java_Writing_High_Replication_Datastore_tests的观察结果解释了这个问题: “在本地环境中,执行属于具有未应用写入的实体组的实体的get()将始终使未应用写入的结果对后续全局查询可见。”

在本文中,这意味着祖先查询:

List<DownloadTask> downloadTasks1 = ofy().load().type(DownloadTask.class).ancestor(user).list();

在内部“执行get()属于具有未应用写入的实体组的Entity”会影响紧随其后的全局查询的行为:

List<DownloadTask> downloadTasks2 = ofy().load().type(DownloadTask.class).list();

为了避免您的测试相互影响,特别是以这种方式相互干扰,最好每个测试操作使用一个单独的方法(每个都有所有需要的设置和拆卸部分),而不是在单一测试方法中连续进行的测试操作。