Showing posts with label JBI. Show all posts
Showing posts with label JBI. Show all posts

2015-08-05

GAE の Datastore を Master/Slave から High Replication (HRD)へ移行する方法

管理しているウェブアプリ Japanese Bloggers Info が動かなくなっていたので、ようやく重い腰を上げて、データストアの移行に乗り出した。それが昨日(2015-08-04)のこと。確認してみると、3 年も前から Master/Slave Datastore は非推奨になっていたのね。そりゃ、アプリも止まるわ、と。 GAE ダッシュボードからリンクをたどってドキュメントを見てみると、衝撃のタイムテーブルを発見。
August 3, 2015: You will no longer be able to re-enable your application. However you will still be able to migrate to HRD.
(拙訳:2015-08-03 で、もうアプリケーションは有効にできなくなります。HRD への移行はできますが。 )
無効になっている M/S アプリは、もう有効にできないとのこと。M/S から HRD への移行には、アプリの複製を作って、そこにプログラムをデプロイ、移行ツールを使って元のアプリからデータをコピー、エイリアスを設定という手順を取るのだけれど、肝心のアプリの複製を作る前提として、そのアプリが有効でないといけない。実際に、無効になっているアプリの複製を取ろうとして失敗したのが、次のスクリーンショット。


Sorry, that operation is not allowed while the application is disabled. This Master/Slave application is disabled.
「アプリケーションが無効になってるから無理です」っていうメッセージと、押せない「再度有効に」のボタン。これは八方ふさがりですね…。

で結局、最後の神頼みとて、GAE のサポートにリクエストを送ることにした。 名前とメールアドレス、電話番号、GAE のプロジェクト ID、リクエスト内容を入力して、送信ボタン押下。リクエスト内容は、「I want to duplicate application settings. Please re-enable my application.」と打ってみたけど、まあご参考に。

すると 1 時間もしないうちに、返信メールが届いた。
Hi,
We have re-enabled your app "japanese-bloggers". Please perform the migration as soon as possible. Feel free to get back to us should you have any questions.
Also, I will forward this case to my colleagues in Tokyo if you need any assistance during Japan business hours.
(拙訳:あなたのアプリケーションを再度有効にしました。できるだけ早く移行してください。質問があればご自由にどうぞ。日本の営業時間中に援助が必要な場合、日本の同僚にこのケースを転送します。)
なんと優しいお言葉!で、本来の移行の手順をたどって、無事 Japanese Bloggers Info が復活したというわけ。移行の参考にしたのが、次のブログ(ありがとうございます!)。説明が分かりやすいので、間違えることはないはず。 ただ一点、「Activate Read-only」の段では、データストア移行に時間をかけられないので「Launch Incremental Copy(増分コピーを起動)」を飛ばして、すぐさま「Activate Read-only」にするのがいいかと。すると、移行自体は 1 時間もかからずに終了。なぜこれをサボっていたのかという感じもしたり…。

ということで、僕みたいにズボラな人がそんなにいるとも思えないプラス、同じようにやってできるかも分からないけれど、一応参考にしてもらえたらと。

ちなみに、前掲タイムテーブルの最後には、2015-08-10 に M/S アプリケーションが完全停止し、アクセスできなくなるということが書かれているので、移行作業はぜひお早めに。


追記(2015-08-05):

その後、GAE サポートから再びメール「移行作業は成功しているけど、課金(Billing)が有効になっていないせいで、QUOTA オーバーを起こしているよ」と。なんと親切なご指摘。エイリアスを設定することで、閲覧者はアプリケーションの変更を意識しないで済むものの、基本的には別のアプリケーションなため、新たな課金設定がいるみたい。元々 GAE の無料枠に収まっていなかったという人は、要注意。課金有効化と「Daily Budget(日ごとの課金上限)」設定をお忘れなく。

2011-12-25

GAE/J 新 Quota と新料金体系への対策

もういろんなところで書き尽くされていると思うのだけれど、自分の記録用として。

