続:cronのないGoogle App Engineで1日に1回程度の処理をする方法

GAEのcron - def __mopemope__(self, *args, **kwargs):

まあ現状だとurlfetchでまわすしかないよね。

Nakai 11:49
http://d.hatena.ne.jp/mopemope/20090309/p2

nishio 11:56
urlfetchってブロッキングだからぐるぐる回していると
1リクエストあたりの時間制限で切られそうな気がするなー
って書いた

Nakai 11:58
urlfetch の面白い機能として
タイムアウトが 30 秒くらいまである
処理は 5 秒くらいで着られそうなんだけど
urlfetch だけは 30 秒くらいまで待ってくれる
という抜け穴を使ったわざ

nishio 11:59
urlfetch中は処理時間としてカウントしない?

Nakai 11:59
正解

nishio 11:59
でもいつかタイムアウトするな。

Nakai 12:00
リダイレクトしてるから大丈夫なんじゃないの?

nishio 12:00
1ループに0.01秒だとして
urlfetchで10秒稼いだとしても
100000秒後には最初にキックしたリクエストが死んでしまう
27時間後だな

Nakai 12:01
なるほど

nishio 12:01
このやり取りをブログに載せてトラックバックするか

Nakai 12:01
そこら辺気になるね

nishio 12:01
なかなかに難しい問題だ


もちろんcronが入ればすべて解決するのだが。



追記

nishio 12:11
/crond/へのアクセスがタイムアウトする
def taskの中のget_urlがsleepを叩いて
sleepの中のget_urlがtaskを叩くだろ、
urlfetchはブロッキングするので
この交互に呼び合っている間一番最初に/crond/を叩いたリクエストは完了しない
各々の関数の中でどの程度の時間をくうかによってXデーは変わるけども
0.01秒だとしたら1日ちょいで死んでしまう

問題は
最初にキックしたリクエストが死んだときに
そこからurlfetchで叩かれているリクエストが中断するかどうかだな
threadが外部から終了されたときに
urlfetchはレスポンスが帰ってくるのを待ってから終了するのか
即座に終了してそれがサーバ側に伝わるのかどうか
結局のところ、sleep(10)してから処理をするビューがあったときに
5秒でブラウザを閉じたら
処理は最後まで行くのかどうか
最後まで行くのなら追いかけてくるタイムアウトから永遠に逃げ回れるのか。

逃げ回れるような気がしてきた。

nishio 12:29
なんかmopemope案でうまく動く気がしてきた
永遠に逃げ回れる、という線
ソケットがクライアント側から切られたとしても処理は続行する設計じゃないかなと。

nishio 12:30
ソケットが切れた時点で殺すかどうか

Nakai 12:31
ころさないんじゃない?
タイムアウト指定でしょう

nishio 12:31
切れたかどうか監視するの面倒だから殺さないんじゃない?
そういうこと。
だったら逃げ回れるよね。

というわけでmopemope案でうまく動くだろう、という結論になった。


おなかすいた。



nishio 12:40
これを使えばGAE上で疑似スレッドを作れるな
自分を呼び続けるワーカースレッドがあって
キューにタスクを積むとそれを処理してくれる

nishio 12:41
quotaが657,000 calls/day 3,000 calls/minuteだから
0.1秒で自分を呼んだりしても全然問題ない
とても余裕

これを使えばスレッドが使えないって理由でGAEでやるのをやめて最中限オンラインも問題なくいけるんじゃないか?