summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2019-12-26 20:13:58 +0000
committerdakkar <dakkar@thenautilus.net>2019-12-26 20:13:58 +0000
commit6171cb0d7fe0ac8f6352b8d3b9b87d56c56cf791 (patch)
tree98b6f42a0ab9939f78134b27f780261211845968
parenttest email (diff)
downloadMaildirIndexer-6171cb0d7fe0ac8f6352b8d3b9b87d56c56cf791.tar.gz
MaildirIndexer-6171cb0d7fe0ac8f6352b8d3b9b87d56c56cf791.tar.bz2
MaildirIndexer-6171cb0d7fe0ac8f6352b8d3b9b87d56c56cf791.zip
restructure store, extract server
now Store has a set of Index, which actually do the indexing Store also runs the scan-dir (this may not be ideal, but will do for now) Server handles I/O
-rw-r--r--bayes46
-rw-r--r--lib/MaildirIndexer/Email.pm63
-rw-r--r--lib/MaildirIndexer/Index.pm67
-rw-r--r--lib/MaildirIndexer/Index/ByRef.pm636
-rw-r--r--lib/MaildirIndexer/Parser.pm615
-rw-r--r--lib/MaildirIndexer/Server.pm630
-rw-r--r--lib/MaildirIndexer/Store.pm655
7 files changed, 126 insertions, 66 deletions
diff --git a/bayes b/bayes
index e3814fc..0bb9d3e 100644
--- a/bayes
+++ b/bayes
@@ -1,47 +1,17 @@
#!/usr/bin/env perl6
use v6.d.PREVIEW;
use lib 'lib';
-use MaildirIndexer::ScanDir;
use MaildirIndexer::Store;
-use MaildirIndexer::Parser;
+use MaildirIndexer::Server;
+use MaildirIndexer::Index::ByRef;
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 {
- $store.add-file($file);
- }
- elsif !$file.e {
- $store.del-file($file);
- }
- }
- }
- }
-
- my $listener = IO::Socket::Async.listen(
- '127.0.0.1',
- 9000,
- :enc<utf8-c8>,
+ my $store = MaildirIndexer::Store.new(
+ :$maildir,
+ indices => MaildirIndexer::Index::ByRef.new,
);
- react {
- whenever signal(SIGINT) { exit }
- whenever signal(SIGHUP) {
- $store.dump();
- }
- whenever $listener -> $conn {
- LEAVE { $conn.close }
- with parse-email($conn) -> $email {
- with $store.mailbox-for-email($email) -> $mailbox {
- await $conn.print("$mailbox\x0d\x0a");
- }
- }
- }
- }
+ my $server = MaildirIndexer::Server.new(:$store);
+ $store.start();
+ $server.serve()
}
diff --git a/lib/MaildirIndexer/Email.pm6 b/lib/MaildirIndexer/Email.pm6
index 993d8b1..0cd5bd7 100644
--- a/lib/MaildirIndexer/Email.pm6
+++ b/lib/MaildirIndexer/Email.pm6
@@ -1,10 +1,11 @@
use v6.d.PREVIEW;
unit class MaildirIndexer::Email;
+has IO $!path;
has %!headers;
has $!body;
-method BUILD(:%!headers,:$!body) { }
+method BUILD(:%!headers,:$!body,:$!path = IO) { }
method message-id { split-refs(%!headers<message-id>)[0] // '' }
method refs {
diff --git a/lib/MaildirIndexer/Index.pm6 b/lib/MaildirIndexer/Index.pm6
new file mode 100644
index 0000000..2cb308a
--- /dev/null
+++ b/lib/MaildirIndexer/Index.pm6
@@ -0,0 +1,7 @@
+use v6.d;
+unit role MaildirIndexer::Index;
+use MaildirIndexer::Email;
+
+method add-mail(MaildirIndexer::Email:D $email, Str:D $mailbox --> Nil) { ... }
+method del-path(IO:D $path, Str:D $mailbox --> Nil) { ... }
+method mailbox-for-email(MaildirIndexer::Email:D $email --> Str) { ... }
diff --git a/lib/MaildirIndexer/Index/ByRef.pm6 b/lib/MaildirIndexer/Index/ByRef.pm6
new file mode 100644
index 0000000..497b5a1
--- /dev/null
+++ b/lib/MaildirIndexer/Index/ByRef.pm6
@@ -0,0 +1,36 @@
+use v6.d;
+use MaildirIndexer::Index;
+unit class MaildirIndexer::Index::ByRef does MaildirIndexer::Index;
+use MaildirIndexer::Email;
+
+has Str %!id-for-file;
+has Str %!mailboxes-for-id;
+
+method dump() {
+ say "{.key} → {.value}" for %!id-for-file;
+ say "{.key} ⇒ {.value.perl}" for %!mailboxes-for-id;
+}
+
+method add-mail(MaildirIndexer::Email:D $email, Str:D $mailbox --> Nil) {
+ my $id = $email.message-id or return;
+ %!id-for-file{ $email.path } = $id;
+ %!mailboxes-for-id{ $id }.push($mailbox);
+ return;
+}
+
+method del-path(IO:D $file, Str:D $mailbox --> Nil) {
+ my $id = %!id-for-file{ $file.path }:delete;
+ with %!mailboxes-for-id{ $id } {
+ with .grep($mailbox):k -> $pos {
+ .splice($pos,1);
+ }
+ }
+ return;
+}
+
+method mailbox-for-email(MaildirIndexer::Email:D $email --> Str) {
+ for |$email.refs() -> $ref {
+ with %!mailboxes-for-id{$ref} { return .[*-1] }
+ }
+ return Nil;
+}
diff --git a/lib/MaildirIndexer/Parser.pm6 b/lib/MaildirIndexer/Parser.pm6
index edcbe6d..e6be32f 100644
--- a/lib/MaildirIndexer/Parser.pm6
+++ b/lib/MaildirIndexer/Parser.pm6
@@ -38,10 +38,12 @@ grammar Message {
}
class Message-actions {
+ has $.path = IO;
method TOP($/) {
make MaildirIndexer::Email.new(
headers => $/<headers>.made,
body => $/<body>.Str,
+ path => $.path,
);
}
method headers($/) {
@@ -55,21 +57,22 @@ class Message-actions {
}
}
-multi parse-email(IO::Path $p) is export {
- return parse-email($p.slurp(:enc<utf8-c8>));
+multi parse-email(IO::Path:D $p --> MaildirIndexer::Email) is export {
+ return parse-email($p.slurp(:enc<utf8-c8>), path => $p.path);
}
-multi parse-email(IO::Path $p, :$headers-only!) is export {
+multi parse-email(IO::Path:D $p, :$headers-only! --> MaildirIndexer::Email) is export {
return parse-email(
$p.lines(
:enc<utf8-c8>,
:nl-in(@separators),
:!chomp,
)[0],
+ path => $p.path,
);
}
-multi parse-email(IO::Socket::Async $s) is export {
+multi parse-email(IO::Socket::Async:D $s --> MaildirIndexer::Email) is export {
my $string;
react {
whenever $s.Supply(:enc<utf8-c8>) {
@@ -80,8 +83,8 @@ multi parse-email(IO::Socket::Async $s) is export {
return parse-email($string);
}
-multi parse-email(Str $email-str) is export {
- with Message.parse($email-str,:actions(Message-actions.new)) {
+multi parse-email(Str:D $email-str, :$path = IO --> MaildirIndexer::Email) is export {
+ with Message.parse($email-str,:actions(Message-actions.new(:$path))) {
return .made;
}
return Nil;
diff --git a/lib/MaildirIndexer/Server.pm6 b/lib/MaildirIndexer/Server.pm6
new file mode 100644
index 0000000..53f4ba9
--- /dev/null
+++ b/lib/MaildirIndexer/Server.pm6
@@ -0,0 +1,30 @@
+use v6.d;
+unit class MaildirIndexer::Server;
+use MaildirIndexer::Parser;
+use MaildirIndexer::Store;
+
+has $.port = 9000;
+has MaildirIndexer::Store $.store is required;
+
+method serve() {
+ my $listener = IO::Socket::Async.listen(
+ '127.0.0.1',
+ 9000,
+ :enc<utf8-c8>,
+ );
+
+ react {
+ whenever signal(SIGINT) { exit }
+ whenever signal(SIGHUP) {
+ $.store.dump();
+ }
+ whenever $listener -> $conn {
+ LEAVE { $conn.close }
+ with parse-email($conn) -> $email {
+ with $.store.mailbox-for-email($email) -> $mailbox {
+ await $conn.print("$mailbox\x0d\x0a");
+ }
+ }
+ }
+ }
+}
diff --git a/lib/MaildirIndexer/Store.pm6 b/lib/MaildirIndexer/Store.pm6
index e54fa8f..5c95250 100644
--- a/lib/MaildirIndexer/Store.pm6
+++ b/lib/MaildirIndexer/Store.pm6
@@ -1,45 +1,58 @@
-use v6.d.PREVIEW;
+use v6.d;
unit class MaildirIndexer::Store;
+use MaildirIndexer::Index;
+use MaildirIndexer::ScanDir;
use MaildirIndexer::Parser;
-has %!id-for-file;
-has %!mailboxes-for-id;
-has $!lock = Lock.new;
+has Lock $!lock .= new;
+has MaildirIndexer::Index @.indices is required;
+has Str $.maildir is required;
+has Int $.workers = 10;
method dump() {
$!lock.protect: {
- say "{.key} → {.value}" for %!id-for-file;
- say "{.key} ⇒ {.value.perl}" for %!mailboxes-for-id;
+ .dump() for @!indices;
}
}
-method add-file(IO $file) {
+method start() {
+ 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 {
+ self.add-file($file);
+ }
+ elsif !$file.e {
+ self.del-file($file);
+ }
+ }
+ }
+ }
+}
+
+method add-file(IO:D $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);
- };
+ .add-mail($email,$mailbox) for @!indices;
+ }
return;
}
-method del-file(IO $file) {
+method del-file(IO:D $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);
- }
- }
+ .del-path($file,$mailbox) for @!indices;
}
return;
}
-method mailbox-for-email(MaildirIndexer::Email $email) {
- for |$email.refs() -> $ref {
- with %!mailboxes-for-id{$ref} { return .[*-1] }
+method mailbox-for-email(MaildirIndexer::Email:D $email) {
+ for @!indices -> $index {
+ with $index.mailbox-for-email($email) { return $_ };
}
return Nil;
}