対策結果

最初に、Japanese Bloggers Info の Billing History データ。



インスタンスをたくさん使っているものの、この当時はまだ旧 Quota で CPU Time も 6.50 に収まっていたので、課金はなし。で、最終的にこうなった。



結局課金になってはいるものの、日に 7.00 ドルかかるぞ(Frontend Instance Hour は現在の半額での計算)と宣言されていたのが 0.15 ドルになったのは上出来。


対策内容

<1> Idle Instances と、Pending Latency の設定。GAE の設定ページ「Application Settings」を開いて、スライダーを使って Idle Instances の Max Idle Instances を 1、Min Idle Instances を Auto に。Pending Latency の Min Pending Latency を 15、Max Pending Latency を Auto に設定する。これだけで、Frontend Instance Hour が 35 時間くらいに激減。

<2> TaskQueue の rate(実行頻度)を緩和。5/s だったものを 2/s に。Japanese Bloggers Info は、ブログチェックのため、5 分ごとに cron で 300 個以上の TaskQueue を呼ぶ仕組みになっているので、これだけのことでも意外と効果あり。Frontend Instance Hour も大体 30 時間以内に。

<3> Backends を利用。上記の TaskQueue が一日中動いているので、日に 6 時間は Backends で TaskQueue を動かすことに。どうしても 2 インスタンス動くところがあるので、6 時間は必ず超えるけれど、9 時間までは Backends の無料枠があるので、問題なし。というか、この残りの 3 時間で、2 インスタンス動いてしまう時間を吸収してもらう感じ。で、Frontend Instance Hour もほとんど 28 時間に収まるようになったというわけ。

<4> Memcache の積極利用。全ブログのリストや、各ブログのデータなど、5 分ごとで変化しない内容については、Memcache を利用。大幅なデータ取得の仕組みは改修せず、Entity にアクセスする前に Memcache を確認するようにしただけ。Memcache になければ、通常通り Entity からデータを得て、Memcache に入れておく。それだけで、Datastore Reads は 0.27 ドルから 0.08 ドルへ、約 3 分の 1 に。

で、現在に至る、と。どれもちょっとしたことなので、誰にでもできるはず。よかったら参考にしてください。

2011-05-14

トラックバック受信機能作成中…

Blogger からトラックバックを送信するシステムを作って公開したのは、ちょっと前にお知らせしたとおり。今はトラックバックを受け取る仕組みも一応できて、あとは受け取ったトラックバックのブログでの表示方法や、削除用のトラックバック一覧画面を考えているところ。

まだ途中の段階だけれど、Blogger Tipsテストブログにトラックバック受信機能設置してみた。テストブログでは、トラックバック受信機能のテスト中。興味のある人は、以下の投稿から表示の確認をしてみたり、いろんなブログからトラックバックを送ったりしてみて、感想など聞かせてもらえるとうれしかったり…。

2011-02-20

GAE/J、PreparedQuery#countEntities() ではまっていた件

GAE/J で運営しているサイト Japanese Bloggers Info で、ようやく登録ブログ件数が 1000 件になった。

Japanese Bloggers Info、登録ブログが 1000 件になった。やった! http://japanese-bloggers.appspot.com/Tue Feb 15 18:28:37 via web


サイトトップの
このサイトでは、日本語の Blogger ブログの更新情報を紹介しています。現在、1000 個のブログが登録されています。
という表記でブログ件数を見ていたのだけれど、ここ数日「1000 個」から増えないので、不思議に思ってコードを見てみると、
PreparedQuery pq = ds.prepare(query);
pq.countEntities();
みたいになっていました。そういえば、PreparedQuery#countEntities() は 1000 超えの数を返さない、と噂になっていましたね…。こちらを参考にしつつ、
PreparedQuery pq = ds.prepare(query);
pq.countEntities(FetchOptions.Builder.withOffset(0).limit(Integer.MAX_VALUE));
と変えておきました。すると、すぐさま 1035 件に。いったい、どれだけ放置していたんだろうか…(汗)。

2011-02-06

Japanese Bloggers Info にトラックバック送信機能をつけた。

表題のとおり。Japanese Bloggers Info にトラックバック送信機能を設置。送信先は問わないけれど、送信元は Japanese Bloggers Info に登録しているブログのみ。登録されている最新投稿の内容を、トラックバック Ping で送れるようにしたもの。
今回作った JQuery を使ったページは、Japanese Bloggers Info の、登録 Blogger ブログの投稿データからトラックバックを送るページに使用。今途中のトラックバックを受け取る方の仕組みを完成させたら、公開する予定。
と以前書いたのだけれど、受信機能のほうはいつ完成するのかわからないので、送信機能のみ beta 版として、とにかく公開。 参考にした、トラックバックの仕様はこちら。 変なところがあったら、指摘してもらえると助かります。

2010-10-31

JQuery はじめました

#ajnk3 で刺激を受けて、新しいことに挑戦しようと思っているところ。で、昨日からひとまず JQuery を始めてみた。

とっかかりは、JQuery のすすめ的な、こちら。
CSS と JavaScript がちょっとできれば、何とかなりそうな感じ。
それで、次はこれを見て色々コードを打ってみる。 あとは、以下のリファレンスを見ながら、 あーでもないこーでもないとパソコンに向かっていたら、一通り、AJAX 的なページができた。非常に簡単+便利なので、これまでの食わず嫌いを反省中。来週は JQuery UI と組み合わせて使ってみよっと。

今回作った JQuery を使ったページは、Japanese Bloggers Info の、登録 Blogger ブログの投稿データからトラックバックを送るページに使用。今途中のトラックバックを受け取る方の仕組みを完成させたら、公開する予定。

できなかったことができるようになるっていうのは、やっぱりいくつになってもうれしい。

2010-08-15

GAE/J、AuthSub で AuthenticationException …

アクセス解析にて「Japanese Bloggers Info 登録できない」という検索フレーズを発見、「えっ」と を確認してみると、確かにアプリケーションにブログを登録できず…。

問題は Blogger に所有ブログを問い合わせる際の AuthSub 認証で
com.google.gdata.util.AuthenticationException
が出ていたこと。

Google に登録している証明書の期限が切れたのかな? SSL は?とチェックしてみるも問題なし。うんうんうなること 10 数分…。最終的に、Google 先生に教えてもらいました。
String token = AuthSubUtil.getTokenFromReply(req.getQueryString());
token = URLDecoder.decode(token, "UTF-8");
URLデコードしてやれば良いようです。
これまでちゃんと動いていたんだけど、いつからデコードが要るようになったんだろう(汗)?アクセス解析をつけていて良かったとひしひしと感じた今日この頃。

検索してくれた人、ありがとう。プラス、この間ブログを登録できなかった人、すみません。

2010-04-17

Query.addSort(String).addSort(String) ではまる

Japanese Bloggers Info にカテゴリーページを追加。その後、カテゴリートップのページに、カテゴリ一覧を表示。

そこで気がついたのが、これ。カテゴリデータを保存しているエンティティを、親カテゴリを主キーに、日本語名を副キーに指定して並び替えるクエリ。
Query query = new Query("Category").addSort("japanese").addSort("parent");
みたいに、日本語名で並び替えてから、親カテゴリで並び替えればいいと思っていたのが大間違い。
Query query = new Query("Category").addSort("parent").addSort("japanese");
という風に
SELECT * FROM Category
ORDER BY parent, japanese
と SQL で書くのと同じ順で並べなきゃいけないみたい。

…。って API のリファレンスにも書いてあるじゃないですか。
addSort を初めて呼び出すと、並び替えの主キーとなるプロパティが登録されます。addSort を再び呼び出すと、並び替えの副キーなどが設定されます。
ううむ。ちゃんと読んどかないと…。

2010-04-11

Japanese Bloggers Info にカテゴリー機能追加

Japanese Bloggers Info にカテゴリー機能をつけてみた。

とりあえず、ベータ版としてこのブログを見ている人にだけお知らせ。 時間があるときに、トップページのようなプレビュー機能をつけるかもしれないけど、まだ未定。

Japanese Bloggers Info にブログを登録している人は、カテゴリー設定をしてみて、感想や不具合の報告などをコメントで書いてもらえるとうれしかったり…。

ちなみに、現在の設定では、カテゴリー登録順で上位に表示されるというウワサです。

2010-03-25

サムネイルのプリロード

Japanese Bloggers Info で、サムネイル画像をプリロードさせることに。最初のページ表示で少しもたつく気がするけれど、ブログのプレビューは画像読み取り時間がなくなり快適に。
var thumbs = new Array(blogurls.length);

function preload() {
  for (var i = 0; i < blogurls.length; i++) {
    thumbs[i] = new Image();
    thumbs[i].src = "http://capture.heartrails.com/medium?" + blogurls[i];
  }
}

if (window.addEventListener) {
  window.addEventListener("load", preload, false);
} else if (window.attachEvent) {
  window.attachEvent("onload", preload);
} else {
  window.onload = preload;
}

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-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-01-31

OPML と Google カスタム検索

Japanese Bloggers Info に、登録ブログを記載した OPML 発行と、登録ブログ対象のカスタム検索の機能をつけた。
  • ブログ情報から自動的に OPML ファイルを生成するサーブレットを作成。
  • Google のカスタム検索を作成し、OPML を登録、検索対象サイトを自動的に更新させる。
ということをした。OPML の仕様は、次のサイトを参考に。 カスタム検索への OPML 登録は、Google カスタム検索エンジン「マイ検索エンジン > コントロールパネル > 詳細設定」から。

「アノテーションフィードの追加」という項目に、Custom Search XML という、アノテーション(検索対象サイトを指定するもの)を記載した XML を登録する必要があるが、OPML をこの XML に変換するツールが用意されているので、それを間にかませる。つまり、

www.google.com/cse/tools/makeannotations?url=(OPML の URL)&label=(カスタム検索の ID)

のような URL を、アノテーションフィードとして登録すれば OK。検索フォームについては、検索結果をページ内に出すために、カスタム検索「マイ検索エンジン > Custom Search Element」を利用した。うん、なかなかいい感じ。

2010-01-21

GAE/J で If-Modified-Since に対応

フィードを配信するようになったので、ついでに If-Modified-Since ヘッダに対応させてみた。フィードリーダーからのアクセスがよくなるのかどうなのか、わからないのだけれど。

コードはほとんど、こちらの丸写し。変えたのは、Last-Modified をブログのリストをキャッシュしたときの日時にしたことぐらい。 なんとなく、フィードリーダーでのデータ更新の反映が早くなった気がする…。

GAE/J で RSS フィードの配信

でフィード配信開始しました。それがこちら。 フィードリーダーに登録しておくと楽しいかも。

RSS フィード発行のためのコードはこんな感じ。いつも載せるコードよりちょっと長いけれど、まあ備忘録として。
Feed feed = new Feed();
feed.setTitle(TextConstruct.create(TextConstruct.Type.TEXT, "Japanese Bloggers Info", null));
feed.setSubtitle(TextConstruct.create(TextConstruct.Type.HTML, "日本語の Blogger ブログの更新情報を紹介しています。", null));
feed.setGenerator("1.0", "http://japanese-bloggers.appspot.com/", "Japanese Bloggers Info");
feed.setUpdated(new DateTime(now.getTime(), 540));
feed.addLink("alternate", "text/html", "http://japanese-bloggers.appspot.com/");
feed.addLink("self", "application/rss+xml", "http://japanese-bloggers.appspot.com/feed");
feed.getAuthors().add(new Person("Kuribo", "http://www.kuribo.info/", "kurikuribo@gmail.com"));

