ラベル Google App Engine 1.2.0 の投稿を表示しています。 すべての投稿を表示
ラベル Google App Engine 1.2.0 の投稿を表示しています。 すべての投稿を表示

2009年5月2日土曜日

Google App Engineで、index.yamlに記述したインデックスが正しく生成されないときの対処法



Google App EngineでDatastoreのindexを利用したアプリケーションを作成していたのですが、運悪くindexの生成がいつまで経っても終わらない現象に見舞われてしまいました。データ量はたかだか1000件程度しかないのですが、3日経ってもindexの状態が"Building"のまま。Googleグループの書き込みを見ると(http://groups.google.co.jp/group/google-appengine/search?group=google-appengine&q=index)、indexの生成に失敗するというケースがたびたび発生しているようです。
  • index対象となるモデルの数は全く関係がない。数件しか保存されていないモデルに対してindexを生成しても発生する。
  • Googleの中の人曰く、indexはアプリ開発者全体で共有のindex作成クローラーによって行われているため、全体的に一度に利用する人が増えると不安定になる。

■まずはappcfg.pyを利用して、indexを消して再生成してみる
まずはindexをいったん消して再作成することにより、自分の手で解決できないかどうか試してみます。こちらの記事(http://osima.jp/blog/gae-index-in-trouble.html)を参考にさせていただきました。

まずは、index.yaml中のトラブルを起こしているindexをコメントアウトして削除し、
# Get a list of articles for "all" news page.
#- kind: Article
# properties:
# - name: is_duplicated
# - name: date_update
# direction: desc

ターミナルから以下のコマンドを実行。
appcfg.py --force vacuum_indexes /path/to/my/application

うまくいけば、管理者コンソールのIndexesメニューを開くと、対象のindexが"Deleting"という状態になっているはずですので、しばらく待って完全にindexが消えてからindex.yaml中で再度コメントアウトした記述を復活して、
appcfg.py update_indexes /path/to/my/application

を実行すれば、無事にindexが再作成されます。


■それでもだめなら、GoogleグループからGoogleの中の人にお願いして消してもらう
これでうまくいけば万事解決なのですが、ときどきこの方法ではうまくいかない場合があります。たとえば私の場合は、下記のようなエラーが出て上手くindexの削除が出来ませんでした。
akisute $ appcfg.py --force vacuum_indexes .
Fetching index definitions diff.
Deleting selected index definitions.
2009-05-02 12:48:33,476 WARNING appcfg.py:670 An index was not deleted. Most likely this is because it no longer exists.

kind: Article
properties:
- name: is_duplicated
- direction: desc
name: date_update

このような場合は、2009/05/02現在、米国本家のGoogle App Engineグループ(http://groups.google.co.jp/group/google-appengine)に直接お願いしてGoogleの中の人によってindexを削除してもらうしかないようです。以下の点に気をつけて新規ディスカッションを投稿すれば、スムーズにindexを削除してもらえると思います。
  • indexの生成がBuildingのまま進まない、24時間以上経っているのにうんともすんとも言わないことを明記する
  • appcfg.py vacuum_indexを試したけれどもうまくいかなかったことを明記する
  • 自分のアプリのApp IDを載せる
  • どのindexを削除してもらいたいかを載せる
参考までに、Google App Engineグループをindexで検索したときの結果(http://groups.google.co.jp/group/google-appengine/search?group=google-appengine&q=index)を載せてみました。同様の症状例がたくさん報告されていますので、それらの文面を適当にパクって参考にして投稿するのをおすすめします。
ただし、
Before posting, please read our Charter. Please note that due to recent spam activity, a member's first post will be moderated by one of the group's managers.
と注意書きがあるとおり、現在Spam対策として、最初の1回目の投稿はモデレータによってチェックされてしまい、すぐに投稿が反映されないみたいです。投稿されたとしても、いつindexの削除をしてくれるかはGoogleの中の人の気まぐれになってしまうので、解決には少々時間がかかります。


■英語が苦手なら、日本のコミュニティに助けてもらおう!
どうしても英語が苦手なら、日本のGoogle App Engineコミュニティ(http://groups.google.co.jp/group/google-app-engine-japan)に相談してみるとよいかもしれません。たとえば、こちらの投稿(http://groups.google.co.jp/group/google-app-engine-japan/browse_thread/thread/289b87a344715ea1/c9b5f8e394ac6a47)が参考になります。


■でも本当は
早くこんなトラブルが起こらないようなシステムになってほしいです><

2009年4月13日月曜日

Google App Engineのcronは、users.is_current_user_admin()では認証できない

先日作成したまとめの内容に間違いがありましたので、訂正してお詫びさせていただきます。

users.is_current_user_admin()を利用して、RequestHandler中にて起動ユーザーがcronかどうかを判定することが出来ると記事に掲載しておりましたが、
実際には出来ない模様です。

以下の方法にて検証を行いました。
1.まずはこのようなRequestHandlerを作る
class CronFetch(webapp.RequestHandler):
    def get(self):
        if not users.is_current_user_admin():
            logging.warn('CronFetch invoked by non-admin user:%s' % users.get_current_user())
            return
        logging.info('CronFetch begin')
        # この間に処理を記述
        logging.info('CronFetch end')

2.cron.yamlを記述する
cron:
- description: Test cron
  url: /cron/fetch
  schedule: every 1 hours
  timezone: Asia/Tokyo

3.本番環境にデプロイして、admin consoleから確認してみる


ごらんの通り、users.get_current_user()の結果がNoneになります。
おそらく2009/04/13現在では、Google公式のドキュメントにあるとおりapp.yamlで指定する以外にcron起動かどうかの認証を行う方法はなさそうです。

2009年4月9日木曜日

Google App Engineのcronサポートまとめ



http://code.google.com/intl/en/appengine/docs/python/config/cron.html

■注意
以下の情報は2009/04/09現在(Google App Engine 1.2.0.0)の情報です。皆様がごらんになっているときには古くなっている可能性があります。



■時間指定方法
cron.yamlを書く
本家cronとは記法が異なるが、本家cronとほぼ同様のスケジューリングが可能
起動タイムゾーンの指定も可能
cron:
- description: daily summary job
  url: /tasks/summary
  schedule: every 24 hours
- description: monday morning mailout
  url: /mail/weekly
  schedule: every monday 9:00
  timezone: Australia/NSW

■認証
cronによって起動されたURLはadminユーザーによって起動されるため、以下の
2種類の方法で認証が可能
app.yamlのhandlers要素にlogin: adminを指定する
application: hello-cron
version: 1
runtime: python
api_version: 1

handlers:
  - url: /report/weekly
    script: reports.py
    login: admin

2009/04/13追記、以下の方法は利用できません。詳しくはこちらの記事をご覧ください。ご迷惑をおかけいたしまして申し訳ありませんでした。
アプリケーションのRequestHandler内で、users.is_current_user_admin()を利用して判定する(こちらの方法は未確認)
from google.appengine.api import users

# ログインしていない場合やadmin以外の場合にはFalse。adminがログインしている場合のみTrue。
if users.is_current_user_admin():
    # cronジョブをここで実行
else:
    # エラー画面を表示するなど

さらにcronはURLを起動する際にHTTPリクエストヘッダーに以下の要素を付けるため、RequestHandler内でヘッダをチェックすることが出来る
X-AppEngine-Cron: true

■cronタスクの管理方法
cronタスクをアップロードするには、通常のアプリケーションをアップロードするときと同様に以下のコマンドを実行すれば、アプリケーションと一緒にアップロードされる
appcfg.py update

cronタスクだけをアップロードしたい場合場合は以下のコマンドを実行
appcfg.py update_cron

cronタスクを削除したい場合は、cron.yamlを以下のように書き換えてからアップロードすればよい
cron: 

以下のコマンドを実行すれば、現在のcronの設定状況を見ることが出来る(ただし、タイムゾーンを扱う場合はpytzライブラリが必要)
appcfg.py cron_info

■制限
  • 今のところPython版のみ(Java版はない)Java版もある。Java版はcron.xmlを記述する。http://code.google.com/intl/ja/appengine/docs/java/config/cron.html
  • タスクは20個まで
  • 最短実行間隔は1分
  • cron.yamlから起動できるのは自アプリのURLのみ。人のアプリを起動したり、全然関係ないURLを指定したり、シェルスクリプトを起動したりは出来ない
  • cronから対象URLを起動した場合のCPU時間・通信量もすべて従量対象になる