[Bps-public-commit] rt-extension-rest2 branch, no-shared-connections, created. c3610c1a6a2460be4fd0c7044c40137e588fec7a
Alex Vandiver
alexmv at bestpractical.com
Sun Nov 12 23:56:08 EST 2017
The branch, no-shared-connections has been created
at c3610c1a6a2460be4fd0c7044c40137e588fec7a (commit)
- Log -----------------------------------------------------------------
commit c3610c1a6a2460be4fd0c7044c40137e588fec7a
Author: Alex Vandiver <alex at chmrr.net>
Date: Tue Nov 7 22:13:23 2017 -0500
Connect to the database at request start, not app init
rt-server takes pains to close down the database connection before
handing off control to the PSGI server, such that the database
connection is not preserved across the `fork`. DB connections which
are so shared result in undefined behavior -- postgres, for instance,
will reuse the same statement ids on the handle in different
processes, resulting in errors of the form:
DBD::Pg::st execute failed: ERROR: prepared statement "dbdpg_p4068_1" already exists
Unfortunately, `to_app` is called _after_ that preventative
disconnection has happened, so opening the database connection there
_does_ cause it to be shared -- with the aforementioned disasterous
results.
_Some_ call to `ConnectToDatabase` is required, because (at the time
of this commit, in <= 4.4) the only other explicit call to it is done
inside the Mason handler. Thus, without an explicit connect in this
extension, REST requests which happen to have not served a Mason page
will fail, due to lack of a database connection.
Move database connections to inside the PSGI handlers themselves, such
that the connection is opened inside the forked child, not the parent.
Just the addition in Auth is technically sufficient, since it
currently always runs before the main dispatcher -- however, we
include the connection there as a preventative measure. This is safe
because DBIx::SearchBuilder::Handle's Connect (and thus
RT::ConnectToDatabase) is a no-op if the connection is already live.
diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index fdecd03..ad88726 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -566,8 +566,6 @@ sub to_psgi_app { shift->to_app(@_) }
sub to_app {
my $class = shift;
- RT::ConnectToDatabase();
-
return builder {
enable '+RT::Extension::REST2::Middleware::ErrorAsJSON';
enable '+RT::Extension::REST2::Middleware::Log';
diff --git a/lib/RT/Extension/REST2/Dispatcher.pm b/lib/RT/Extension/REST2/Dispatcher.pm
index 1c7f780..166492e 100644
--- a/lib/RT/Extension/REST2/Dispatcher.pm
+++ b/lib/RT/Extension/REST2/Dispatcher.pm
@@ -43,6 +43,8 @@ sub to_psgi_app {
return sub {
my $env = shift;
+
+ RT::ConnectToDatabase();
my $dispatch = $self->_dispatcher->dispatch($env->{PATH_INFO});
return [404, ['Content-Type' => 'text/plain'], 'Not Found']
diff --git a/lib/RT/Extension/REST2/Middleware/Auth.pm b/lib/RT/Extension/REST2/Middleware/Auth.pm
index 875ebcf..7e33738 100644
--- a/lib/RT/Extension/REST2/Middleware/Auth.pm
+++ b/lib/RT/Extension/REST2/Middleware/Auth.pm
@@ -14,6 +14,7 @@ our @auth_priority = qw(
sub call {
my ($self, $env) = @_;
+ RT::ConnectToDatabase();
for my $method (@auth_priority) {
last if $env->{'rt.current_user'} = $self->$method($env);
}
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list