Add "app_builder" type of argument for Plack::Runner #415

Closed
wants to merge 1 commit into
from

Projects

None yet

2 participants

@ChinaXing

when I use Plack::Runner to plackup pice of code to run, i found it can not supply some code ran at each time of the server was loaded (especially reloaded), for exmaple :

package Te::Myblog;
#use HiD; # is a static blog builder
use Plack::Runner;

my $hid = $self->build_hid;
my $app = sub {
     $hid->rebuild;
     return  Plack::App::File->new(root => $self->destination )->to_app;
};

my $runner = Plack::Runner->new;
$runner->parse_options('-r', '-R' => $self->source_dir);
$runner->run($app);

then, the plack server will restart when it found the directory 's file changed;
when the server restart, I hope I can do some work incidentally , here is rebuild the blog;

I found the Plack::Runner::locate_app method will treat code ref of app as :

(https://github.com/plack/Plack/blob/master/lib/Plack/Runner.pm#L160)

 if (ref $psgi eq 'CODE') {
    return sub { $psgi };
}

so, I append a pice of code, to satisfy my requirement

hopen you can merge it to your wonderful code. that's great for everyone to use it :)

Very thanks !

@miyagawa
Member

I don't think it's a good idea. Also the test is failing.

Plack::Loader might be the right place to look at.

@miyagawa miyagawa closed this Jun 15, 2013
@ChinaXing

yes, use cod ref ref is urgly ,how to do it with Plack::Loader? very thanks:)

@miyagawa
Member

Plack::Loader (and the rest of Plack ecosystem) allows to return an object that overrides to_app to return PSGI app.

You can write a custom to_app method that runs whatever hook, then returns a PSGI app code reference.

@ChinaXing

would to_app method be called at each time of server was restarted ? I need something be called at the server restarted. I use Plack::Loader::Restarter ( I use -r and -R argument to plack::Runner )

thank you :)

@miyagawa
Member

Yes.

@ChinaXing

oh,maybe that not works for me, the to_app will be called automatically when app is an object ( at each request but not each time of server restart)and app must be in a external file plan runner to load( but i hope it can be in an object or call back i created in my code )

I think you can do some extends at here:

can pass an object to Plack::Runner::run

can pass an app_builder to Plack::Runner::Run

@miyagawa
Member

(at each request but not each time of server restart)

It's called each restart, not each request.

app must be in a external file plan runner to load( but i hope it can be in an object or call back i created in my co de )

No, there's no restriction like that.

@ChinaXing

maybe I wrong, I just found the code in Plack::Runner::run;

https://github.com/plack/Plack/blob/master/lib/Plack/Runner.pm#L250

my $app = $self->locate_app(@args);
https://github.com/plack/Plack/blob/master/lib/Plack/Runner.pm#L154

if (ref $psgi eq 'CODE') {
    return sub { $psgi };
}

if ($self->{eval}) {
    $self->loader->watch("lib");
    return build {
        no strict;
        no warnings;
        my $eval = "builder { $self->{eval};";
        $eval .= "Plack::Util::load_psgi(\$psgi);" if $psgi;
        $eval .= "}";
        eval $eval or die $@;
    };
}

$psgi ||= "app.psgi";

require File::Basename;
$self->loader->watch( File::Basename::dirname($psgi) . "/lib", $psgi );
build { Plack::Util::load_psgi $psgi };

}

looks like the $psgi either an code ref or an "string" means a .psgi file ; if i pass an object to it, it will treat as a .psgi file string, that's wrong.

@miyagawa
Member

Right, reloader doesn't seem to support object.

You just implement an object with to_app, then don't use restarter but use your own watcher.

Or, create an app in .psgi as suggested.

Or subclass Reloader loader that ignores the app object, and specify that loader.

@miyagawa
Member

When going back to what you're trying to achieve, I think you're trying to abuse the Plack's restarter process to do your application logic, which i don't think is a good idea at all, since it won't work very well in the production environment.

I recommend you to step back and write your PSGI app that rebuilds the actual file server object with the timer (or a better backend), then swap out the App::File app object inside your application, rather than restarting the actual PSGI container.

@ChinaXing

at first, I use AnyEvent::Inotify to watch the change and than restart Plack Server,

then found the Plack Server has '-r' and '-R' option, so I want to just use Plack server's watch and restart function ( for reduce code )

the restart and watch function was used in development environment in my senior --- A blog generator tool/ just to test the correctness of generated content not works as a server online at all time;

so use your plack's restarter is suitable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment