Skip to content

Instantly share code, notes, and snippets.

Created June 10, 2014 21:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/45eeebaf96b0cec19fff to your computer and use it in GitHub Desktop.
Save anonymous/45eeebaf96b0cec19fff to your computer and use it in GitHub Desktop.
package Minion::Backend::Storable;
use Mojo::Base 'Minion::Backend';
use Sys::Hostname 'hostname';
use Time::HiRes 'time';
sub new { shift->SUPER::new(file => shift) }
sub register_worker {
my $guard = shift->_guard;
my $id = $guard->_id;
push @{$guard->_workers},
{host => hostname, id => $id, pid => $$, started => time};
return $id;
}
sub repair {shift}
sub reset { shift->_guard->_spurt({}) }
sub unregister_worker {
my ($self, $id) = @_;
my $guard = $self->_guard;
$guard->_data->{workers} = [grep { $_->{id} ne $id } @{$guard->_workers}];
}
sub worker_info { shift->_guard->_worker(shift) }
sub _guard { Minion::Backend::Storable::_Guard->new(shift->{file}) }
package Minion::Backend::Storable::_Guard;
use Mojo::Base -base;
use Fcntl ':flock';
use List::Util 'first';
use Mojo::Util qw(md5_sum slurp spurt);
use Storable qw(freeze thaw);
sub DESTROY {
my $self = shift;
$self->_spurt($self->_data);
flock $self->{lock}, LOCK_UN;
}
sub new {
my $self = shift->SUPER::new(file => shift);
$self->_spurt({}) unless -f $self->{file};
open $self->{lock}, '<', $self->{file};
flock $self->{lock}, LOCK_EX;
return $self;
}
sub _data { $_[0]->{data} //= thaw slurp $_[0]->{file} }
sub _id {
my $self = shift;
my $id;
do { $id = md5_sum(time . rand 999) }
while $self->_worker($id) || $self->_job($id);
return $id;
}
sub _job {
first { $_[1] eq $_->{id} } @{$_[0]->_jobs};
}
sub _jobs { shift->_data->{jobs} //= [] }
sub _spurt { spurt freeze(pop), shift->{file} }
sub _worker {
first { $_[1] eq $_->{id} } @{$_[0]->_workers};
}
sub _workers { shift->_data->{workers} //= [] }
1;
use Mojo::Base -strict;
use Test::More;
use File::Spec::Functions 'catfile';
use File::Temp 'tempdir';
use Minion;
use Sys::Hostname 'hostname';
# Clean up before start
my $tmpdir = tempdir CLEANUP => 1;
my $file = catfile $tmpdir, 'minion.data';
my $minion = Minion->new(Storable => $file);
$minion->reset;
# Nothing to repair
my $worker = $minion->repair->worker;
isa_ok $worker->minion->app, 'Mojolicious', 'has default application';
# Register and unregister
$worker->register;
like $worker->info->{started}, qr/^[\d.]+$/, 'has timestamp';
is $worker->unregister->info, undef, 'no information';
is $worker->register->info->{host}, hostname, 'right host';
is $worker->info->{pid}, $$, 'right pid';
is $worker->unregister->info, undef, 'no information';
done_testing();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment