From 3b97aa0df99bcad2656899c03ee1f759cb3efc55 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 9 Nov 2018 15:19:16 +0000 Subject: in-memory store, and Email class --- bayes | 18 ++++++++++++++---- lib/MaildirIndexer/Email.pm6 | 21 +++++++++++++++++++++ lib/MaildirIndexer/Parser.pm6 | 8 ++++++-- lib/MaildirIndexer/Store.pm6 | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 lib/MaildirIndexer/Email.pm6 create mode 100644 lib/MaildirIndexer/Store.pm6 diff --git a/bayes b/bayes index c7c81bf..0843976 100644 --- a/bayes +++ b/bayes @@ -2,21 +2,31 @@ use v6.d.PREVIEW; use lib 'lib'; use MaildirIndexer::ScanDir; -use MaildirIndexer::Parser; +use MaildirIndexer::Store; sub MAIN($maildir) { + my $store = MaildirIndexer::Store.new; + my $file-supply = scan-dir($maildir); my $file-channel = $file-supply.Channel; + for ^10 { start react { whenever $file-channel -> $file { if $file.e && $file.f { - my $email = parse-email($file,:headers-only); - say "{$file} - {$email}"; + $store.add-file($file); + } + elsif !$file.e { + $store.del-file($file); } } } } - react whenever signal(SIGINT) { exit } + react { + whenever signal(SIGINT) { exit } + whenever signal(SIGHUP) { + $store.dump(); + } + } } diff --git a/lib/MaildirIndexer/Email.pm6 b/lib/MaildirIndexer/Email.pm6 new file mode 100644 index 0000000..f5d1c39 --- /dev/null +++ b/lib/MaildirIndexer/Email.pm6 @@ -0,0 +1,21 @@ +use v6.d.PREVIEW; +unit class MaildirIndexer::Email; + +has %!headers; +has $!body; + +method BUILD(:%!headers,:$!body) { } + +method message-id { split-refs(%!headers)[0] } +method refs { + return |( + split-refs(%!headers), + split-refs(%!headers).reverse, + ); +} + +multi split-refs(Any) { return (); } +multi split-refs(Str:D $str) { + return $/».Str if $str ~~ m{'<' $ = (<-[<>]>+)+ % [ '>' .*? '<' ] '>' }; + return (); +} diff --git a/lib/MaildirIndexer/Parser.pm6 b/lib/MaildirIndexer/Parser.pm6 index 90b3678..c2425fe 100644 --- a/lib/MaildirIndexer/Parser.pm6 +++ b/lib/MaildirIndexer/Parser.pm6 @@ -1,5 +1,6 @@ use v6.d.PREVIEW; unit module MaildirIndexer::Parser; +use MaildirIndexer::Email; my @separators = ( "\x0a\x0d\x0a\x0d", @@ -38,13 +39,16 @@ grammar Message { class Message-actions { method TOP($/) { - make %( headers => $/.made, body => $/.Str ); + make MaildirIndexer::Email.new( + headers => $/.made, + body => $/.Str, + ); } method headers($/) { make %( |$/
».made ); } method header($/) { - make $/ ?? () !! ( $/.Str => $/.made ); + make $/ ?? () !! ( $/.Str.lc => $/.made ); } method value($/) { make $/.join(' ') diff --git a/lib/MaildirIndexer/Store.pm6 b/lib/MaildirIndexer/Store.pm6 new file mode 100644 index 0000000..cbfcfa1 --- /dev/null +++ b/lib/MaildirIndexer/Store.pm6 @@ -0,0 +1,43 @@ +use v6.d.PREVIEW; +unit class MaildirIndexer::Store; +use MaildirIndexer::Parser; + +has %!id-for-file; +has %!mailboxes-for-id; +has $!lock = Lock.new; + +method dump() { + $!lock.protect: { + say "{.key} → {.value}" for %!id-for-file; + say "{.key} ⇒ {.value.perl}" for %!mailboxes-for-id; + } +} + +method add-file(IO $file) { + my $email = parse-email($file,:headers-only); + my $id = $email.message-id or return; + my $mailbox = mailbox-from-path($file.path) or return; + $!lock.protect: { + %!id-for-file{ $file.path } = $id; + %!mailboxes-for-id{ $id }.push($mailbox); + }; + return; +} + +method del-file(IO $file) { + my $mailbox = mailbox-from-path($file.path) or return; + $!lock.protect: { + my $id = %!id-for-file{ $file.path }:delete; + with %!mailboxes-for-id{ $id } { +with .grep($mailbox):k -> $pos { + .splice($pos,1); + } +} + } + return; +} + +sub mailbox-from-path(Str() $path) { + $path ~~ m{'/' (<-[/]>+?) '/' [cur|new|tmp] '/'} and return ~$/[0]; + return Nil; +} -- cgit v1.2.3