Hatena::Groupcatalyst

dann@catalyst このページをアンテナに追加 RSSフィード

2008-05-14

DBIx::Class:Schema::Slave

|  DBIx::Class:Schema::Slave - dann@catalyst を含むブックマーク はてなブックマーク -  DBIx::Class:Schema::Slave - dann@catalyst  DBIx::Class:Schema::Slave - dann@catalyst のブックマークコメント

DBIx::Class:Schema::Slave について

http://hibinokoto.jp/archives/2008/05/post-263.html

Blog::Slaveのように書けばいいだけっていうのはDRYでいいかもしれないなぁ。今までは単にコネクションを分けるだけでいいんじゃないかと思っていたのだけれど、こっちのほうがずっと綺麗。

日記に書いておかないと忘れそうなのでメモ

oiouxfawoiouxfaw2011/03/24 05:26SPSwuq <a href="http://chdglodetxpl.com/">chdglodetxpl</a>, [url=http://vrjfkcyyoxop.com/]vrjfkcyyoxop[/url], [link=http://dgfqtusveujx.com/]dgfqtusveujx[/link], http://pcdbfdvwdlgt.com/

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080514

2008-03-30

Migration

| 00:12 |  Migration - dann@catalyst を含むブックマーク はてなブックマーク -  Migration - dann@catalyst  Migration - dann@catalyst のブックマークコメント

http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Schema/Versioned.pm

多分、これがActive::RecordのMigrationに対応するものになっていくんだろうという話。ただ、誰もまだ使ってないといってた。

ZIGOROuZIGOROu2008/03/31 16:20今度、どこかしらに網羅的に分かりやすいエントリ挙げますー > OpenID

danndann2008/03/31 17:56おぉ。多分、みんな知りたいんじゃないかと!楽しみにしてます。

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080330

2008-03-29

プロセス or リクエスト単位でのconnectionの共有

| 13:53 |  プロセス or リクエスト単位でのconnectionの共有 - dann@catalyst を含むブックマーク はてなブックマーク -  プロセス or リクエスト単位でのconnectionの共有 - dann@catalyst  プロセス or リクエスト単位でのconnectionの共有 - dann@catalyst のブックマークコメント

MySQLでconnectionをどれくらいの数まで張ってパフォーマンスが維持できるのかわからないけど、300程度なら全然パフォーマンス上も問題なく動くってことを聞いた。だから、プロセス単位でconnectionを保持しても結構なアクセスをさばけるらしい。

アプリケーションサーバー数が増えていったときに、プロセス数に応じてconnectionを維持する数が増加していくとボトルネックになるといっても、それは割に後の段階なのかもしれないなぁと思った。そういう段階では、リクエスト単位でDBのハンドラを保持することで、最大接続数を抑えられるのかもしれない。

connectionを張る単位

| 13:53 |  connectionを張る単位 - dann@catalyst を含むブックマーク はてなブックマーク -  connectionを張る単位 - dann@catalyst  connectionを張る単位 - dann@catalyst のブックマークコメント

request単位

  • Apacheのpnotesにいれておけばよいというところまで分かった。requestにローカルな変数を作れるのか。やっぱりあった!こないだ、Catalyst::Pluginでうんぬんっていうのは、考え方が間違いだった。

大体、以下のような感じでpnotesにつっこんどけばよさそうだ。

sub dbh {
  my $dbh = Apache->request()->pnotes('dbh');
  if (!$dbh) {
    $dbh = new_dbh();
    Apache->request()->pnotes('dbh', $dbh);
  }
  return $dbh;
}

プロセス単位

  • Apache::DBIと同様に起動時にdbhを保持しておくっていうのはあるのかもしれない

DBIx::Classのコード中では特にこのdbhの保持単位っていうのは、どこに書いてあるのかわからなかった。

リクエスト単位でDBのハンドらを保持する方法は?

| 13:53 |  リクエスト単位でDBのハンドらを保持する方法は? - dann@catalyst を含むブックマーク はてなブックマーク -  リクエスト単位でDBのハンドらを保持する方法は? - dann@catalyst  リクエスト単位でDBのハンドらを保持する方法は? - dann@catalyst のブックマークコメント

connect_info([ sub { DBI->connect(...) } ]);

DBIx::Class::Storage::DBIの_connectメソッド。connect_infoの一番目の引数がコードレファレンスの場合にはそれが実行されるみたいだから、ここでdbhの返しかたを変えれば、リクエスト単位、プロセス単位の切り替えはできるんじゃないかと思った。

sub _connect {
  (snip)
  eval {
    if(ref $info[0] eq 'CODE') {
       $dbh = &{$info[0]}
    }
    else {
       $dbh = DBI->connect(@info);
    }

以下のような感じで書けるってことらしい。connect_infoに渡すcode_ref中に、mod_perlだったらApacheのpnotesから取得するとかいうコードを書いとけばいいのかな。プロセス単位で保持する場合でもここでよさそう。

  # Connect via subref
  ->connect_info([ sub { DBI->connect(...) } ]);

  # Subref + DBIC-specific connection options
  ->connect_info(
    [
      sub { DBI->connect(...) },
      {
          quote_char => q{`},
          name_sep => q{@},
          on_connect_do => ['SET search_path TO myschema,otherschema,public'],
          disable_sth_caching => 1,
      },
    ]
  );

storageを設定するところのコードを後で読んでおけば、これで大体いけるんじゃないかなぁ。TODOリストに積む。

vkgtarovkgtaro2008/03/30 22:05おつでしたー。
そしてお邪魔しましたー。
奥様にもよろしくお伝えください。

danndann2008/03/30 23:57
おつでしたー。また遊びにきてくださーい。では。

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080329

2008-03-20

DBICでマスターとスレーブの振り分けをやるのはどこでやる?

| 02:48 |  DBICでマスターとスレーブの振り分けをやるのはどこでやる? - dann@catalyst を含むブックマーク はてなブックマーク -  DBICでマスターとスレーブの振り分けをやるのはどこでやる? - dann@catalyst  DBICでマスターとスレーブの振り分けをやるのはどこでやる? - dann@catalyst のブックマークコメント

どこのレイヤでやるのが美しいんだろうかと思っていた。Readをスレーブに、Writeをマスターに振り分けるのであれば、どうもStorage::DBIでやるのが綺麗なように見える。

CPANを探してみると、Storage::DBI::Replicationというモジュールがあった。ざっとコードをみた感じでは、WriteはMasterに、ReadはSlaveにということだけしかやってないみたい。

ただ、これだと、レプリケーションのタイムラグがあった場合、WRITE直後のREADは失敗するから現実的には使えないんじゃないかと思った。レプリケーションが同期ってのも現実的じゃないから、こういうのはどこでハンドリングするべきなんだろうなぁというのが疑問。

Masterが1台であれば、Storage::DBIレベルで頑張るのがいいんじゃないかなぁという気がするのだけれど、どうなんだろう。マスター分割が必要になると、Storage::DBIレベルでは吸収できなそうだから、結局アプリケーションレベルでMasterとSlaveの振り分けが必要になってくるのかも、と思うとそもそもDBのスケールを考えるようなレベルのアプリケーションを作る場合には、Storage::DBIのレイヤでやるっていうのもあんまよくないのかな。

この辺の情報は、あまり世間にはでていないような気がするなぁ。綺麗に解決する解というのはないものかなぁと。

# id:hidedenに色々と教えてもらって、*現実解*は大体どういうものかは分かって、実装のイメージも大体できたんだけれど。hideden++

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080320

2008-03-17

Fixtureの読み込みとダンプ

| 21:30 |  Fixtureの読み込みとダンプ - dann@catalyst を含むブックマーク はてなブックマーク -  Fixtureの読み込みとダンプ - dann@catalyst  Fixtureの読み込みとダンプ - dann@catalyst のブックマークコメント

DBIx::Class::Fixtures

http://search.cpan.org/~lsaunders/DBIx-Class-Fixtures/lib/DBIx/Class/Fixtures.pm

ダンプもできるのがいい。

この前書いたモデルのテストのベースクラスの、fixtureを読み込む部分を書き換えることにしよう。

http://catalyst.g.hatena.ne.jp/dann/20080313/1205416454

テストデータは、DBIx::Class::Fixturesでダンプして作って、テストケース側では、それを読み込むと。ベーシックなやつは、fixtureは手書きで。そんな感じかな。

テスト用のデータベースクラスにFixtureのロード機能もまかせちゃって、テストケース側ではそのテスト用データベースクラスだけuseするっていうほうが、美しいかもしれないなぁ。そこはもう少し検討。

KerrynKerryn2011/12/27 20:55Which came first, the prboelm or the solution? Luckily it doesn't matter.

hfdcpsrqzshfdcpsrqzs2011/12/28 22:452lU7Ej , [url=http://hffosourukyv.com/]hffosourukyv[/url], [link=http://ivjsgtvhzfak.com/]ivjsgtvhzfak[/link], http://smraetuehzze.com/

gpzayorgpzayor2011/12/29 19:028nYjn5 <a href="http://ncmyvxwidlkt.com/">ncmyvxwidlkt</a>

トラックバック - http://catalyst.g.hatena.ne.jp/dann/20080317

2008-03-13

モデルのfunctional test

| 22:54 |  モデルのfunctional test - dann@catalyst を含むブックマーク はてなブックマーク -  モデルのfunctional test - dann@catalyst  モデルのfunctional test - dann@catalyst のブックマークコメント

DBICx::TestDatabaseとTest::Fixture::DBIC::Schemaを使ってモデルのテストをしてみた。大体イメージどおりの感じで使えるかなぁと。

テスト用のDBクラス

DBICx::TestDatabaseを使っている。将来的に拡張する可能性があるため継承をしておく。

package MyApp::Test::DBIC::Database;
use strict;
use warnings;
use base qw(DBICx::TestDatabase::Subclass MyApp::Schema);

1;

モデルのテスト用のベースクラス。

setupでfixture作成. Test::Fixture::DBIC::Schemaでfixtureのロード.

package MyApp::Test::Model::Base;
use strict;
use warnings;
use base qw/Test::Class/;
use MyApp::Test::DBIC::Database;
use Test::Fixture::DBIC::Schema;
use File::Spec;

sub setup: Test(setup) {
    my $self = shift;
    $self->_make_fixture($self->model,$self->fixture);
}

sub _make_fixture {
    my $self = shift;
    my $model = shift;
    my $fixture = shift;

    $self->{schema} = MyApp::Test::DBIC::Database->connect();
    my $fixture_path = File::Spec->catfile('t','fixtures', $self->fixture . ".yaml");
    my $data = construct_fixture(
        schema  => $self->{schema},
        fixture => $fixture_path,
    );
    $self->{model} = $self->{schema}->resultset($model);
}

sub teardown : Test(teardown) {
};

sub fixture {
    my $self = shift;
    die "need to override";
}

sub model {
    my $self = shift;
    die "need to override";
}

1;

テストコード

モデルのテストクラスは、MyApp::Test::Model::Baseを継承する。fixtureとmodelメソッドをオーバーライドすると、該当するfixtureがロードされる。各テストメソッド間では、テーブルの内容は削除されるので、メソッド間に依存関係はない。

#!perl
use strict;
use warnings;

MyApp::Test::Model::Feeds->runtests;

package MyApp::Test::Model::Feeds;
use base qw/MyApp::Test::Model::Base/;
use Test::More;

sub test_feed : Tests {
    my $self = shift;

    my $feed = $self->{model}->find(1);
    is $feed->id, 1;
    is $feed->feedlink, "http://example.net/rss";
}

sub fixture {
    return "feeds";
}

sub model {
    return "Feeds";
}

1;

fixture

t/fixtures/feeds.yaml

t/fixturesに置くのは、Railsのパクリ。

- schema: Feeds
  name: entry1
  data:
    id: 1
    feedlink: http://example.net/rss
    link: http://example.net
    title: Example
    description: This is Example site
    subscribers_count: 1

- schema: Feeds
  name: entry2
  data:
    id: 2
    feedlink: http://example2.net/rss
    link: http://example2.net
    title: Example2
    description: This is Example2 site
    subscribers_count: 2

検討事項

  • SQLiteでテストする必要がなければ、Test::Fixture::DBIC::Schemaだけでいいなぁ。ここらはSQLiteでのテストが必要かも含めて少し検討かな。
    • モデルのテストはSQLiteだけ、結合テストのときだけMySQLでという選択肢もありえるかもしれない。
  • DB使わないでモデルをテストするユニットテスト用のベースクラスも作成する
  • fixture作るのが面倒. SQLでデータ流し込んで、YAMLDBからDumpする仕組みを用意したほうがいいかも

CarrieCarrie2011/08/02 22:59This website makes tghins hella easy.

uqkmntyamuqkmntyam2011/08/04 23:04LV0GWW , [url=http://ssntczkglidm.com/]ssntczkglidm[/url], [link=http://ybwyazadkvxq.com/]ybwyazadkvxq[/link], http://tnhbhzdyqjob.com/

xixywzesscxxixywzesscx2011/08/05 22:32WrlimC , [url=http://uxhjuacepxav.com/]uxhjuacepxav[/url], [link=http://mgietljruzer.com/]mgietljruzer[/link], http://tumkfemdvdet.com/