Skip to content

Instantly share code, notes, and snippets.

@brianmed
Last active June 14, 2020 13:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brianmed/8983255 to your computer and use it in GitHub Desktop.
Save brianmed/8983255 to your computer and use it in GitHub Desktop.
Non-blocking commands with Mojolicious::Lite
use Mojolicious::Lite;
use File::Temp qw(tempfile);
use Proc::Background;
use Fcntl qw(SEEK_SET);
use IO::Handle;
any '/run' => sub {
my $self = shift;
my ($fh,$filename) = tempfile();
my $script;
my $tmp = File::Temp->new( UNLINK => 0, SUFFIX => '.pl');
say($tmp
"#!perl\n",
"\n",
"use IO::Handle;\n",
q(open($fh, ">", $ARGV[0]);), "\n",
q($fh->autoflush(1);), "\n",
q(do { print($fh scalar(localtime), "\n"); sleep 1 } foreach (1 .. 20);), "\n",
);
$script = $tmp->filename;
undef($tmp);
$self->app->log->debug("script: $script");
my $command = qq($^X $script $filename);
$self->app->log->debug("Command: $command");
my $proc = Proc::Background->new($command);
Mojo::IOLoop->stream($self->tx->connection)->timeout(30);
$self->render_later;
my $recurring = Mojo::IOLoop->recurring(1 => sub {
my $tmp_fh = $self->stash->{_fh};
my $told = $self->stash->{_told} // 0;
my $proc = $self->stash->{_proc};
$self->app->log->debug("Recurring: " . $proc->pid);
my $file = $self->stash->{_filename};
open(my $fh, "<", $file);
if (fileno($fh)) {
seek($fh, $told, SEEK_SET);
read($fh, my $buf, 1024);
$self->stash->{_told} = tell($fh);
chomp($buf);
$self->write_chunk(qq(<script>document.getElementById("stuff").innerHTML += "$buf<br>";</script>\n));
}
if ($proc->alive) {
return;
}
$self->app->log->debug("Done");
$self->write_chunk("Done</body></html>");
$self->finish;
});
$self->stash->{_recurring} = $recurring;
$self->stash->{_fh} = $fh;
$self->stash->{_filename} = $filename;
$self->stash->{_proc} = $proc;
$self->on(finish => sub {
my $fh = $self->stash->{_fh};
my $recurring = $self->stash->{_recurring};
Mojo::IOLoop->remove($fh);
Mojo::IOLoop->remove($recurring);
$self->app->log->debug("Finished");
});
$self->res->code(200);
$self->res->headers->content_type('text/html');
$self->write_chunk("<html><body><div id=stuff>Starting...<br></div>");
};
push(@ARGV, 'daemon', '-l', 'http://*:5555') unless @ARGV;
app->log->level("debug");
app->secrets(["I Knos# you!!"]);
app->start;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment