最近のDB開発とTengとちょっとだけRedis
Kyoto.pm #5
Jul 13th, 2013
profile
Redisの話はしません
Recent output
- DBIx::Schema::DSL
- Cache::Redis
- Config::PL
- Redis::LeaderBoard
- DBIx::FixtureLoader
- SQL::Maker::Plugin::JoinSelect
- Teng::Plugin::SearchJoined
- GitDDL::Migrator (書きかけ)
- PhiloPurple (?)
Teng and DBIx::Class
typester likes DBIC.
社内では、去年Tengに傾いたものの、今年に入って揺り戻しがあって、
DBICが増えてる。新規でTeng使ってるの多分僕だけ><
僕の中で大分ノウハウが固まってきたのでその辺の話。
DBICきらいじゃないので、結構ゴツメの使い方。
スキーマ(DDL)管理 - use DBIx::Schema::DSL;
定義
package MyApp::Schema;
use DBIx::Schema::DSL;
create_table player => columns {
primary_key 'id';
varchar 'name';
};
1;
出力
% perl -ML -E 'say MyApp::Schema->output' > sql/myapp.sql
DBIx::Schema::DSL
メリット
- Perlの定数連携(Defualt値とか)
- DRYに書ける
- Perlなのでシンタックスチェックが楽
- SQLのクオリティーが統一される
- 特にSQL::TranslatorフレンドリーなSQLが出力される
- GitDDLを使う上で重要
デメリット
Migration - use GitDDL;
- typester++
- 現在のDDLのバージョンをgitのハッシュを結びつけて管理する
- % git log -1 sql/myapp.sql を見る
- DEMO
- 運用向けに GitDDL::Migratorってのを今書いてる
Tengのスキーマ定義 - use Teng::Schema::Loader;
- せっかくDDL書いてるのに、Teng::Schema::Declare とか使うのめんどい
- プロダクションで使っても問題になってない
partition切ってて、pkが id, created_atの時にちょっとおかしくなった時があったので
無理やり定義書き換えてidのみをpkに定義しなおしたりとかしてる。詳しいことは忘れた
- SQL::Translator::Producer::Teng とか作ってもいいけど特に困ってないのでやってない
JOIN - use Teng::Plugin::SearchJoined;
- TengはJOINサポートしてない割り切った設計になっている(agree)
- ただ、joinしたSQL投げつつ、rowオブジェクトは個別に取るみたいなことはやりたい
my $itr = $teng->search_joined(
user_item => [
item => {'item.id' => 'user_item.item_id'},
], {
'user_item.user_id' => 10,
});
# $itr->suppress_object_creation(1);
while (my ($user_item, $item) = $itr->next) {
...
}
- search_by_sql みたいなのは諦めた
- DBICのprefetchとかと違って、発行されるSQLがイメージしやすくなっている。
Trigger - use Class::Method::Modifiers;
- created_at自動的に入れるとかそういうやつ
- Class::Method::Modifier使って代用してる
before on_update => sub {
...
};
ResultSet - use MyApp::DB::ResultSet;
DBICだと、Rowの集合みたいな概念があって結構便利。DBIC脳だと欲しくなる
- Teng::Iteratorを継承したMyApp::DB::ResultSetみたいなのを作る
- さらに、それを継承したMyApp::DB::ResultSet::Player クラスを作る
- $tengにresult_setってメソッド生やしてそのインスタンス返すようにする
my $rs = $teng->result_set('player');
$rs->single({id => 1});
は以下と等価
$teng->single(player, {id => 1});
例外処理 - use Exception::Tiny;
- yappo++
- Teng#handle_error をオーバーライドして例外投げるようにしてる
- 投げる例外を階層化しておくと便利
- MyApp::DB::Exception
- MyApp::DB::DuplicateException
トランザクションとの連携 - DBIx::TransactionManager::EndHook
- soh335++
- nested transactionで一番外側のコミットが走った時点で処理を走らせたい
- 逆にロールバック時は処理させたくない
- アイテム付与処理でちゃんとログを投げたい
- 得点更新処理でちゃんとRedisに投げたい
- 作者がDBICでもやろうとしてたけど断念してた
Teng便利!
ソースが把握しやすいし、拡張しやすいのが楽。
nekokakさん、cho45さん、tokuhiromさん、nihenさん、他のcontributorの皆様
ありがとうございます。
以上
ありがとうございました。
ご質問おねがいします!