use v6.d; 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; has Channel $.file-channel is required; has Int $.workers = Kernel.cpu-cores - 1; has Channel @!index-channels = Channel.new xx +@!indices; method dump(--> Nil) { $!lock.protect: { .dump() for @!indices; } } method start(--> Nil) { for @.indices Z @!index-channels -> ($i, $c) { start $i.receive($c); } for ^$.workers { start react { whenever $.file-channel -> $file { CATCH { warn "looking at $file\n"; warn .gist }; when $file ~~ MaildirIndexer::ScanDir::End { MaildirIndexer::LogTimelineSchema::Scan::End.log(); } when $file ~~ :e & :f { MaildirIndexer::LogTimelineSchema::Store::Add.log: :file($file.path), -> { self.add-file($file); } } when $file ~~ :!e { MaildirIndexer::LogTimelineSchema::Store::Rm.log: :file($file.path), -> { self.del-file($file); } } } } } } method add-file(IO:D $file --> Nil) { my Str $mailbox = mailbox-from-path($file.path) or return; my MaildirIndexer::Email $email = parse-email($file,:headers-only) or return; my $event = AddMail.new(:$email,:$mailbox); .send($event) for @!index-channels; return; } method del-file(IO:D $file --> Nil) { my $mailbox = mailbox-from-path($file.path) or return; my $event = DelPath.new(:path($file),:$mailbox); .send($event) for @!index-channels; return; } method mailbox-for-email(MaildirIndexer::Email:D $email --> Str) { my Str $result; my Channel $replies .= new; my $event = MailboxForEmail.new(:$email,:reply-to($replies)); MaildirIndexer::LogTimelineSchema::Store::Find.log: { .send($event) for @!index-channels; my @results = $replies.receive() xx @!index-channels; $result = @results.grep(*.defined).join("\n"); } return $result; } sub mailbox-from-path(Str() $path --> Str) { $path ~~ m{'/' (<-[/]>+?) '/' [cur|new|tmp] '/'} and return ~$/[0]; return Nil; }