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;
}