TaskQueueはたしかに必ず起動される。例えば、"Request was aborted after waiting too long・・"というエラーになったとしても、正しく起動されるまでリトライされる。 しかし、起動してから30秒を超えた場合に、com.google.apphosting.api.DeadlineExceededExceptionやcom.google.apphosting.runtime.HardDeadlineExceededErrorが発生すると、そのTaskは強制終了となってリトライされない。※Exceptionをcatchで握りつぶすのではなく、ちゃんとスローさせれば必ずリトライされる。(正確には、com.google.apphosting.api.DeadlineExceededExceptionの後、300ms~400msでHardDeadlineExceededErrorになって強制終了する。300ms~400msでは出来ることは限られるが、何らかの救済処理を追記できるかもしれない。また、com.google.apphosting.utils.servlet.TransactionCleanupFilterというのもある。これらの動作については、30秒後の後を見て得たものが詳しい。)
11件目からDatastoreTimeoutExceptionが発生し始める。 また、com.google.apphosting.api.DeadlineExceededException: This request (b0dadab42eb7da0a) started at 2010/01/18 06:33:21.954 UTC and was still executing at 2010/01/18 06:33:51.109 UTC. との30秒超過エラーが発生。(Errorログ)
このあたりから"Request was aborted ..."ログが出始める。
12件目からDatastoreTimeoutException、DeadlineExceededExceptionの後、 com.google.apphosting.runtime.HardDeadlineExceededError: This request (9e9803f05d46a8c5) started at 2010/01/18 06:33:32.729 UTC and was still executing at 2010/01/18 06:34:03.487 UTC. とのCriticalログが発生。
時々正常終了する場合もあるが、"This request used a high amount of CPU, and was roughly 1.1 times over the average request CPU limit. High CPU requests have a small quota, and if you exceed this quota, your app will be temporarily disabled."とのWarningログが出力されている。
① クライアントからのリクエストはMemcacheに登録する(※1) ② cronが最初のTaskを起動、未完了の文字列を拾ってINDEX登録。登録成功でMemcacheから消す。(※2) ③ パラメータに文字列指定して次のTaskを登録する(URLは最大2038 文字なのでたぶん大丈夫) ※1 Memcacheの排他制御は必要。(参考)Memcacheでスピンロックを実装してTask Queue処理結果を集約してみるテストCommentsAdd Star Max1MBなので最大1000件とする。 それを超える場合はKeyを+1する。 ※2 未完了のものを再実行する際は、途中までPUT成功しているものを読み飛ばす
INDEX生成実験
これは、全文検索(SuffixArray)用INDEX生成のために実際に用いて実験したもの。
Store Skipping方式で500文字(日本語)×100件の文字列のSuffix Arrayを作成する。
しかし私は疑問を抱かざるを得ない。 複雑さを考える---Complexity Quanta and Platform Definition Summary of Jim Waldo‘sKeynote at the 10th Jini Community Meetingでいわんとしていることは、「それぞれの段階を通り抜ける際、我々は、何かを失う」ということ。 何も失わずにすべてを手に入れることなんて可能なのだろうか。これはとても難しい命題のように思える。 昨日、"eCloud"というリスティング広告に引っかかって、中島御大のサイトを発見した私であるが、とりあえず見なかったことにしようと思う。 (リタイヤされた元上司のサイトを半年もたってやっと見つけました。連絡ぐらいくれればいいのに。)
しかし、我々は何かを得てきた Seq to MT: 並列処理 MT to MP: プロセスの分離(安全を与える) MP to MM: 独立した失敗(何かまずいことが起きても、システムの部分は生きのこる) MM to MMU: スケール(webスケール、インターネットスケール). 誰か他の人のリソースを利用せよ(あるいは、他の誰かが、我々のリソースを利用することを認めよ)
先日、Google Docsにオンライン・ファイルストレージ機能を追加するという発表があった。画像・動画、ZIPファイルなどあらゆる種類のファイルをGoogle Docsで保管でき、アップロードしたファイルは検索機能や共有フォルダ機能の対象にもなる。アップロードできるファイルのサイズは1つにつきMAX250MB※までだが、全体の容量の制限はなく、1GBまでは無料である。それ以上は追加で購入できる。ストレージの値段は、現時点で20GBが5ドル/年だが、Google Apps Premier Editionユーザーに対しては、1GB=3.50ドル/年で今後数ヶ月以内に提供する計画とのこと。 (※ MAX1Gに変更された。2010/1/28) Documents List API: Upload any file and more (1/12/2010)
Documents List APIの一番大きな目玉はなんといっても全文検索APIである。Protocol Guide (v3.0)で「Performing a full text query」が New になっていないところをみると、もともとあった機能のようだが、今回から容量制限がなくなり、XMLやテキストファイルを登録できるようになったことで、やっと実用的になったのではないか。(サンプルプログラムによる検証を参照) 本題に入る前に、これまでのGAEにおける全文検索の実装方法についてまとめてみる。
GAEにおいて現実的な実装と思われるものは、①のSuffixArrayと、②のTinySegmenterだろう。①はデータ量が膨大になることと、最大サイズが500バイトまでなので、長い文章には向かない。②は長い文章でも大丈夫だが、分かち書きの精度に問題があって、使い物になるかどうかはよくわからない。 Google Documents List Data APIの精度は、検証結果からみて②のb.ではないかと思う。とてもよい品質なので、これで十分だと思われるが、漏れが完全になくなるわけではないので、完全性が必要な項目にはSuffixArrayを使うとよいと思う。 注意点としては、Google Apps Premier Editionユーザーでないと、Documents List APIを使えないこと。ストレージの値段がGAEよりも2倍ほど高くなり、現在はまだストレージを追加購入できない。
サンプルプログラムによる検証
Google Docs Serviceの生成と認証 DocsService service = new DocsService(appName); service.setUserCredentials(user, pass);
Google Docsの全文検索 URL feedUri = new URL("https://docs.google.com/feeds/default/private/full/"); DocumentQuery query = new DocumentQuery(feedUri); query.setFullTextQuery(word); DocumentListFeed feed = service.getFeed(query, DocumentListFeed.class);
ポイント
テキスト形式(text/plain)が対象
Google Documents List Data APIを使用してアップロードしたmimeType="text/plain"のXMLファイルは検索対象となった。
Google DocsのページからアップロードしたXMLファイルは検索対象とならなかった。
Google DocsのページからアップロードしたTXTファイルは検索対象となった。
Google DocsのページからアップロードしたExcelファイルは検索対象とならなかった。
インデックス生成
アップロード後、すぐに検索対象となった。
検索ワード
「半茹で冷凍又は・・・」という文字列について
「半茹で」はヒットした。○
「半茹」はヒットしなかった。×
「冷凍」はヒットした。○
「冷凍又」はヒットしなかった。×
「冷凍又は」はヒットした。○
「東京都調布市深大寺東町1-XX-X」という住所文字列について
「調布市」はヒットした。○
「深大寺」はヒットした。○
「深大寺東」はヒットしなかった。×
「東町」はヒットした。○
「東町1」はヒットした。○
XMLファイルをGoogle Docsにアップロードする。
Google Docs Serviceの生成と認証 DocsService service = new DocsService(appName); service.setUserCredentials(user, pass);
Googleのサンプルにあった String mimeType = DocumentListEntry.MediaType.fromFileName(file.getName()).getMimeType(); を実行すると java.lang.IllegalArgumentException: No enum const class com.google.gdata.data.docs.DocumentListEntry$MediaType.XML とエラーが発生する。
mimeTypeを"text/xml"に固定で設定すると com.google.gdata.util.InvalidEntryException: Content-Type text/xml is not a valid media type. アップロード時に上記エラーとなる。 "application/xml"でも同じくエラー。