Updates for NATS Streaming support

NATS Streaming is deprecated and will be removed from OpenFaaS
CE in a future release for security reasons.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
Alex Ellis (OpenFaaS Ltd)
2023-01-17 21:55:48 +00:00
parent 8e1c34e222
commit c26ec5221e
188 changed files with 22639 additions and 3717 deletions

View File

@ -101,6 +101,12 @@ type subscription struct {
inboxSub *nats.Subscription
opts SubscriptionOptions
cb MsgHandler
// closed indicate that sub.Close() was invoked, but fullyClosed
// is only set if the close/unsub protocol was successful. This
// allow the user to be able to call sub.Close() several times
// in case an error is returned.
closed bool
fullyClosed bool
}
// SubscriptionOption is a function on the options for a subscription.
@ -247,6 +253,16 @@ func (sc *conn) subscribe(subject, qgroup string, cb MsgHandler, options ...Subs
sc.subMap[sub.inbox] = sub
sc.Unlock()
doClean := true
defer func() {
if doClean {
sc.Lock()
//Un-register subscription.
delete(sc.subMap, sub.inbox)
sc.Unlock()
}
}()
// Hold lock throughout.
sub.Lock()
defer sub.Unlock()
@ -319,6 +335,9 @@ func (sc *conn) subscribe(subject, qgroup string, cb MsgHandler, options ...Subs
}
sub.ackInbox = r.AckInbox
// Prevent cleanup on exit.
doClean = false
return sub, nil
}
@ -414,15 +433,22 @@ func (sub *subscription) SetPendingLimits(msgLimit, bytesLimit int) error {
// given boolean.
func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
sub.Lock()
sc := sub.sc
if sc == nil {
// Already closed.
// If we are fully closed, return error indicating that the
// subscription is invalid. Note that conn.Close() in this case
// returns nil, but keeping behavior same so we don't have breaking change.
if sub.fullyClosed {
sub.Unlock()
return ErrBadSubscription
}
sub.sc = nil
sub.inboxSub.Unsubscribe()
sub.inboxSub = nil
wasClosed := sub.closed
// If this is the very first Close() call, do some internal cleanup,
// otherwise, simply send the close protocol message.
if !wasClosed {
sub.closed = true
sub.inboxSub.Unsubscribe()
sub.inboxSub = nil
}
sc := sub.sc
sub.Unlock()
sc.Lock()
@ -430,8 +456,9 @@ func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
sc.Unlock()
return ErrConnectionClosed
}
delete(sc.subMap, sub.inbox)
if !wasClosed {
delete(sc.subMap, sub.inbox)
}
reqSubject := sc.unsubRequests
if doClose {
reqSubject = sc.subCloseRequests
@ -464,10 +491,13 @@ func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
if err := r.Unmarshal(reply.Data); err != nil {
return err
}
// As long as we got a valid response, we consider the subscription fully closed.
sub.Lock()
sub.fullyClosed = true
sub.Unlock()
if r.Error != "" {
return errors.New(r.Error)
}
return nil
}
@ -493,13 +523,14 @@ func (msg *Msg) Ack() error {
ackSubject := sub.ackInbox
isManualAck := sub.opts.ManualAcks
sc := sub.sc
closed := sub.closed
sub.RUnlock()
// Check for error conditions.
if !isManualAck {
return ErrManualAck
}
if sc == nil {
if closed {
return ErrBadSubscription
}