Repository: inbucket/inbucket
Pull request #319 (2023-01-23 00:18:54)

extension: Make AfterMessageStored async


Patch:
diff --git a/pkg/extension/host.go b/pkg/extension/host.go
index ac86b7a..7889050 100644
--- a/pkg/extension/host.go
+++ b/pkg/extension/host.go
@@ -10,8 +10,17 @@ type Host struct {
 }
 
 // Events defines all the event types supported by the extension host.
+//
+// Before-events provide an opportunity for extensions to alter how Inbucket responds to that type
+// of event.  These events are processed synchronously; expensive operations will reduce the
+// perceived performance of Inbucket.  The first listener in the list to respond with a non-nil
+// value will determine the response, and the remaining listeners will not be called.
+//
+// After-events allow extensions to take an action after an event has completed.  These events are
+// processed asynchronously with respect to the rest of Inbuckets operation.  However, an event
+// listener will not be called until the one before it complets.
 type Events struct {
-	MessageStored EventBroker[event.MessageMetadata, Void]
+	AfterMessageStored EventBroker[event.MessageMetadata, Void]
 }
 
 // Void indicates the event emitter will ignore any value returned by listeners.
diff --git a/pkg/message/manager.go b/pkg/message/manager.go
index 5efa4e0..8cdb66a 100644
--- a/pkg/message/manager.go
+++ b/pkg/message/manager.go
@@ -92,7 +92,7 @@ func (s *StoreManager) Deliver(
 		Date:    delivery.Date(),
 		Size:    delivery.Size(),
 	}
-	s.ExtHost.Events.MessageStored.Emit(&event)
+	go s.ExtHost.Events.AfterMessageStored.Emit(&event)
 
 	return id, nil
 }
diff --git a/pkg/msghub/hub.go b/pkg/msghub/hub.go
index 30c8bfa..ef98206 100644
--- a/pkg/msghub/hub.go
+++ b/pkg/msghub/hub.go
@@ -35,7 +35,7 @@ func New(historyLen int, extHost *extension.Host) *Hub {
 	}
 
 	// Register an extension event listener for MessageStored.
-	extHost.Events.MessageStored.AddListener("msghub",
+	extHost.Events.AfterMessageStored.AddListener("msghub",
 		func(msg event.MessageMetadata) *extension.Void {
 			hub.Dispatch(msg)
 			return nil


Test patch:
diff --git a/pkg/message/manager_test.go b/pkg/message/manager_test.go
index d21608c..9826953 100644
--- a/pkg/message/manager_test.go
+++ b/pkg/message/manager_test.go
@@ -2,6 +2,7 @@ package message_test
 
 import (
 	"testing"
+	"time"
 
 	"github.com/inbucket/inbucket/pkg/extension"
 	"github.com/inbucket/inbucket/pkg/extension/event"
@@ -20,11 +21,13 @@ func TestManagerEmitsMessageStoredEvent(t *testing.T) {
 	}
 
 	// Capture message event.
-	var got *event.MessageMetadata
-	extHost.Events.MessageStored.AddListener(
+	gotc := make(chan *event.MessageMetadata)
+	defer close(gotc)
+
+	extHost.Events.AfterMessageStored.AddListener(
 		"test",
 		func(msg event.MessageMetadata) *extension.Void {
-			got = &msg
+			gotc <- &msg
 			return nil
 		})
 
@@ -39,5 +42,10 @@ func TestManagerEmitsMessageStoredEvent(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	assert.NotNil(t, got, "No event received, or it was nil")
+	select {
+	case got := <-gotc:
+		assert.NotNil(t, got, "No event received, or it was nil")
+	case <-time.After(time.Second * 2):
+		t.Fatal("Timeout waiting for message event")
+	}
 }