func (h *EventHandler) getIndexOfSub(t interfaces.Topic, s interfaces.Subscriber) (int, error) { subs, ok := h.subscriber[t.Topic()] if !ok { return -1, errors.New("Topic does not exist.") } for k, sub := range subs { if s == sub { return k, nil } } return -1, errors.New("Subscriber not found.") }
// Publish sends out a notification to all subscribers that have a subscription for the given topic. func (h *EventHandler) Publish(t interfaces.Topic, p interfaces.Publisher) { if t.Topic() == interfaces.AllTopics { h.publishAll(t, p) return } // Publish to normal topic subscribers subs, ok := h.subscriber[t.Topic()] if ok { for _, sub := range subs { sub.Notify(t, p) } } // Publish to all topic subscribers subs, _ = h.subscriber[interfaces.AllTopics] for _, sub := range subs { sub.Notify(t, p) } }
// Subscribe subscribes a struct that implements the Subscriber interface to a topic. // The Subscriber's Notify method is called when the Publish method is called on the same topic. // Returns an error if the same Subscriber already has a subscribtion for the given topic. // Be aware, that subscribing to all topics does not revoke previous subscriptions. func (h *EventHandler) Subscribe(t interfaces.Topic, s interfaces.Subscriber) error { h.Lock() defer h.Unlock() // Check if topic exists. If not, create entry with new slice _, ok := h.subscriber[t.Topic()] if !ok { h.subscriber[t.Topic()] = []interfaces.Subscriber{s} return nil } // Check if subscriber already has a subscription of that topic _, err := h.getIndexOfSub(t, s) if err == nil { return fmt.Errorf("Subscriber %v has already a subscription for topic %v.", s, t) } // Add subscriber h.subscriber[t.Topic()] = append(h.subscriber[t.Topic()], s) return nil }
// Unsubscribe unsubscribes a struct that implements the Subscriber interface from a topic. // Returns an error if the given Subscriber does not have a subscription for the given topic. func (h *EventHandler) Unsubscribe(t interfaces.Topic, s interfaces.Subscriber) error { h.Lock() defer h.Unlock() // Check if subscriber exists index, err := h.getIndexOfSub(t, s) if err != nil { return err } // Delete subscriber from slice h.subscriber[t.Topic()], h.subscriber[t.Topic()][len(h.subscriber[t.Topic()])-1] = append(h.subscriber[t.Topic()][:index], h.subscriber[t.Topic()][index+1:]...), nil return nil }