2015 年 9 月 23 日 水曜日
Google App Engineでは、1回のリクエストに対し、30秒以内にレスポンスを返さなければいけない
上記の制約がある中で、バッチ処理のように、1回の処理に数分から数時間かかる処理を実現するにはどうすれば良いか?
多くの場合、答えはTaskQueueになると思いますが、TaskQueueは実行ユーザーがGoogle App Engine Adminになってしまいます。
処理を開始したユーザーで繰り返し実行したい場合—たとえば、あるユーザーにしか参照権限が無いSpreadSheetを、APIで検索する場合。Adminには参照権限が無いので、当然、接続に失敗します。
30秒以内にレスポンスを返す処理を、非同期に、目的が達成するまで繰り返します。
index.jsp
————————
var query = {
'state' : $("#state").val(),
'startindex' : $("#startindex").val(),
};
$.ajax({
url: "/do",
type:"post",
data: query,
dataType: "TEXT",
success: function(html){
// レスポンス受信成功
html = $.trim(html);
document.getElementById('target_ajax_load').innerText = html;
// レスポンス分解
// レスポンスを連想配列にしておく
var response = document.getElementById('target_ajax_load').innerText.split("\n");
var keyvalue = new Array();
for (var i = 0; i < response.length; i ++) {
var kv = response[i].split("=");
keyvalue[$.trim(kv[0])] = $.trim(kv[1]);
}
// 以下、レスポンステキストによって処理変更
if (keyvalue['state'] == 'done'){
// ★ 完了した場合
var resulthtml = '完了しました';
document.getElementById('target_ajax_load').innerHTML = resulthtml;
} else if (keyvalue['state'] == 'step1' || keyvalue['state'] == 'step2' || keyvalue['state'] == 'step3'){
// ★ タイムオーバーした場合(続きから検索)
$('#state').val(keyvalue['state']);
$('#startindex').val(keyvalue['startindex']);
document.getElementById('target_ajax_load').innerHTML = "しばらくお待ちください..." + stateMessage;
setTimeout("sync()", 5000);
} else if (keyvalue['state'] == 'error'){
// ★ エラー発生時(メッセージ出して終わり)
document.getElementById('target_ajax_load').innerText = $.trim(keyvalue['error']);
}
});
do.jsp
——————————
<%@page pageEncoding="UTF-8" isELIgnored="false" session="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>;
${response}
DoContoroller.java
——————————
int startindex = Integer.parseInt(request.getParameter("startindex"));
String state = request.getParameter("state");
if (state.equals("step1")){
if (counter > hoge){
// 処理が終わったら...
response += "state=step2\n";
startindex = startindex + counter;
response += "startindex=" + startindex + "\n";
requestScope("response", response);
return forward("do.jsp");
} else {
// 処理が終わらなかったら...
response += "state=step1\n";
startindex = startindex + counter;
response += "startindex=" + startindex + "\n";
requestScope("response", response);
return forward("do.jsp");
}
} else if (state.equals("step2")){
// 略
} else if (state.equals("step3")){
// 略
}
処理失敗時のリトライであったり、
作業データのバックアップ、失敗時のリストアが必要かも。
このエントリーのトラックバックURL:
http://www.bmoo.net/archives/2011/05/312388.html/trackback