]> Sergey Matveev's repositories - public-inbox.git/commitdiff
watch: limit batch size of NNTP and IMAP workers, too
authorEric Wong <e@yhbt.net>
Mon, 31 Aug 2020 04:41:30 +0000 (04:41 +0000)
committerEric Wong <e@80x24.org>
Tue, 1 Sep 2020 00:19:00 +0000 (00:19 +0000)
We don't want to monopolize locks because processes can easily
block each other if using `watchspam' on a Maildir while a big
NNTP or IMAP import is happening.

This can also happen if somebody configured a single inbox to
watch from several sources to merge several mailboxes into one
(e.g. both an IMAP and Maildir are watched).

lib/PublicInbox/WatchMaildir.pm

index a227a6fd2719746e77070432285db893d5c890c7..5176ef69db9e9d698ceb4a33efadc019739b80f9 100644 (file)
@@ -108,6 +108,7 @@ sub new {
        return unless $mdre || scalar(keys %imap) || scalar(keys %nntp);
 
        bless {
+               max_batch => 10, # avoid hogging locks for too long
                spamcheck => $spamcheck,
                mdmap => \%mdmap,
                mdre => $mdre,
@@ -472,8 +473,14 @@ sub imap_fetch_all ($$$) {
 
                $l_uid = $uids->[-1] + 1; # for next search
                my $last_uid;
+               my $n = $self->{max_batch};
 
                while (scalar @$uids) {
+                       if (--$n < 0) {
+                               _done_for_now($self);
+                               $itrk->update_last($r_uidval, $last_uid);
+                               $n = $self->{max_batch};
+                       }
                        my @batch = splice(@$uids, 0, $bs);
                        $batch = join(',', @batch);
                        local $0 = "UID:$batch $mbx $sec";
@@ -888,9 +895,15 @@ sub nntp_fetch_all ($$$) {
        };
        my $inboxes = $self->{nntp}->{$url};
        my $last_art;
+       my $n = $self->{max_batch};
        for ($beg..$end) {
                last if $self->{quit};
                $art = $_;
+               if (--$n < 0) {
+                       _done_for_now($self);
+                       $itrk->update_last(0, $last_art);
+                       $n = $self->{max_batch};
+               }
                my $raw = $nn->article($art);
                unless (defined($raw)) {
                        my $msg = $nn->message;
@@ -976,12 +989,11 @@ sub fs_scan_step {
        local $PublicInbox::DS::in_loop = 0; # waitpid() synchronously
 
        # continue existing scan
-       my $max = 10;
        my $opendirs = $self->{opendirs};
        my @dirnames = keys %$opendirs;
        foreach my $dir (@dirnames) {
                my $dh = delete $opendirs->{$dir};
-               my $n = $max;
+               my $n = $self->{max_batch};
                while (my $fn = readdir($dh)) {
                        _try_path($self, "$dir/$fn");
                        last if --$n < 0;
@@ -996,7 +1008,7 @@ sub fs_scan_step {
                                warn "failed to open $dir: $!\n";
                                next;
                        }
-                       my $n = $max;
+                       my $n = $self->{max_batch};
                        while (my $fn = readdir($dh)) {
                                _try_path($self, "$dir/$fn");
                                last if --$n < 0;