Sfoglia il codice sorgente

Add *rudimentary* support for uwsgi, can still squeeze out some juice here

George Baugh 3 anni fa
parent
commit
12f79da1e7
5 ha cambiato i file con 53 aggiunte e 8 eliminazioni
  1. 1 0
      Makefile
  2. 8 0
      Readme.md
  3. 18 0
      config/tcms.ini
  4. 24 8
      lib/TCMS.pm
  5. 2 0
      tcms

+ 1 - 0
Makefile

@@ -31,6 +31,7 @@ prereq-debian: prereq-debs prereq-perl prereq-frontend prereq-node
 prereq-debs:
 	sudo apt-get update
 	sudo apt-get install -y sqlite3 nodejs npm libsqlite3-dev libdbd-sqlite3-perl cpanminus starman libxml2 curl         \
+		uwsgi uwsgi-plugin-psgi \
 	    libtext-xslate-perl libplack-perl libconfig-tiny-perl libdatetime-format-http-perl libjson-maybexs-perl          \
 	    libuuid-tiny-perl libcapture-tiny-perl libconfig-simple-perl libdbi-perl libfile-slurper-perl libfile-touch-perl \
 	    libfile-copy-recursive-perl libxml-rss-perl libmodule-install-perl libio-string-perl                             \

+ 8 - 0
Readme.md

@@ -81,6 +81,14 @@ Planned Development:
 * Elasticsearch - Documents are ideally indexed in a search engine, should be nice and fast too.
 * Git - More for the APE crossover
 
+Supported PSGI servers
+======================
+
+Starman and uWSGI
+
+In production, I would expect you to run under uWSGI, and the `tcms` command in the TLD runs this.
+Otherwise, you can run `www/server.psgi` to start starman normally.
+
 Ideas to come:
 =============
 

+ 18 - 0
config/tcms.ini

@@ -0,0 +1,18 @@
+# default uWSGI configuration file for tCMS
+[uwsgi]
+
+master = 1
+processes = 5
+http-socket = :5000
+plugin = psgi
+socket = tcms.sock
+
+# Reporting
+memory-report = 1
+
+# TODO figure out why things break without this
+lazy-apps = 1
+
+# TODO use mount options to do virtual hosting
+psgi = www/server.psgi
+perl-auto-reload = 1

+ 24 - 8
lib/TCMS.pm

@@ -152,12 +152,15 @@ sub app {
         return _forbidden($query);
     }
 
+    my $streaming = $env->{'psgi.streaming'};
+    $query->{streaming} = $streaming;
+
     # If we have a static render, just use it instead (These will ALWAYS be correct, data saves invalidate this)
     # TODO: make this key on admin INSTEAD of active user when we add non-admin users.
     $query->{start} = $start;
     if (!$active_user && !$has_query) {
-        return _static("$path.z",$start) if -f "www/statics/$path.z" && $deflate;
-        return _static($path,$start) if -f "www/statics/$path";
+        return _static("$path.z",$start, $streaming) if -f "www/statics/$path.z" && $deflate;
+        return _static($path,$start, $streaming) if -f "www/statics/$path";
     }
 
     # Handle HTTP range/streaming requests
@@ -173,9 +176,6 @@ sub app {
         } split(/,/, $range) );
     }
 
-    my $streaming = $env->{'psgi.streaming'};
-    $query->{streaming} = $streaming;
-
     return _serve("www/$path", $start, $streaming, \@ranges, $last_fetch, $deflate) if -f "www/$path";
 
     #Handle regex/capture routes
@@ -225,8 +225,8 @@ sub app {
 };
 
 sub _generic($type, $query) {
-    return _static("$type.z",$query->{start}) if -f "www/statics/$type.z";
-    return _static($type, $query->{start}) if -f "www/statics/$type";
+    return _static("$type.z",$query->{start}, $query->{streaming}) if -f "www/statics/$type.z";
+    return _static($type, $query->{start}, $query->{streaming}) if -f "www/statics/$type";
     my %lookup = (
         notfound => \&Trog::Routes::HTML::notfound,
         forbidden => \&Trog::Routes::HTML::forbidden,
@@ -252,7 +252,7 @@ sub _toolong() {
     return _generic('toolong', {});
 }
 
-sub _static($path,$start,$last_fetch=0) {
+sub _static($path,$start,$streaming,$last_fetch=0) {
 
     # XXX because of psgi I can't just vomit the file directly
     if (open(my $fh, '<', "www/statics/$path")) {
@@ -275,6 +275,22 @@ sub _static($path,$start,$last_fetch=0) {
         my $tot = tv_interval($start) * 1000;
         $headers_parsed->{'Server-Timing'} = "static;dur=$tot";
 
+        #XXX uwsgi just opens the file *again* when we already have a filehandle if it has a path.
+        # starman by comparison doesn't violate the principle of least astonishment here.
+        # This is probably a performance optimization, but makes the kind of micromanagement I need to do inconvenient.
+        # As such, we will just return a stream.
+
+        return sub {
+            my $responder = shift;
+            #push(@headers, 'Content-Length' => $sz);
+            my $writer = $responder->([ $code, [%$headers_parsed]]);
+            while ( read($fh, my $buf, $CHUNK_SIZE) ) {
+                $writer->write($buf);
+            }
+            close $fh;
+            $writer->close;
+        } if $streaming;
+
         return [$code, [%$headers_parsed], $fh];
     }
     return [ 403, ['Content-Type' => $Trog::Vars::content_types{plain}], ["STAY OUT YOU RED MENACE"]];

+ 2 - 0
tcms

@@ -0,0 +1,2 @@
+#!/bin/bash
+uwsgi --ini config/tcms.ini --perl-auto-reload=1