GAE/Pythonでデータベースを使う場合は、google.appengine.extパッケージのdbモジュールを使います。インスタンス間の関係は、ReferencePropertyを使ってあらわすのが自然なので、連番を振る必要があることはめったにないのですが、昨日公開した、URL短縮サービスでは、連番が必要になりました。しかし、GAEのデータストアには連番を振る機能が用意されていなかったので自作することにしました。
※実は連番の実装がURL短縮サービスで一番苦戦した部分です。
連番生成
連番を作る手順は以下の通りです。
- 過去に作成した最大の番号を取り出す
- 1で取り出した番号より1大きい値を「新しい値」とする
- 2で作成した「新しい値」を保存する
すごく単純な操作なのですが、マルチスレッド環境で確実に動作させるためにはトランザクションを使わないといけません。トランザクションを利用したコードは以下の通りです。1-3までの操作を、prodecureという関数で定義し、それをdb.run_in_transaction()で実行しています。こうすることで、procedure内の操作がトランザクション内で実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 | def getNextNum(): def procedure(): num = MAXNUM.get_by_key_name('URL') if num is None: num = MAXNUM(key_name = 'URL') num.max_num = num.max_num + 1 num.put() return num.max_num return db.run_in_transaction(procedure) class MAXNUM(db.Model): max_num = db.IntegerProperty(default = 0) |