From c37be91b068606c9023c790c59abe4b85d9d8c2b Mon Sep 17 00:00:00 2001
From: a <a@tuxpa.in>
Date: Mon, 17 Feb 2025 17:30:06 -0600
Subject: [PATCH] change subscription logic to always try sending before the
 first notify, but otherwise allow sending of errors.

---
 contrib/extension/subscription/engine.go       | 3 +--
 contrib/extension/subscription/subscription.go | 7 ++++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/contrib/extension/subscription/engine.go b/contrib/extension/subscription/engine.go
index e8d1aa6..369c9ae 100644
--- a/contrib/extension/subscription/engine.go
+++ b/contrib/extension/subscription/engine.go
@@ -55,10 +55,9 @@ func (e *Engine) Middleware() func(jsonrpc.Handler) jsonrpc.Handler {
 				e.mu.Lock()
 				e.subscriptions[n.id] = n
 				e.mu.Unlock()
-				// now send the subscription id back
-				w.Send(n.id, nil)
 				// then inject the notifier
 				r = r.WithContext(context.WithValue(r.Context(), notifierKey{}, n))
+				// start serving the request/sub
 				h.ServeRPC(w, r)
 			case strings.HasSuffix(r.Method, serviceMethodSeparator+unsubscribeMethodSuffix):
 				// read the subscription id to close
diff --git a/contrib/extension/subscription/subscription.go b/contrib/extension/subscription/subscription.go
index f970f24..bd9159a 100644
--- a/contrib/extension/subscription/subscription.go
+++ b/contrib/extension/subscription/subscription.go
@@ -35,7 +35,7 @@ var (
 	// ErrNotificationNotFound is returned when the notification for the given id is not found
 	ErrSubscriptionNotFound = errors.New("subscription not found")
 	// ErrNotificationNotFound is returned when the notification for the given id is not found
-	ErrSubscriptionClosed = errors.New("subscription not found")
+	ErrSubscriptionClosed = errors.New("subscription closed. not found")
 )
 
 var globalInc = atomic.Int64{}
@@ -110,6 +110,11 @@ func (n *Notifier) Err() <-chan error {
 
 func (n *Notifier) send(data json.RawMessage) error {
 	params, _ := jjson.Marshal(&subscriptionResult{ID: string(n.id), Result: data})
+	// try to send the id back. this will just fail with errAlreadySent if its already been sent.
+	// so it is safe-ish to just ignore this error
+	// technically we should check for jsonrpc.ErrSendAlreadyCalled and then error earlier otherwise... but is that really right?
+	_ = n.h.Send(n.id, nil)
+
 	err := n.h.Notify(
 		n.namespace+
 			serviceMethodSeparator+
-- 
GitLab