App-CSE
view release on metacpan or search on metacpan
lib/App/CSE/Command/Watch.pm view on Meta::CPAN
use App::CSE::File;
use File::MimeInfo::Magic;
use Filesys::Notify::Simple;
use Lucy::Search::IndexSearcher;
use Lucy::Index::Indexer;
use Log::Log4perl;
my $LOGGER = Log::Log4perl->get_logger();
sub execute{
my ($self) = @_;
my $colorizer = $self->cse()->colorizer();
my $colored = sub{ $colorizer->colored(@_);};
my $cse = $self->cse();
# Check the index.
# Re-index if nothing is there.
my $check = App::CSE::Command::Check->new({ cse => $cse });
if( $check->execute() ){
$LOGGER->info(&$colored("Rebuilding the index..", 'green bold'));
my $index_cmd = App::CSE::Command::Index->new( { cse => $cse });
if( $index_cmd->execute() ){
$LOGGER->error(&$colored("Building index failed", 'red'));
return 1;
}
}
if( my $previous_pid = $cse->index_meta()->{'watcher.pid'} ){
# A previous pid should be a number.
( $previous_pid ) = ( $previous_pid =~ /(\d+)/ );
if( kill(0, $previous_pid ) ){
$LOGGER->error(&$colored("Previous watcher (PID=".$previous_pid.") is still running. Try cse unwatch first",
"red bold"));
return 1;
}
}
my $direct_child = fork();
confess("Cannot fork() a direct child: $!") unless defined $direct_child;
if( $direct_child ){
waitpid($direct_child , 0 );
return 0;
}
my $pid = fork();
confess("Cannot fork() a worker child: $!") unless defined $pid;
if( $pid ){
$cse->index_meta()->{'watcher.pid'} = $pid;
$cse->index_meta()->{'watcher.started'} = DateTime->now()->iso8601();
$cse->save_index_meta();
$LOGGER->info(&$colored("PID=$pid : Watching for changes in ".$self->dir_index().", updating ".$cse->index_dir(), "green bold"));
exit(0);
}
my $deamon_log = q|log4perl.rootLogger = INFO, SYSLOG
log4perl.appender.SYSLOG = Log::Dispatch::Syslog
log4perl.appender.SYSLOG.min_level = debug
log4perl.appender.SYSLOG.ident = cse V|.$cse->version().q|[|.$$.q|]
log4perl.appender.SYSLOG.facility = daemon
log4perl.appender.SYSLOG.layout = Log::Log4perl::Layout::SimpleLayout
|;
Log::Log4perl::init(\$deamon_log);
$LOGGER->info("Watching for changes in ".$self->dir_index().", updating ".$cse->index_dir());
my $lock = 0;
my $should_exit = 0;
$SIG{TERM} = $SIG{INT} = sub{
$LOGGER->info("Caught INT or TERM signal. Will exit");
$should_exit = 1;
unless( $lock ){
exit(0);
}
};
my $watcher = Filesys::Notify::Simple->new([ $self->dir_index()->absolute()->stringify() ]);
while( !$should_exit ){
$watcher->wait(sub {
my @events = @_;
# Lock exiting before we do anything meaty
$lock = 1;
eval{
foreach my $event ( @events ) {
my $file_name = $event->{path};
# file_path here is absolute.
# $self->dir_index() can be relative
if ( $self->dir_index()->is_relative() ) {
# We should remove the absolute prefix from the file path
my $abs_prefix = $self->dir_index->absolute()->stringify();
$file_name =~ s/^$abs_prefix/\./ ;
}
# Unreadable files are invalid. This will help
# not adding deleted files.
( run in 0.540 second using v1.01-cache-2.11-cpan-39bf76dae61 )