From f744eb13bcea64a2b8c3482dfe4c9baf015f8b4b Mon Sep 17 00:00:00 2001 From: dakkar Date: Sun, 29 Dec 2019 18:41:21 +0000 Subject: better scandir * breadth-first, not depth-first * emits an `End` once all files that were there at the start have been emit-ed --- lib/MaildirIndexer/ScanDir.rakumod | 40 +++++++++++++++++++++++++++----------- lib/MaildirIndexer/Store.rakumod | 7 +++++-- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/lib/MaildirIndexer/ScanDir.rakumod b/lib/MaildirIndexer/ScanDir.rakumod index b21fd81..c45d787 100644 --- a/lib/MaildirIndexer/ScanDir.rakumod +++ b/lib/MaildirIndexer/ScanDir.rakumod @@ -1,34 +1,52 @@ use v6.d; unit module MaildirIndexer::ScanDir; +class End {}; + sub scan-dir(IO() $path --> Supply) is export { supply { my %watched-dirs; - sub add-dir(IO::Path $dir, :$initial) { - %watched-dirs{$dir} = True; + CATCH { when X::IO { }; default { warn $_; done } } - CATCH { when X::IO::Dir { }; default { warn $_ } } + sub start-watching(IO::Path $dir) { + %watched-dirs{$dir.Str} = True; whenever $dir.watch { my $path-io = .path.IO; emit $path-io; - when $path-io.e && $path-io.d { - add-dir($path-io) unless %watched-dirs{$path-io}; + when $path-io ~~ :e & :d { + add-dir($path-io) unless %watched-dirs{$path-io.Str}; } - when !$path-io.e { - %watched-dirs{$path-io}:delete + when $path-io ~~ :!e { + %watched-dirs{$path-io.Str}:delete } } + } + + sub add-dir(IO::Path $dir) { + my @todo = $dir; + + while @todo { + my $next = @todo.shift; - for $dir.dir { - emit $_; - when .e && .d { - add-dir($_); + emit $next; + + next unless $next ~~ :e & :r & :d; + start-watching($next); + + for $next.dir { + emit $_; + when .e && .d { + @todo.push($_); + start-watching($_); + } } } + } add-dir($path); + emit End; } } diff --git a/lib/MaildirIndexer/Store.rakumod b/lib/MaildirIndexer/Store.rakumod index 502d60e..03492f7 100644 --- a/lib/MaildirIndexer/Store.rakumod +++ b/lib/MaildirIndexer/Store.rakumod @@ -3,6 +3,7 @@ unit class MaildirIndexer::Store; use MaildirIndexer::LogTimelineSchema; use MaildirIndexer::Index; use MaildirIndexer::Parser; +use MaildirIndexer::ScanDir; has Lock $!lock .= new; has MaildirIndexer::Index @.indices is required; @@ -20,12 +21,14 @@ method start(--> Nil) { start react { CATCH { warn $_ }; whenever $.file-channel -> $file { - if $file.e && $file.f { + when $file ~~ MaildirIndexer::ScanDir::End { + } + when $file ~~ :e & :f { MaildirIndexer::LogTimelineSchema::Store::Add.log: :file($file.path), -> { self.add-file($file); } } - elsif !$file.e { + when $file ~~ :!e { MaildirIndexer::LogTimelineSchema::Store::Rm.log: :file($file.path), -> { self.del-file($file); } -- cgit v1.2.3