Skip to content

Commit 5213603

Browse files
author
Philipp Heckel
committed
Subscribe to more than one topic
1 parent a481f4c commit 5213603

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

server/server.go

+50-27
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ const (
7878

7979
var (
8080
topicRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app!
81-
jsonRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/json$`)
82-
sseRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/sse$`)
83-
rawRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/raw$`)
81+
jsonRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/json$`)
82+
sseRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/sse$`)
83+
rawRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/raw$`)
8484

8585
staticRegex = regexp.MustCompile(`^/static/.+`)
8686

@@ -223,7 +223,7 @@ func (s *Server) handleStatic(w http.ResponseWriter, r *http.Request) error {
223223
}
224224

225225
func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visitor) error {
226-
t, err := s.topic(r.URL.Path[1:])
226+
t, err := s.topicFromID(r.URL.Path[1:])
227227
if err != nil {
228228
return err
229229
}
@@ -289,7 +289,9 @@ func (s *Server) handleSubscribe(w http.ResponseWriter, r *http.Request, v *visi
289289
return errHTTPTooManyRequests
290290
}
291291
defer v.RemoveSubscription()
292-
t, err := s.topic(strings.TrimSuffix(r.URL.Path[1:], "/"+format)) // Hack
292+
topicsStr := strings.TrimSuffix(r.URL.Path[1:], "/"+format) // Hack
293+
topicIDs := strings.Split(topicsStr, ",")
294+
topics, err := s.topicsFromIDs(topicIDs...)
293295
if err != nil {
294296
return err
295297
}
@@ -314,14 +316,21 @@ func (s *Server) handleSubscribe(w http.ResponseWriter, r *http.Request, v *visi
314316
w.Header().Set("Access-Control-Allow-Origin", "*") // CORS, allow cross-origin requests
315317
w.Header().Set("Content-Type", contentType+"; charset=utf-8") // Android/Volley client needs charset!
316318
if poll {
317-
return s.sendOldMessages(t, since, sub)
319+
return s.sendOldMessages(topics, since, sub)
318320
}
319-
subscriberID := t.Subscribe(sub)
320-
defer t.Unsubscribe(subscriberID)
321-
if err := sub(newOpenMessage(t.id)); err != nil { // Send out open message
321+
subscriberIDs := make([]int, 0)
322+
for _, t := range topics {
323+
subscriberIDs = append(subscriberIDs, t.Subscribe(sub))
324+
}
325+
defer func() {
326+
for i, subscriberID := range subscriberIDs {
327+
topics[i].Unsubscribe(subscriberID) // Order!
328+
}
329+
}()
330+
if err := sub(newOpenMessage(topicsStr)); err != nil { // Send out open message
322331
return err
323332
}
324-
if err := s.sendOldMessages(t, since, sub); err != nil {
333+
if err := s.sendOldMessages(topics, since, sub); err != nil {
325334
return err
326335
}
327336
for {
@@ -330,25 +339,27 @@ func (s *Server) handleSubscribe(w http.ResponseWriter, r *http.Request, v *visi
330339
return nil
331340
case <-time.After(s.config.KeepaliveInterval):
332341
v.Keepalive()
333-
if err := sub(newKeepaliveMessage(t.id)); err != nil { // Send keepalive message
342+
if err := sub(newKeepaliveMessage(topicsStr)); err != nil { // Send keepalive message
334343
return err
335344
}
336345
}
337346
}
338347
}
339348

340-
func (s *Server) sendOldMessages(t *topic, since sinceTime, sub subscriber) error {
349+
func (s *Server) sendOldMessages(topics []*topic, since sinceTime, sub subscriber) error {
341350
if since.IsNone() {
342351
return nil
343352
}
344-
messages, err := s.cache.Messages(t.id, since)
345-
if err != nil {
346-
return err
347-
}
348-
for _, m := range messages {
349-
if err := sub(m); err != nil {
353+
for _, t := range topics {
354+
messages, err := s.cache.Messages(t.id, since)
355+
if err != nil {
350356
return err
351357
}
358+
for _, m := range messages {
359+
if err := sub(m); err != nil {
360+
return err
361+
}
362+
}
352363
}
353364
return nil
354365
}
@@ -382,19 +393,31 @@ func (s *Server) handleOptions(w http.ResponseWriter, r *http.Request) error {
382393
return nil
383394
}
384395

385-
func (s *Server) topic(id string) (*topic, error) {
396+
func (s *Server) topicFromID(id string) (*topic, error) {
397+
topics, err := s.topicsFromIDs(id)
398+
if err != nil {
399+
return nil, err
400+
}
401+
return topics[0], nil
402+
}
403+
404+
func (s *Server) topicsFromIDs(ids... string) ([]*topic, error) {
386405
s.mu.Lock()
387406
defer s.mu.Unlock()
388-
if _, ok := s.topics[id]; !ok {
389-
if len(s.topics) >= s.config.GlobalTopicLimit {
390-
return nil, errHTTPTooManyRequests
391-
}
392-
s.topics[id] = newTopic(id, time.Now())
393-
if s.firebase != nil {
394-
s.topics[id].Subscribe(s.firebase)
407+
topics := make([]*topic, 0)
408+
for _, id := range ids {
409+
if _, ok := s.topics[id]; !ok {
410+
if len(s.topics) >= s.config.GlobalTopicLimit {
411+
return nil, errHTTPTooManyRequests
412+
}
413+
s.topics[id] = newTopic(id, time.Now())
414+
if s.firebase != nil {
415+
s.topics[id].Subscribe(s.firebase)
416+
}
395417
}
418+
topics = append(topics, s.topics[id])
396419
}
397-
return s.topics[id], nil
420+
return topics, nil
398421
}
399422

400423
func (s *Server) updateStatsAndExpire() {

0 commit comments

Comments
 (0)