func (r *Registry) Push(name string, value *Message) error { r.Lock() defer r.Unlock() if mailbox, ok := r.mailboxes[name]; ok { return mailbox.Push(value) } return errors.Subject(ENoMailbox, name) }
func (s *Service) handleInternal(c net.Conn, msg *Push, data *clientData) error { var err error switch msg.Name { case ":lwt": debugf("%s: setup LWT", s.Address) err = s.setupLWT(msg.Message, data) case ":publish", ":subscribe": err = s.Registry.Push(msg.Name, msg.Message) default: err = errors.Subject(ErrUknownSystemMailbox, msg.Name) } return err }
func (s *Service) setupLWT(msg *Message, data *clientData) error { s.lock.Lock() defer s.lock.Unlock() if msg.CorrelationId == "" { data.lwt = msg } else { info, ok := data.ephemerals[msg.CorrelationId] if !ok { return errors.Subject(ENoMailbox, msg.CorrelationId) } info.lwt = msg } return nil }
func (r *Registry) LongPoll(name string, til time.Duration) (*Delivery, error) { r.Lock() mailbox, ok := r.mailboxes[name] if !ok { debugf("missing mailbox %s\n", name) r.Unlock() return nil, errors.Subject(ENoMailbox, name) } debugf("long polling %s: %#v\n", name, mailbox) val, err := mailbox.Poll() if err != nil { r.Unlock() return nil, err } if val != nil { r.Unlock() return NewDelivery(mailbox, val), nil } indicator := mailbox.AddWatcher() r.Unlock() select { case val := <-indicator: if val == nil { return nil, nil } return NewDelivery(mailbox, val), nil case <-time.Tick(til): return nil, nil } }
func (r *Registry) LongPollCancelable(name string, til time.Duration, done chan struct{}) (*Delivery, error) { r.Lock() mailbox, ok := r.mailboxes[name] if !ok { debugf("missing mailbox %s\n", name) r.Unlock() return nil, errors.Subject(ENoMailbox, name) } debugf("long polling %s: %#v\n", name, mailbox) val, err := mailbox.Poll() if err != nil { r.Unlock() return nil, err } if val != nil { r.Unlock() return NewDelivery(mailbox, val), nil } indicator := mailbox.AddWatcherCancelable(done) r.Unlock() select { case <-done: // It's possible for both done and indicator to have values. // So we need to also check if there a value in indicator and // if so, pull it out and nack it. select { case val := <-indicator: if val != nil { mailbox.Nack(val.MessageId) } default: } return nil, nil case val := <-indicator: // It's possible for both done and indicator to have values. // So we need to also check if there a value in indicator and // if so, pull it out and nack it. select { case <-done: if val != nil { mailbox.Nack(val.MessageId) return nil, nil } default: } if val == nil { return nil, nil } return NewDelivery(mailbox, val), nil case <-time.Tick(til): return nil, nil } }