PSGI - constructor for each prefork-child

109 views Asked by At

I have question about constructor for each child after forking. For example:

warn "INIT : Parent : ".$$;
my $stash;
sub {
    unless($stash) {
        warn "init : Child : ".$$;
        $stash = {
            dbh => {}
        };
    }
    return [ 200, ['Content-Type' => 'text/plain'], ['Hello World'] ];
}

This code is working but this is bad practice. I would like create something like that

package Myapp;
sub new {
    my $class=shift;
    my $self=bless {
        dbh =>{},
    }, $class;

}
sub call {
    my ($self, $env) = @_;
    # body
    return [ 200, ['Content-Type' => 'text/plain'], ['Hello World'] ];    }

i hope somebody an explain me how it can working by prefork-server like Starman or Feersum ( But one guy "Audrey Tang" tell me that Feersum it not good idea for that )

So - thanks for yours answers

1

There are 1 answers

0
ccm On

Your .psgi could be as simple as this:

my $obj = Myapp->new;

my $app = sub {
    my $env = shift;

    return $obj->call($env);
};

If run with starman, Myapp will be instantiated each time Starman forks, and your instance's call method will be called on each request. This works because, by default, your .psgi file is loaded by the child processes.

If run with starman --preload-app, Myapp will be instantiated only once (in the parent) and all children will share the same instance. You may get memory savings by doing this, but your app will need to take care not to mess with other siblings by using shared connections. See https://metacpan.org/pod/distribution/Starman/script/starman#preload-app for more information.

Here's another idea for your .psgi:

my %objects;

my $app = sub {
    my $env = shift;
    my $obj;

    if ($objects{$$}) {
        $obj = $objects{$$};
    }
    else {
        $obj = Myapp->new;
        %objects = ($$ => $obj);
    }

    return $obj->call($env);
};

With this approach, Myapp isn't instantiated until a request is received, but it is instantiated only once per child process. This behavior is consistent whether or not --preload-app is used.