Commit 9528ec4

mokha <mokha@cisco.com>
2019-04-15 21:09:07
use the listen gem to capture new emails on disk
1 parent c23bf0f
Changed files (4)
lib/minbox/inbox.rb
@@ -1,33 +1,36 @@
 # frozen_string_literal: true
+require 'listen'
 
 module Minbox
   class Inbox
     include Enumerable
-    attr_reader :root_dir
 
-    def initialize(root_dir: 'tmp')
-      @root_dir = Pathname.new(root_dir)
+    def initialize
+      empty!
+    end
+
+    def start(root_dir: 'tmp')
+      ::Listen.to(File.expand_path(root_dir), only: /\.eml$/) do |modified, added, removed|
+        added.each do |file|
+          @emails[File.basename(file)] = Mail.read(file)
+        end
+      end.start
     end
 
     def emails
-      map { |x| File.basename(x) }
+      @emails.keys
     end
 
     def open(id)
-      file = find { |x| x.end_with?(id) }
-      file ? Mail.read(file) : nil
+      @emails[id]
     end
 
     def empty!
-      each do |email|
-        File.unlink(email)
-      rescue StandardError
-        nil
-      end
+      @emails = {}
     end
 
     def each
-      Dir[root_dir.join("*.eml")].sort_by { |x| File.mtime(x) }.each do |email|
+      @emails.each do |id, email|
         yield email
       end
     end
spec/minbox/inbox_spec.rb
@@ -5,6 +5,7 @@ RSpec.describe Minbox::Inbox do
 
   before do
     FileUtils.rm(Dir.glob('tmp/*.eml'))
+    subject.start
   end
 
   describe "#empty!" do
@@ -17,22 +18,25 @@ RSpec.describe Minbox::Inbox do
       subject.empty!
     end
 
-    specify { expect(Dir['tmp/*.eml'].count).to be_zero }
+    specify { expect(subject.count).to be_zero }
   end
 
   describe "#emails" do
     before :example do
-      subject.empty!
-      IO.write("tmp/1.eml", Mail.new do
-        to Faker::Internet.email
-        from Faker::Internet.email
-        subject "hello world"
-      end.to_s)
-      IO.write("tmp/2.eml", Mail.new do
-        to Faker::Internet.email
-        from Faker::Internet.email
-        subject "goodbye world"
-      end.to_s)
+      pid = fork do
+        IO.write("tmp/1.eml", Mail.new do
+          to Faker::Internet.email
+          from Faker::Internet.email
+          subject "hello world"
+        end.to_s)
+        IO.write("tmp/2.eml", Mail.new do
+          to Faker::Internet.email
+          from Faker::Internet.email
+          subject "goodbye world"
+        end.to_s)
+        sleep 0.3
+      end
+      Process.wait(pid)
       @result = subject.emails
     end
 
@@ -41,17 +45,20 @@ RSpec.describe Minbox::Inbox do
 
   describe "#open" do
     before :example do
-      subject.empty!
-      IO.write("tmp/1.eml", Mail.new do
-        to Faker::Internet.email
-        from Faker::Internet.email
-        subject "hello world"
-      end.to_s)
-      IO.write("tmp/2.eml", Mail.new do
-        to Faker::Internet.email
-        from Faker::Internet.email
-        subject "goodbye world"
-      end.to_s)
+      pid = fork do
+        IO.write("tmp/1.eml", Mail.new do
+          to Faker::Internet.email
+          from Faker::Internet.email
+          subject "hello world"
+        end.to_s)
+        IO.write("tmp/2.eml", Mail.new do
+          to Faker::Internet.email
+          from Faker::Internet.email
+          subject "goodbye world"
+        end.to_s)
+        sleep 0.3
+      end
+      Process.wait(pid)
     end
 
     context "when opening an email in the inbox" do
Gemfile.lock
@@ -4,6 +4,7 @@ PATH
     minbox (0.1.4)
       concurrent-ruby (~> 1.1)
       hashie (~> 3.6)
+      listen (~> 3.1)
       mail (~> 2.7)
       redis (~> 4.1)
       thor (~> 0.20)
@@ -19,10 +20,15 @@ GEM
     diff-lcs (1.3)
     faker (1.9.3)
       i18n (>= 0.7)
+    ffi (1.10.0)
     hashie (3.6.0)
     i18n (1.6.0)
       concurrent-ruby (~> 1.0)
     jaro_winkler (1.5.2)
+    listen (3.1.5)
+      rb-fsevent (~> 0.9, >= 0.9.4)
+      rb-inotify (~> 0.9, >= 0.9.7)
+      ruby_dep (~> 1.2)
     mail (2.7.1)
       mini_mime (>= 0.1.1)
     mini_mime (1.0.1)
@@ -33,6 +39,9 @@ GEM
     psych (3.1.0)
     rainbow (3.0.0)
     rake (10.5.0)
+    rb-fsevent (0.10.3)
+    rb-inotify (0.10.0)
+      ffi (~> 1.0)
     redis (4.1.0)
     rspec (3.8.0)
       rspec-core (~> 3.8.0)
@@ -59,6 +68,7 @@ GEM
     rubocop-rspec (1.32.0)
       rubocop (>= 0.60.0)
     ruby-progressbar (1.10.0)
+    ruby_dep (1.5.0)
     thor (0.20.3)
     unicode-display_width (1.4.1)
 
minbox.gemspec
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
 
   spec.add_dependency 'concurrent-ruby', '~> 1.1'
   spec.add_dependency 'hashie', '~> 3.6'
+  spec.add_dependency 'listen', '~> 3.1'
   spec.add_dependency 'mail', '~> 2.7'
   spec.add_dependency 'redis', '~> 4.1'
   spec.add_dependency 'thor', '~> 0.20'