Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Alternative script of MT::Worker::Publish.
#!/usr/bin/perl
package MT::Tool::SpeedRebuild;
use strict;
use warnings;
use File::Spec;
use FindBin;
use lib map File::Spec->catdir( $FindBin::Bin, File::Spec->updir, $_ ), qw/lib extlib/;
use base qw( MT::Tool );
use MT::FileMgr;
use MT::Util qw( log_time );
use Time::HiRes qw/usleep/;
our $microseconds = 700000;
our $proc_lifetime = 1800;
sub usage { '--per_proc 30 --max_proc 10' }
our $verbose;
our $per_proc;
our $max_proc;
our $work_dir;
our $pid_file;
our $sleeptime;
our $proc_name = 'mt-speed-rebuild.pid';
our $fmgr;
sub help {
return q {
Alternative script of MT::Worker::Publish.
--per_proc 30 --max_proc 10 --proc_lifetime 3600
};
}
my ( $debug );
sub options {
return (
'per_proc=i' => \$per_proc,
'max_proc=i' => \$max_proc,
'proc_lifetime=i' => \$proc_lifetime,
'proc_name=s' => \$proc_name,
);
}
sub main {
my $class = shift;
$verbose = $class->SUPER::main( @_ );
my $app = MT->instance;
my $tmp_dir = $app->config->TempDir;
if (! $per_proc ) {
$per_proc = $app->config->RebuildPerProc || 30;
}
if (! $proc_lifetime ) {
$proc_lifetime = 1800;
}
$sleeptime = $app->config->RebuildWaitTime || 5;
$fmgr = MT::FileMgr->new( 'Local' );
$pid_file = File::Spec->catfile( $tmp_dir, $proc_name );
if ( -f $pid_file ) {
return 1;
}
$fmgr->put_data( '', $pid_file );
chmod 0777, $pid_file;
$work_dir = File::Spec->catdir( $tmp_dir, 'RebuildProcDir' );
if (! -d $work_dir) {
$fmgr->mkpath( $work_dir );
}
require MT::TheSchwartz::FuncMap;
require MT::TheSchwartz::Job;
require MT::FileInfo;
require MT::WeblogPublisher;
my $funcmap = MT::TheSchwartz::FuncMap->load( { funcname => 'MT::Worker::Publish' } );
return unless $funcmap;
my @jobs = MT::TheSchwartz::Job->load( { funcid => $funcmap->funcid, },
{ 'sort' => 'priority',
direction => 'decend',
},
);
my @works = ();
my $pub = MT::WeblogPublisher->new();
my $rebuilt;
for my $job ( @jobs ) {
push ( @works, $job );
if ( ( scalar @works ) >= $per_proc ) {
if ( $rebuilt ) {
usleep ( $microseconds );
}
_do_work( \@works );
@works = ();
}
$rebuilt++;
}
if ( @works ) {
if ( $rebuilt ) {
usleep ( $microseconds );
}
_do_work( \@works );
}
while ( _count_dir( $work_dir ) ) {
sleep $sleeptime;
}
unlink $pid_file;
1;
}
sub _do_work {
my $works = shift;
my $app = MT->instance();
if (! $max_proc ) {
$max_proc = $app->config->RebuildMaxProc || 4;
}
$sleeptime = $app->config->RebuildWaitTime || 5;
while ( $max_proc <= _count_dir( $work_dir ) ) {
sleep $sleeptime;
}
my $rebuild_sub = sub {
my $token = _make_magic_token();
my $work_file = File::Spec->catdir( $work_dir, $token );
$fmgr->put_data( '', $work_file );
chmod 0777, $work_file;
my $i = 0;
for my $job ( @$works ) {
if ( my $fi = MT::FileInfo->load( $job->uniqkey ) ) {
$i++;
$fi->{ from_queue } = 1;
my $res = MT->instance->publisher->rebuild_from_fileinfo( $fi );
if ( defined $res ) {
$app->log(
{ ( $fi->blog_id ? ( blog_id => $fi->blog_id ) : () ),
message => $app->translate('Background Publishing Done') . ' : ' . $i,
metadata => log_time() . ' '
. $app->translate( 'Published: [_1]', $fi->file_path ),
category => "publish",
level => MT::Log::INFO(),
}
);
$job->remove; # or die $job->errstr;
} else {
my $error = $app->publisher->errstr;
my $errmsg = $app->translate( "Error rebuilding file [_1]:[_2]",
$fi->file_path, $error );
MT::TheSchwartz->debug($errmsg);
$job->permanent_failure($errmsg);
require MT::Log;
$app->log(
{ ( $fi->blog_id ? ( blog_id => $fi->blog_id ) : () ),
message => $errmsg,
metadata => log_time() . ' ' . $errmsg . ":\n" . $error,
category => "publish",
level => MT::Log::ERROR(),
}
);
}
} else {
$job->remove;# or die $job->errstr;
}
}
unlink $work_file;
};
_background_rebuild( $rebuild_sub );
}
sub _count_dir {
my $dir = shift;
my @files;
opendir my $dh, $dir or die "$dir:$!";
while ( my $file = readdir $dh ) {
next if $file =~ /^\./;
$file = File::Spec->catfile( $dir, $file );
my $modified = ( stat $file )[9];
if ( ( time() - $modified ) > $proc_lifetime ) {
unlink $file;
} else {
push @files, $file;
}
}
closedir $dh;
return scalar @files;
}
sub _make_magic_token {
my @alpha = ( 'a' .. 'z', 'A' .. 'Z', 0 .. 9 );
my $token = join '', map $alpha[ rand @alpha ], 1 .. 40;
$token;
}
sub _background_rebuild {
my $app = MT->instance();
my $default = $app->config->LaunchBackgroundTasks;
$app->config( 'LaunchBackgroundTasks', 1 );
my $res = MT::Util::start_background_task( @_ );
$app->config( 'LaunchBackgroundTasks', $default );
return $res;
}
__PACKAGE__->main() unless caller;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment