Files
next.orly.dev/app/handle-close.go
mleku 581e0ec588
Some checks failed
Go / build (push) Has been cancelled
Go / release (push) Has been cancelled
Implement comprehensive WebSocket subscription stability fixes
- Resolved critical issues causing subscriptions to drop after 30-60 seconds due to unconsumed receiver channels.
- Introduced per-subscription consumer goroutines to ensure continuous event delivery and prevent channel overflow.
- Enhanced REQ parsing to handle both wrapped and unwrapped filter arrays, eliminating EOF errors.
- Updated publisher logic to correctly send events to receiver channels, ensuring proper event delivery to subscribers.
- Added extensive documentation and testing tools to verify subscription stability and performance.
- Bumped version to v0.26.2 to reflect these significant improvements.
2025-11-06 18:21:00 +00:00

53 lines
1.2 KiB
Go

package app
import (
"errors"
"lol.mleku.dev/chk"
"lol.mleku.dev/log"
"next.orly.dev/pkg/encoders/envelopes/closeenvelope"
)
// HandleClose processes a CLOSE envelope by unmarshalling the request,
// validates the presence of an <id> field, and signals cancellation for
// the associated listener through the server's publisher mechanism.
func (l *Listener) HandleClose(req []byte) (err error) {
var rem []byte
env := closeenvelope.New()
if rem, err = env.Unmarshal(req); chk.E(err) {
return
}
if len(rem) > 0 {
log.I.F("extra '%s'", rem)
}
if len(env.ID) == 0 {
return errors.New("CLOSE has no <id>")
}
subID := string(env.ID)
// Cancel the subscription goroutine by calling its cancel function
l.subscriptionsMu.Lock()
if cancelFunc, exists := l.subscriptions[subID]; exists {
log.D.F("cancelling subscription %s for %s", subID, l.remote)
cancelFunc()
delete(l.subscriptions, subID)
} else {
log.D.F("subscription %s not found for %s (already closed?)", subID, l.remote)
}
l.subscriptionsMu.Unlock()
// Also remove from publisher's tracking
l.publishers.Receive(
&W{
Cancel: true,
remote: l.remote,
Conn: l.conn,
Id: subID,
},
)
log.D.F("CLOSE processed for subscription %s @ %s", subID, l.remote)
return
}