Explorar el Código

Make web-simple resilient against database connection errors (#3080)

Previously, shortly after the database tests began to run, web-simple
would say that its connection to MySQL had been lost with many
occurrences of this error message:

  Server web-simple: DBD::mysql::st execute failed: Lost connection to
  MySQL server during query at ...

Then for the remainder of the test it would print this error message:

  Server web-simple: DBD::mysql::st execute failed: MySQL server has
  gone away at ...

I think the database handle (the `$dbh` variable) would become corrupt
somehow and the application would never attempt to reconnect.  Now,
instead of using `DBI->connect` once we use `DBI->connect_cached` each
time we want a connection, which should reuse one connection as long as
it's active and reconnect when it breaks.  And we use
`$dbh->prepare_cached(...)` instead of `$dbh->prepare(...)` so that we
don't necessarily create a new statement on each request.

As a minor change, the database tests are now actually using the id
column values they read from the world table instead of ignoring the ids.
I'm not sure if this is a true requirement of the database tests, but it
feels like it should be.

The indentation in `app.pl` was inconsistent so many of the line changes
in this commit are indentation fixes.

I updated web-simple's cpan dependencies because why not.
Michael Hixson hace 7 años
padre
commit
9f8b5b5e29
Se han modificado 2 ficheros con 49 adiciones y 48 borrados
  1. 44 42
      frameworks/Perl/web-simple/app.pl
  2. 5 6
      frameworks/Perl/web-simple/setup.sh

+ 44 - 42
frameworks/Perl/web-simple/app.pl

@@ -3,52 +3,54 @@ use Web::Simple;
 use JSON::XS;
 use DBI;
 
-my $dsn = "dbi:mysql:database=hello_world;host=localhost";
-my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', { RaiseError => 1 });
-my $sth = $dbh->prepare('SELECT * FROM World where id = ?');
+sub get_database_handle {
+    DBI->connect_cached('dbi:mysql:database=hello_world;host=TFB-database', 'benchmarkdbuser', 'benchmarkdbpass', { RaiseError => 1 });
+}
 
 sub dispatch_request {
- sub (/json) {
-    [ 200, [ 'Content-type' => 'application/json', ],
-      [ encode_json({ message => 'Hello, World!' }) ] ];
-  },
-  sub (/db) {
-    my $id = int(rand 10000) + 1;
-    my $rand;
-    $sth->execute($id);
-    $sth->bind_col(2, \$rand);
-    if ( my @row = $sth->fetch ) {
-       [ 200, [ 'Content-type' => 'application/json', ], [ encode_json({ id => $id, randomNumber => $rand })] ];
-    }
-  },
-  sub (/query + ?queries~) {
-    my ($self, $queries) = @_;
-    $queries //= 1;
-    $queries = 1 if ( $queries !~ /^\d+$/ || $queries < 1 );
-    $queries = 500 if $queries > 500;
-    my $rand;
-    my @response;
-    if ($queries == 1) {
-        my $id = int(rand 10000) + 1;
-        $sth->execute($id);
-        $sth->bind_col(2, \$rand);
-        if ( my @row = $sth->fetch ) {
-            [ 200, [ 'Content-type' => 'application/json', ], 
-              [ encode_json([{ id => $id, randomNumber => $rand }])] ];
+    sub (/json) {
+        [ 200, [ 'Content-type' => 'application/json', ], [ encode_json({ message => 'Hello, World!' }) ] ];
+    },
+    sub (/db) {
+        my ($id, $random_number);
+        my $dbh = get_database_handle;
+        my $sth = $dbh->prepare_cached('SELECT id, randomNumber FROM World where id = ?');
+        $sth->execute(int(rand 10000) + 1);
+        $sth->bind_columns(\$id, \$random_number);
+        $sth->fetch;
+        $sth->finish;
+        [ 200, [ 'Content-type' => 'application/json', ], [ encode_json({ id => $id, randomNumber => $random_number })] ];
+    },
+    sub (/query + ?queries~) {
+        my ($self, $queries) = @_;
+        $queries //= 1;
+        $queries = 1 if ($queries !~ /^\d+$/ || $queries < 1);
+        $queries = 500 if $queries > 500;
+        if ($queries == 1) {
+            my ($id, $random_number);
+            my $dbh = get_database_handle;
+            my $sth = $dbh->prepare_cached('SELECT id, randomNumber FROM World where id = ?');
+            $sth->execute(int(rand 10000) + 1);
+            $sth->bind_columns(\$id, \$random_number);
+            $sth->fetch;
+            $sth->finish;
+            [ 200, [ 'Content-type' => 'application/json', ], [ encode_json([{ id => $id, randomNumber => $random_number }])] ];
+        }
+        else {
+            my @worlds;
+            for (1 .. $queries) {
+                my ($id, $random_number);
+                my $dbh = get_database_handle;
+                my $sth = $dbh->prepare_cached('SELECT id, randomNumber FROM World where id = ?');
+                $sth->execute(int(rand 10000) + 1);
+                $sth->bind_columns(\$id, \$random_number);
+                $sth->fetch;
+                $sth->finish;
+                push @worlds, { id => $id, randomNumber => $random_number };
+            }
+            [ 200, [ 'Content-type' => 'application/json', ], [ encode_json(\@worlds)] ];
         }
     }
-    else {
-      for ( 1 .. $queries ) {
-          my $id = int(rand 10000) + 1;
-          $sth->execute($id);
-          $sth->bind_col(2, \$rand);
-          if ( my @row = $sth->fetch ) {
-              push @response, { id => $id, randomNumber => $rand };
-          }
-      }
-      [ 200, [ 'Content-type' => 'application/json', ], [ encode_json(\@response)] ];
-    }
-  }
 }
 
 __PACKAGE__->run_if_script;

+ 5 - 6
frameworks/Perl/web-simple/setup.sh

@@ -1,17 +1,16 @@
 #!/bin/bash
 
-sed -i 's|localhost|'"${DBHOST}"'|g' app.pl
 sed -i 's|server unix:.*/FrameworkBenchmarks/web-simple|server unix:'"${TROOT}"'|g' nginx.conf
 
 fw_depends perl nginx
 
 cpanm --notest --no-man-page  \
-    Web::[email protected]1 \
-    [email protected]6 \
-    DBD::[email protected]33 \
-    [email protected]39 \
+    Web::[email protected]3 \
+    [email protected]7 \
+    DBD::[email protected]43 \
+    [email protected]44 \
     [email protected] \
-    JSON::[email protected]2
+    JSON::[email protected]4
     
 nginx -c $TROOT/nginx.conf