2012年9月1日土曜日

[AppEngine] Eventual ということ。

前回の記事で、データの追加、削除、更新、取得をやってみた。
一応動くのだが、たまに表示される結果にデータの変更内容が反映されていないことがある。

Google App Engine のデータストアの形式には以前は、「Master/Slave」形式と「High Replication」形式があったのだが、「Master/Slave」形式は廃止されて、現在はアプリケーションを作成する際には「High Replication」しか選択できないようになっている。
「High Replication」ではデータの取得が eventual である、すなわり取得したデータが最新ではない可能性があるとのこと。どうやらそのせいのようだ。



こんなコードで試してみた。
500件データを追加して直後に全件読み取りしてその件数を確認する。
または、全データを削除して直後に全件読み取りしてその件数を確認する。

...
@SuppressWarnings("serial")
public class EventualTestServlet extends HttpServlet {
    private static final int SIZE=500;
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException, ServletException  {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            execute(req);
            int count = countData(req);
            resp.setContentType("text/plain");
            resp.getWriter().println("size=" + count);
        } finally {
            if ( pm !=null && ! pm.isClosed()) {
                pm.close();
            };
        }
    }
    
    private void execute(HttpServletRequest req) {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            String operation = req.getParameter("operation");
            if ("add".equals(operation)) {
                for (int i=0; i<SIZE; i++) {
                    MyData data = new MyData();
                    data.setName(req.getParameter("name"));
                    pm.makePersistent(data);
                }
            } else if ("delete".equals(operation)) {
                Query query = pm.newQuery(MyData.class);
                @SuppressWarnings("unchecked") 
                List<MyData> dataList = (List<MyData>)query.execute();
                req.setAttribute("dataList", dataList);
                pm.deletePersistentAll(dataList);
            }
        } finally {
            pm.close();
        }
    }
    
    public int countData(HttpServletRequest req) throws IOException {
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            Query query = pm.newQuery(MyData.class);
            @SuppressWarnings("unchecked") 
            List<MyData> dataList = (List<MyData>)query.execute();
            pm.detachCopyAll(dataList);
            return dataList.size();
        } finally {
            pm.close();
        }
    }
}

結果は 追加のほうは何回やっても500件カウントされている。一方削除のほうはたまに(10回に1回くらい)数件残ったりするようだ。もう一度(削除せずに)カウントだけし直すと0件になる。削除途中の結果が出てきているようだ。

ちなみに追加のほうは結構時間がかかるみたいで、500件でも30秒程度はかかっている。1000件だとタイムアウトしてしまった。

もう少しいろいろやってみようとしたのだが、

Uncaught exception from servlet
com.google.apphosting.api.ApiProxy$OverQuotaException: 
The API call datastore_v3.Put() required more quota than is available.

とエラーになってしまった。「ただで使わせてあげてるのにやりすぎ」とのこと。
ごめんなさい。


0 件のコメント:

コメントを投稿