Thanks for all the valuable suggestions.
1. DBIx::Connector
Stefan shared his suggestion to use 'ping' method to check connection.
so, i tried a cpan module : DBIx::Connector, which seems to have a wrapped ping-like mechanism.
here's the application class, using attr method :
package App1;
use Kelp::Base 'Kelp';
use DBIx::Connector;
attr connector => sub { DBIx::Connector
->new("dbi:mysql:cs", "root", "", {RaiseError => 1}) };
sub build {
my $self = shift;
my $r = $self->routes;
$r->add('/dbTest', sub {
my $self = shift;
my $row = $self->connector->dbh->selectall_arrayref(
"select id, connection_id() from admin");
return join( ", ", @{ $row->[0] } ). "\n";
});
}
1;
then, several http requests were issued/sent to test it :
1, 5
we got a persistent connection (tcp/socket mysql-client connection was still the same between different http request; it can be observed by mysql-connection-id which was always : 5).
then, simulating a database-down event / network problem :
$ mysql -u root -e 'kill 5'
issuing http requests again :
1, 7
the app automatically got a new db connection (connection-id changed), and this new connection is still persistent (connection id was always the same : 7)
2. DBI's connect_cached method
Hi, Alvar, thanks for pointing this. 'connect_cached' can also be used for persistent connection. the application class :
package App1;
use Kelp::Base 'Kelp';
use DBI;
sub dbh { shift->stash->{_dbh} ||= DBI
->connect_cached("dbi:mysql:cs", "root", "", {RaiseError => 1}) }
sub build {
my $self = shift;
my $r = $self->routes;
$r->add('/dbTest', sub {
my $self = shift;
my $row = $self->dbh->selectall_arrayref(
"select id, connection_id() from admin");
return join( ", ", @{ $row->[0] } ). "\n";
});
}
1;
issuing several http requests :
1, 2
it's persistent (connection-id was always: 2).
then, forcing to close socket connection :
$ mysql -u root -e 'kill 2'
1, 4
successfully automatically reconnected to db, persistently.
3. lite ORM
in a medium-large web app development, chances are we will use an ORM.
Using ORM can also help us to provide friendly/easy development environment for junior developers or beginners (for example: dynamic where clause, paging, etc.)
here's what i've tried using DBIx::Lite :
package App1;
use Kelp::Base 'Kelp';
use DBIx::Lite;
attr connector => sub { DBIx::Connector
->new("dbi:mysql:cs", "root", "", {RaiseError => 1}) };
sub db { DBIx::Lite->new(dbh => shift->connector->dbh) }
sub build {
shift->routes->add('/dbTest', sub {
my $row = shift->db
->table("admin")
->select_also(\"connection_id() as conn_id")
->single();
return join( ", ", $row->id, $row->conn_id ). "\n";
});
}
1;
testing persistent connection
1, 4
testing dropped/killed db connection :
$ mysql -u root -e 'kill 4'
1, 6
thanks again for all, i think i've got a safe persistent db connection.
about PostgreSQL, i've seen techempower.com's benchmark results (we can find benchmark results for kelp too in there), and from the results, we can quickly/roughly summarized that PostgreSQL nowadays is also very good in terms of speed/performance.