ArrayList<Entry> entries = new ArrayList<Entry>();

Entry entry = new Entry();
entry.setTitle(TextConstruct.create(TextConstruct.Type.TEXT, blogtitle + ": " + posttitle, null));
entry.setContent(TextConstruct.create(TextConstruct.Type.HTML, summary, null));
entry.setPublished(DateTime.parseDateTime(postPublished));//postPublished は Blogger のフィードから得た発行日時
entry.addLink("alternate", "text/html", posturl);
entry.getAuthors().add(new Person(author));
entries.add(entry);

feed.setEntries(entries);

StringWriter sw = new StringWriter();
try {
 feed.generateRss(new XmlWriter(sw), new ExtensionProfile());
} catch (IOException e) {
 //省略
}
String rss = sw.getBuffer().toString();
ちょっとはまったのが、8 行目と 17 行目の author 項目。Feed.setAuthors(List<Person>) みたいなメソッドがないので焦ったのだけれど、上掲のように get した List(要素なし)に Person を追加するのでいいみたい。

あと 14 行目 content の項目は、アプリケーションでエスケープするので、text でいいやと思って指定してみるとフィードリーダーに本文が表示されず。タイトルは text、内容は html というのがよさそう。

2010-01-17

Quota と 10 秒ルールのはざまで

を公開してから一週間。現在、順調にユーザーが増えているところ。だけど、このままユーザーが増えても、無料の Quota 内でいけるのだろうかと少し心配に。 このアプリでは
  • Update サーブレットが cron で 5 分間隔に呼ばれ、登録されているブログ情報を確認して、TaskQueue で Check サーブレットを呼び出す。
  • Check サーブレットでは Update サーブレットから渡されたパラメータ(Key String)をもとにブログ情報を確認し、その投稿フィードへアクセス。更新があればその内容をブログ情報へ格納。
  • 登録ブログ分の Check サーブレットが全て動き終わると(MemcacheService.increment(Object, long) で確認)、Prepare サーブレットが起動。登録されているブログから更新時刻をもとに 50 個 Query を使って呼び出してリストを作成し、Memcache に格納。
  • トップページの Top サーブレットで、Memcache からリストを表示。なければ Prepare サーブレットのリスト作成メソッドから取得。
なんてことをしているんだけれど、今までは贅沢に、ブログの更新をチェックする Check サーブレットを、ブログの数だけ TaskQueue に積んで起動させていた。無料 Quota の Task Queue 呼び出しリミットは 100,000。このままの仕様だと、348 ブログ登録されただけで、一日の最後の方には「Over Quota」となってアプリが止まってしまう危険性が…。 そこで Check サーブレットの仕組みをいくらか変えて、複数ブログの更新チェックを一度にできるようにしてみた。とりあえず 10 件で。DatastoreService とか GoogleService とか、その他色んなリソースを使いまわせるので、パフォーマンス的にもいいかも。とか思って動かしてみると…

Request was aborted after waiting too long to attempt to service your request. Most likely, this indicates that you have reached your simultaneous dynamic request limit. This is almost always due to excessively high latency in your app. Please see http://code.google.com/appengine/docs/quotas.html for more details.

というログで、ションボリ。なんだこりゃと調べてみて、一番分かりやすかったのがこのページ。
 あのwarningは、リクエスト処理中に後続のリクエストが来てqueueにつまれ10秒以内に処理されなかったときに発生します。

 つまり、AppEgnineは30秒ルール以外にも、負荷が集中するときには、10秒以内に処理しないければいけないという10秒ルールも存在するのです。
ということなので、とりあえず 5 件ごとの更新チェックにしたところ、ようやく何も言われなくなった。登録ブログが次の上限 1736 件に迫ったら、また別の方法を考えないと…。

2010-01-11

GAE/J アプリ「Japanese Bloggers Info」完成

