Add PubSub topics.

A TopicFunc is an interface to let the pubisher decide whether it needs
to send a message to a subscriber or not. It returns true if the
publisher must send the message and false otherwise.

Users of the pubsub package can create a subscriber with a topic
function by calling `pubsub.SubscribeTopic`.

Message delivery has also been modified to use concurrent channels per
subscriber. That way, topic verification and message delivery is not
o(N+M) anymore, based on the number of subscribers and topic verification
complexity.

Using pubsub topics, the API stops controlling the message delivery,
delegating that function to a topic generated with the filtering
provided by the user. The publisher sends every message to the
subscriber if there is no filter, but the api doesn't have to select
messages to return anymore.

Signed-off-by: David Calavera <david.calavera@gmail.com>
Upstream-commit: 434d2e8745696255a204d9eefc6a2854ff74e5c2
Component: engine
This commit is contained in:
David Calavera
2015-12-02 16:43:49 -05:00
parent 79750c94df
commit d555e15f77
5 changed files with 96 additions and 49 deletions
@@ -92,27 +92,11 @@ func (s *router) getEvents(ctx context.Context, w http.ResponseWriter, r *http.R
enc := json.NewEncoder(output)
current, l, cancel := s.daemon.SubscribeToEvents()
defer cancel()
buffered, l := s.daemon.SubscribeToEvents(since, sinceNano, ef)
defer s.daemon.UnsubscribeFromEvents(l)
eventFilter := s.daemon.GetEventFilter(ef)
handleEvent := func(ev *jsonmessage.JSONMessage) error {
if eventFilter.Include(ev) {
if err := enc.Encode(ev); err != nil {
return err
}
}
return nil
}
if since == -1 {
current = nil
}
for _, ev := range current {
if ev.Time < since || ((ev.Time == since) && (ev.TimeNano < sinceNano)) {
continue
}
if err := handleEvent(ev); err != nil {
for _, ev := range buffered {
if err := enc.Encode(ev); err != nil {
return err
}
}
@@ -129,7 +113,7 @@ func (s *router) getEvents(ctx context.Context, w http.ResponseWriter, r *http.R
if !ok {
continue
}
if err := handleEvent(jev); err != nil {
if err := enc.Encode(jev); err != nil {
return err
}
case <-timer.C: