2010-02-28

Blogger ブログの ID ではまる

PubSubHubbub の使い方がなんとなく分かったので、Japanese Bloggers Info に導入しようと試行錯誤。意外と色々なところに手を入れなければいけないことに気づいたので、ついでにデータの保管の仕方も変えてしまう。

Blogger ブログはユーザーが自由にブログの URL を変えられるので、URL をキーにするより、ブログ ID をキーにした方がよさそうな気がして変更。当初あまり考えずにエンティティグループを作っていたのも、全部解除してバラバラに。

問題は、そのブログ ID。この値は、ユーザーのブログ一覧フィードから
tag:blogger.com,1999:user-875683517854.blog-13722714
のような形で取得できるのだけれど、実際のブログの投稿フィードの方から取得すると
tag:blogger.com,1999:blog-13722714
のようにユーザー情報が抜け落ちる。

ブログをアプリケーションに登録するときには、ブログ一覧をもとに上の方の ID をキーにしてエンティティを作るものの、PubSubHubbub の更新通知で送られてくるフィードに記載されているブログ ID は、下のユーザー情報が記載されていない方。

この違いに気づかず、ブログ情報のエンティティ読み出しで随分はまってしまった。ID の表記が複数あるとは思わなかったし。

結局、ブログ情報のエンティティのキーを登録時からユーザー情報抜きの形に加工するようにして、解決。

PubSubHubbub の更新通知のフィードには URL も記載されているので、前の URL をキーにエンティティを作っていたときの方が、連携が楽だった気もしたり…。

2010-02-20

GAE/J、SDK のアップデートではまる

Google App Engine Java SDK を 1.3.0 から 1.3.1 へアップデート。前のアップデートで少し手間取ったような記憶があるので、今回はメモを取りながら。

まずはインストール。eclipse の「ヘルプ > ソフトウェア更新」で開いた「ソフトウェア更新およびアドオン」ウィンドウの「使用可能なソフトウェア」から「Google Update Site for Eclipse *.*」を開き「Google App Engine Java SDK *.*.*」にチェック、「インストール」ボタンを押す。「インストール」という確認画面で「次へ」を押し、ライセンスのレビュー」でライセンスを確認後「使用条件の条項に同意します」ボタンを押下。インストール後 Eclipse の再起動を促す画面が出るので、「はい」ボタンを押す。

次は新しい SDK の選択。「ウィンドウ > 設定」から「Google」を開き「App Engine」をクリックすると、現在使っている SDK と新しくインストールした SDK が並んでいるので、新しいほうにチェックして「OK」ボタンを押す。これで SDK の更新はおしまい。

…のはずだったんだけれど。デプロイは問題がないものの、ウェブアプリケーションの実行ができなくなってしまった。あれれ。

コンソールには

Error occurred during initialization of VM
agent library failed to init: instrument
Error opening zip file: C:\eclipse\plugins\com.google.appengine.eclipse.sdkbundle_1.2.6.v200910130758\appengine-java-sdk-1.2.6\lib\agent\appengine-agent.jar

とのメッセージ。エージェントライブラリーの初期化に失敗するとのこと。…ってそんなディレクトリはもうとっくにないんですけど。

結局色々探して、eclipse のメニュー「実行 > 実行構成から GAE/J プロジェクトを選択、「引数」タブをクリックしてみると「VM 引数」の欄に問題のディレクトリ指定が。そこで

-javaagent:C:\eclipse\plugins\com.google.appengine.eclipse.sdkbundle.1.3.1_1.3.1.v201002101412\appengine-java-sdk-1.3.1\lib\agent\appengine-agent.jar

と、現在選択している SDK のエージェントのパスを指定してやると問題が解決。あーあせった。SDK 1.2.6 から 1.3.0 の更新のときは何も言われなかったのに、なんでだろう。

2010-02-19

GAE メンテナンス…

Google App Engine のメンテナンス。 から Reminder メールが来ていたので、知ってはいたものの未対処で、気づけば 1000 件近くものエラーが発生。TaskQueue で呼び出されたサーブレットがエラーを出して、Task が消えないうちに、さらに新たな Task がどんどん作られていったみたい。

メンテナンス中はデータストアが読み出し専用になって、データを格納しようとすると
com.google.apphosting.api.ApiProxy.CapabilityDisabledException
という例外が出るとのこと。

以下のページのように全部キャッチして、 TaskQueue を使うサーブレットは、メンテナンス時に書き込み動作をするような Task を積まないようにしないと…。
shin1ogawa: @bluerabbit777jp DS.put(new Entity("_capability_check", String.valueOf(Math.random()*10))); して読み込み専用例外をキャッチして判断するしか手が無いかもしれませんねぇ。 #appengineTwitter / shin1ogawa
でも、読み取り専用になっているかどうか、put() してみなければわからないというのは不便だなぁ。

2010-02-14

GAE/J で PubSubHubbub

今回は、Google App Engine for Java で PubSubHubbub を利用する話。

Japanese Bloggers Info、1 月に公開してから、現在の登録ブログ数が 250 近く。まだまだブログ数は伸びそうだけど、すでに CPU Time が 60% ぐらいになってしまっているので、なんとかしなくちゃと思っているところ。

ブログ更新の確認のために、cron と TaskQueue で、5 分ごとに全ブログのフィードにアクセスさせているのだけど、そこがやはり最も CPU を使っている部分。

ポーリングをやめていっそのこと PubSubHubbub にしてみたらどうだろう?と思って調べてみた。Blogger は Publisher として PubSubHubbub に対応しているので、こちらで Subscriber を用意すればいいというわけ。参考にしたのは、PubSubHubbub の仕様 と、実際の Hub。今ごろ気づいたけれど、これも GAE で動いてるんだ…。 この
http://pubsubhubbub.appspot.com/subscribe
という URL に、GAE アプリケーションから POST で Subscription Request を送る(パラメータはこちらを確認)と、hub.callback パラメータで送った Subscriber の更新通知用の URL に、折り返し確認の GET アクセスが来る。受け取ったアクセスのパラメータを確認(こちらを参考に)したら、そのまま hub.challenge の内容を本文にして、200 番台のステータスコードで返してやると、Hub への Subscribe 登録が成功。

最初の購読希望の POST アクセスは、Hub のデバッグページ(というか、ここが実際の Subscription Request の送り先…) から、フォームで送信できるので、色々テストしてみるのがよさそう。

購読登録が終了したフィードに更新があると、自動的にその更新部分のみを Atom フィードにして、POST で Subscriber の更新通知用の URL に送りつけてくれる。受け取ったという印に 200 番台のステータスコードを返せとのことだが、202 Accepted だと認識されず、5 回までリトライ、Failure のまま終了してしまった。200 OK を返してみると 1 回で認識。実際の Subscription 失敗の詳細は、前掲のデバッグページ「Subscriber Diagnostics」から確認できる。

更新情報の Atom フィードは POST の本文として送られてくるので、
Feed feed = new Feed();
try {
  feed.parseAtom(new ExtensionProfile(), req.getInputStream());
} catch (ParseException e) {
  e.printStackTrace(System.err);
}
という形で Feed にパースできる。後は
Entry entry = feed.getEntries().get(0);
String title = entry.getTitle().getPlainText();
String content = entry.getTextContent().getContent().getPlainText();
なり、なんなりと。

ということで、これはなかなか使えそうな予感。とはいえ、なかなかまとまった時間が作れないので、いつこれを組み込めることやら…ううむ。

2010-02-06

GAE/J、1000件超のエンティティ

Google App Engine for Java で、同じ Kind のエンティティは 1000 個までしか作れないのかな?と思ってドキュメントを探していたけど、データストアから一度に 1000 件までしか取得できない(Low Level API)というだけだったみたい…。cron で作りっぱなしだったあのエンティティは、今何個あるのかすらわからず…。

で、アクセスする方法を発見。 と実際のアクセスの仕方は分かったのだけれど、現在全く使用していないエンティティだったので、結局 1000 件ずつ取得→削除で、全部消しちゃった。1000 個で打ち止めと思い込んでいたんだけれど、知らないうちに 3000 個くらいたまってた…。無頓着にどんどんエンティティをためるシステムは考え直さないと。