use TheSchwartz job queue to handle Image-Resize For Catalyst App. TheSchwartz - reliable job queue. original developped by Brad and used in LiveJournal. My main aim is to remove 'Image::Magick' out of my Catalyst App since Image::Magick takes a lot of memories for every process under mod_perl. so we need a non-stop cron script to monitor and resize photos. and I picked TheSchwartz up for my Foorum Catalyst App. Here comes the instructions: 1, create db 'theschwartz' by using schema: http://search.cpan.org/src/BRADFITZ/TheSchwartz-1.04/doc/schema.sql 2, write the main module Foorum::TheSchwartz::Worker::ResizeProfilePhoto use base TheSchwartz::Worker.
package Foorum::TheSchwartz::Worker::ResizeProfilePhoto;
use TheSchwartz::Job;
use base qw( TheSchwartz::Worker );
use Foorum::ExternalUtils qw/schema/;
use File::Spec;
use Image::Magick;
use Cwd qw/abs_path/;
use File::Copy;
my (undef, $path) = File::Spec->splitpath(__FILE__);
sub work {
my $class = shift;
my TheSchwartz::Job $job = shift;
my @args = $job->arg;
my $schema = schema();
# get upload from db
my $upload_id = shift @args;
if ($upload_id !~ /^\d+$/) {
return $job->failed("Wrong upload_id: $upload_id");
}
my $upload = $schema->resultset('Upload')->find( { upload_id => $upload_id } );
unless ($upload) {
return $job->failed("No upload for $upload_id");
}
# get file dir
my $directory_1 = int( $upload_id / 3200 / 3200 );
my $directory_2 = int( $upload_id / 3200 );
my $file = abs_path("$path/../../../../root/upload/$directory_1/$directory_2/" . $upload->filename);
# resize photo
my $p = new Image::Magick;
$p->Read($file);
$p->Scale(geometry=>'120x120');
$p->Sharpen(geometry=>'0.0x1.0');
$p->Set(quality=>'75');
my ($width, $height, $size) = $p->Get('width', 'height', 'filesize');
my $tmp_file = $file . '.tmp';
$p->Write($tmp_file);
move($tmp_file, $file);
# update db
$schema->resultset('UserProfilePhoto')->search( {
type => 'upload',
value => $upload_id,
} )->update( {
width => $width,
height => $height,
} );
($size) = ( $size =~ /^(\d+\.?\d{0,1})/ ); # float(6,1)
$upload->update( { filesize => $size } );
$job->completed();
}
sub max_retries { 3 };
1;
3, write a TheSchwartz_worker.pl and run it. it will monitor the "job" table in "theschwartz" database non-stop.package Foorum::ExternalUtils;
# ... etc.
use TheSchwartz;
sub theschwartz {
$config = config() unless ($config);
my $theschwartz = TheSchwartz->new(
databases => [ {
dsn => $config->{theschwartz_dsn}, # dbi:mysql:theschwartz
user => $config->{dsn_user},
pass => $config->{dsn_pwd},
} ],
verbose => 1,
);
return $theschwartz;
}
use Foorum::ExternalUtils qw/theschwartz/;
use Foorum::TheSchwartz::Worker::ResizeProfilePhoto;
my $client = theschwartz();
$client->can_do('Foorum::TheSchwartz::Worker::ResizeProfilePhoto');
$client->work();
4, at last, we need insert data into 'job' table then let TheSchwartz_worker.pl to handle it.package Foorum::Controller::Profile;
use Foorum::ExternalUtils qw/theschwartz/;
sub xxx : Local {
# ... etc.
my $client = theschwartz();
$client->insert('Foorum::TheSchwartz::Worker::ResizeProfilePhoto', $new_upload_id);
}
That's ALL.
The idea behind TheSchwartz is not so complicate.
sub work {
my $class = shift;
my TheSchwartz::Job $job = shift;
my @args = $job->arg;
# do something
$job->completed();
}