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 )