Google App Engineだと、30秒制限があって長い処理が書きにくいのですが、タスクキューは処理中に例外が発生したり30秒制限にひっかかったりすると自動的に呼び直されるので、これを使って長い処理を実行することができます。
ということは知っていたんだけど、実際どうなのかと思って試してみた。
まずこんなサーブレット書きます。
※GAE/JはServlet3.0に対応してないので、@WebServletアノテーションは擬似コードだと思ってください。
5秒に一回QueueTestに現在値を記録するという処理を行うループを20回繰り返します。5秒×20=100秒 >> 30秒なので、確実にタイムアウトします。
タスク開始時の値をQueueLogに記録しておきます。
@WebServlet(urlPatterns="/queue/testqueue") public class TestQueueServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); Entity ent; Key key = KeyFactory.createKey("QueueTest", 1); try { ent = ds.get(key); } catch (EntityNotFoundException ex) { ent = new Entity(key); ent.setProperty("count", 0L); } Entity log = new Entity("QueueLog"); log.setProperty("count", ent.getProperty("count")); log.setProperty("updated", new Date()); ds.put(log); Long lg = (Long) ent.getProperty("count"); for(; lg < 20; ++lg){ try { Thread.sleep(1000 * 5); ent.setProperty("count", lg); ent.setProperty("updated", new Date()); ds.put(ent); } catch (InterruptedException ex) { } } } }
そしたら、こんな感じでQueueに入れます。
@WebServlet(urlPatterns="/queuetest"); public class QueueTestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Queue q = QueueFactory.getDefaultQueue(); q.add(TaskOptions.Builder.url("/queue/testqueue")); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<title>Servlet QueueTestServlet</title>"); out.println("queued"); out.close(); } }
このサーブレットを呼び出してしばらくほっておくと、QueueLogにデータがたまります。だいたいこんな感じで実行されました。
0: 04:41:09 4: 04:43:34 8: 04:44:33 12: 04:45:10 16: 04:45:47
処理が終わったのは 04:46:07となってたので、ほぼ5分かかったことになります。
4回の繰り返し、つまり20秒以上たって一度の呼び出しが終わっていることもわかります。
機嫌がいいときには40秒以内でタスクキューの処理が繰り返されてますが、1分近くかかっていることもあります。
100秒=1分40秒の処理に、5分=300秒かかるというのがどうかというのはありますが、ともあれ、タスクキューを使って長い処理が実行できることが確認できました。