Google App Engine で作った初めてのアプリ、完成。日本語 Blogger ブログの更新情報を紹介するもの。 簡単な説明がこちら。 実際にアプリを公開して、色んな人に使ってもらって初めて気づくこともあったり。
  • まだ記事のないブログを登録する人がいる。
     →エントリにアクセスしないよう条件分岐。
  • 50 件も表示すると、最後の方のブログは右上のプレビューが見えない。
     →下半分は下半分用のプレビューエリアで表示。
  • ブログ名や投稿タイトルによっては、プレビューの JavaScript が止まってしまう。
     →JavaScript の配列に入れるメッセージのエスケープ。
  • ブログの Blogger 側の設定によっては、full フィードへのアクセス不能に。
     → default へのアクセスに切り替え。
  • Blogger の設定によっては、プロフィールへの URL が取れない。
     → プロフィール URL がなければプロフィールアイコン非表示に。
こういう新しいアプリは、不完全なままでもどんどん公開して、実際に使ってもらった方が、問題点が見えやすくなっていいんだなと実感。動かしながら修正して行くというのは、それはそれで大変なんだけれど。

2010-01-09

GAE/J、Blogger フィードのコンテントが取れない

Perl で昔に書いた Japanese Blogger Update Info の後継として、Blogger ブログの更新情報を掲載する GAE/J アプリを製作中。

Google アカウントと結び付けられた Blogger ブログを登録してもらって、トップページで時系列の更新情報を紹介。cron で一定時間(今のところ 5 分間隔)で Update というサーブレットが起動されるようにしていて、そこからまた TaskQueue で、各ブログのフィードへアクセスして更新を確認する Check サーブレットを複数起動する。全部チェックし終わったら更新されたブログのリスト(HTML)を作って、Memcache へ格納。トップページでそのキャッシュを表示、のようなことをしているのだけれど…。

ブログの投稿フィードのコンテント取得で一晩はまる。
GoogleService myService = new GoogleService("blogger", "kuribo-example-1");
Feed resultFeed = myService.getFeed("http://kuribo-programming.blogspot.com/feeds/posts/summary?max-results=1&redirect=false", Feed.class);//フィード取得。実際のフィード URL は Datastore から取得。
Entry entry = resultFeed.getEntries().get(0);//フィード記載の第 1 エントリ
String title = entry.getTitle().getPlainText();//タイトル
String url = entry.getLink("alternate", "text/html").getHref();//URL
String content = entry.getTextContent().getContent().getPlainText();//コンテント
のようにしていたところ、タイトルや URL は取れるが、コンテント(ブログ投稿の本文)が取れない。結局なんだったかというと、アクセスするフィード URL が悪かった。

Blogger のブログ投稿フィードは full(全文)、summary(冒頭)、default(ブログオーナーが設定している全文・冒頭のどちらか)の 3 種類でアクセスできるが、summary でアクセスした場合本文は <content type='html'> に入らずに <summary type='text'> に入るということが判明。そりゃ取れないや。

通信量を減らそうと summary にしていたのがアダとなったみたい。
http://kuribo-programming.blogspot.com/feeds/posts/full?max-results=1&redirect=false
にアクセスすれば、問題なしにコンテントが取れた。ううむ。まだまだ Blogger 研究が足りない。

追記(2010-01-11):

と思っていたんだけれど…、full ではエラーが出るフィードがあることに、アプリを公開してから気づく。

Blogger でフィードの公開設定を「完全」でなく「先頭のみ」にしていると、full では取れない…。「完全」の場合は、full でも summary でもフィードを取れるので、勘違いしていた。

…ということで、default でタイトルや URL などの情報をまず取得しておいて、コンテントが null だった場合にはまた別の処理(代替の方法が今思いつかないけど)を加えるのがよさそう。

追記(2010-01-11):

…って、
String summary = entry.getSummary().getPlainText();
で、サマリー取れるじゃないか、と今さら気づく。今までなんだったんだと思いつつ、おかげで知らなかった Blogger の Atom フィードの仕様が少し分かったので、まあよしとしよう。

Zenback - Everyone's Related Posts