一応動くのだが、たまに表示される結果にデータの変更内容が反映されていないことがある。
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 件のコメント:
コメントを投稿