DBICでバックエンドとの接続が切れた時などに再接続する際の挙動が、0.07x と 0.08x で異なるようなのでメモ。確認したのは PostgreSQL の場合です。
動作確認スクリプトは末尾に。動作は以下の流れ。
- connect()
- resultset から find()
- バックエンドをkill
- resultset から find()
0.07006 の場合。
$ perl -IDBIx-Class-0.07006/blib/lib/ dbic.pl DBIx::Class->VERSION: 0.07006 get ok 19115 killing 19115 FATAL: terminating connection due to administrator command get ok
正常に再接続可能。
0.08007 の場合。
$ perl -IDBIx-Class-0.08007/blib/lib/ dbic.pl DBIx::Class->VERSION: 0.08007 get ok 19121 killing 19121 FATAL: terminating connection due to administrator command DBIx::Class::ResultSet::find(): DBI Exception: DBD::Pg::st execute failed: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request. [for Statement "SELECT me.id, me.foo FROM foo me WHERE ( ( me.id = ? ) )" with ParamValues: 1='1'] at dbic.pl line 25
2回目の find で再接続出来なくてエラー(例外)になる。
該当する変更は http://search.cpan.org/src/ASH/DBIx-Class-0.08007/Changes を見る限り、以下の部分かなあ。
0.07999_01 2006-10-05 21:00:00 - Storage::DBI now uses exceptions instead of ->ping/->{Active} checks
で、これは $schema->storage->ensure_connected() を呼んで、接続状態を確認することで回避できた。
Catalyst から使う場合は、begin か prepare あたりで呼んでやればいいかな。
#!/usr/bin/perl use strict; use Perl6::Say; package MySchema; use base qw/ DBIx::Class::Schema::Loader /; __PACKAGE__->loader_options(); package main; our $schema = init(); get(); kill_backend(); get(); sub init { say "DBIx::Class->VERSION: ", DBIx::Class->VERSION; MySchema->connect( 'dbi:Pg:dbname=fujiwara', 'fujiwara', '', { RaiseError => 1, AutoCommit => 0, } ); } sub get { $schema->storage->ensure_connected() if $ENV{ENSURE}; eval { $schema->resultset('Foo')->find(1) }; say $@ ? $@ : "get ok"; $schema->txn_commit(); } sub kill_backend { my $pid = <>; chomp $pid; say "killing $pid"; qx{ kill $pid }; }