s.smu.Lock() if ok := s.subscriptions.HasChannel(msg.Identifier); ok { s.smu.Unlock() return nil, fmt.Errorf("already subscribed to %s", msg.Identifier) } res, err := n.controller.Subscribe(s.closeCtx, s.GetID(), s.env, s.GetIdentifiers(), msg.Identifier) if s.IsClosed() { s.Log.Debug("skip subscribe result: closed") return nil, nil } if res == nil && err == nil { return nil, nil } s.Log.Debug("controller subscribe", "response", res, "err", err) var confirmed bool if err != nil { if res == nil || res.Status == common.ERROR { return nil, errorx.Decorate(err, "subscribe failed for %s", msg.Identifier) } } else if res.Status == common.SUCCESS { confirmed = true s.subscriptions.AddChannel(msg.Identifier) s.Log.Debug("subscribed", "identifier", msg.Identifier) } else { s.Log.Debug("subscription rejected", "identifier", msg.Identifier) } s.smu.Unlock() if res != nil { n.handleCommandReply(s, msg, res) n.markDisconnectable(s, res.DisconnectInterest) } if confirmed { if s.IsResumeable() { if berr := n.broker.CommitSession(s.GetID(), s); berr != nil { s.Log.Error("failed to persist session in cache", "error", berr) } } if msg.History.Since > 0 || msg.History.Streams != nil { if err := n.History(s, msg); err != nil { s.Log.Warn("couldn't retrieve history", "identifier", msg.Identifier, "error", err) } } if msg.Presence != nil { if err := n.handlePresenceReply(s, msg.Identifier, common.PresenceJoinType, msg.Presence); err != nil { s.Log.Warn("couldn't process presence join", "identifier", msg.Identifier, "error", err) } } } return res, nil }