setDefaultHighRepJobPolicyUnappliedJobPercentage(100) 真的有效吗?

Does setDefaultHighRepJobPolicyUnappliedJobPercentage(100) really work?

根据 https://cloud.google.com/appengine/docs/java/tools/localunittesting#Writing_HRD_Datastore_Tests,"If your app uses the High Replication Datastore (HRD), you may want to write tests that verify your application's behavior in the face of eventual consistency. LocalDatastoreServiceTestConfig exposes options that make this easy." 你应该设置 setDefaultHighRepJobPolicyUnappliedJobPercentage(100) 然后 "By setting the unapplied job percentage to 100, we are instructing the local datastore to operate with the maximum amount of eventual consistency. Maximum eventual consistency means writes will commit but always fail to apply, so global (non-ancestor) queries will consistently fail to see changes."

不过,我认为 setDefaultHighRepJobPolicyUnappliedJobPercentage(100) 行不通。

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

EventualConsistencyTest 测试用例

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();
    }

}

用户定义

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

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

    public User () {

    }
}

下载任务定义

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() {

    }
}

环境:

如果我遗漏了任何其他重要内容,这里有一个更详尽的列表:

我的问题是:

  1. setDefaultHighRepJobPolicyUnappliedJobPercentage(100)坏了吗

  2. setDefaultHighRepJobPolicyUnappliedJobPercentage(100) 是否真的没有记录的那样有效?它是否真的适用于这份工作,即使文档说它不应该适用?

  3. 传递给 setDefaultHighRepJobPolicyUnappliedJobPercentage() 的值真的应该是 100 而不是 1.0f?

  4. Objectify 祖先查询是否真的如记录的那样工作?

这个问题可以通过 https://cloud.google.com/appengine/docs/java/tools/localunittesting#Java_Writing_High_Replication_Datastore_tests 的观察来解释: "In the local environment, performing a get() of an Entity that belongs to an entity group with an unapplied write will always make the results of the unapplied write visible to subsequent global queries."

在这种情况下,这意味着祖先查询:

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

在内部 "performs a get() of an Entity that belongs to an entity group with an unapplied write" 影响紧随其后的全局查询的行为:

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

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