2012年2月7日火曜日

GoogleAppEngin(Python2.7)で、NDBによる非同期アクセスをお試し中


以下のサイトで、GAE/PのNDB(Next DB module)モジュールについて知りました。
https://sites.google.com/site/copypesouko/--manyuaru/datastore-plus-tutorial-ja
(ただ、今は【ここ】の情報が最新らしいですね)


全然ドキュメント読めていないのですが、(Python創始者のGuidoがせっせこ作っている)GAE/Pのデータストアで非同期アクセスを行う為のモジュールらしいですね。
(他にもコンテキスト処理?とかいろいろ出来るらしいけれど難しそうなので読んでません)

非同期にアクセスできるようにということは、
  • 複数のテーブルへのアクセスを並列実行できるので、反応を改善できることがある。
    (とはいえ、高価なデータストアに頻繁にアクセスする設計は間違っている気がします)
  •  書き込み結果を待たずにレスポンスを返せる。たとえば、ブログの更新のように、書き込みにほぼ成功するような更新なら、反応を早くできる。
    具体的には、データストアとMemcacheへの更新を並行して実施することで、データストアへの書き込みを待たずにキャッシュを使って更新結果を参照させることができる。
といったような効果を期待できますね!

ただ、この新しいモジュールではkey_nameを使えません(!)


from google.appengine.ext.ndb.model import (Model as _NdbModel,
                                            transactional)


class Model(NdbModel):
    u"""google.appengine.ext.db.Modelの動きを真似るラッピング
        ぶっちゃけ、こんなラッピングはしないほうが良いと思います
    """

    def __init__(self, **kwds):
        _kwds = kwds.copy()
        key_name = _kwds.get('key_name')
        if key_name != None:
            _kwds['id'] = key_name
            del(_kwds['key_name'])
        NdbModel.__init__(self, **_kwds)

    @classmethod
    def get_by_key_name(cls, key_name, **kwds):
        return cls.get_by_id(id=key_name, parent=kwds.get('parent'))

    @classmethod
    @transactional
    def insert_or_fail(cls, id_or_keyname, **kwds):
        u"""挿入して挿入された値を返します。
            キー重複は、何もせずにNullを返します。全然非同期じゃないし、動作未検証です。
        """
        entity = cls.get_by_id(id=id_or_keyname, parent=kwds.get('parent'))
        if entity is None:
            entity = cls(id=id_or_keyname, **kwds)
            entity.put()
            return entity
        return None


  • google.appengine.ext.dbをgoogle.appengine.ext.ndbにすると新しいモジュールでなんとなく動く(だいたいのAPIは上位互換)
  • key_nameとidの区別がなくなって、key_nameを使っていたところはidを使うようにAPIが変更されている
  • 普通にput()とかすると、これまでどおりの処理が行われる(全然非同期じゃない)
  • 非同期処理を行う場合は、
    k1 = Key('モデル名', id)
    f1 = k1.get_async() # これで、値の取得が開始される
    <何か処理をする>
    a1=f1.get_result() # 取得結果を受け取る

    ということらしいです。(key_nameが無くなったことを知るだけで2時間くらい消費してしまった・・・。へこみました)

    確かに、自動でidを振られた場合と 自分でkey_nameを指定した場合で、使うメソッドが違うのは格好が悪いので、このほうが良いですね。

    だから、上の例みたいなラッピングはしないことがお勧めです(!)
    普通にget_by_idで統一しましょう。


2012/02/25 追記:
あれ、でも別にNDB使わなくても、昔から非同期でデータストアにアクセスできるんですね・・・。
GAE/PのAsync Datastore APIの使い方


その他の追加の機能(yeildで非同期アクセスの結果を受け取る書き方や、taskletsとか)や、設計上の不合理、新バージョンを押し付けない、ってのがメインなんですね・・・。


うーん?別にそんなにNDBにこだわる必要もないような?

2012/03/05 追記:
ここの記事見るより、こっちを見ましょう!
http://najeira.blogspot.com/2012/02/google-app-engineapindb.html

0 件のコメント:

コメントを投稿