func subscribeWebsocket(resp http.ResponseWriter, req *http.Request, topic string, useNewPublisher func(pubsub.Publisher) error) { updates, err := pubsub.Subscribe(topic, useNewPublisher) if err != nil { log.Println("subscribing for updates on", topic, "failed:", err) resp.WriteHeader(http.StatusInternalServerError) return } conn, err := upgrader.Upgrade(resp, req, nil) if err != nil { log.Println(err) return } viewer := &Viewer{ Conn: conn, ServerAddress: topic, Updates: updates, } viewer.writeUpdatesUntilClose() pubsub.Unsubscribe(updates, topic) _ = viewer.Close() }
func (ms *MasterServerPoller) refreshServers() error { // open connection conn, err := net.DialTimeout("tcp", ms.Address, 15*time.Second) if err != nil { return err } defer conn.Close() in := bufio.NewScanner(conn) out := bufio.NewWriter(conn) // request new list _, err = out.WriteString("list\n") if err != nil { return err } err = out.Flush() if err != nil { return err } updatedList := map[string]extinfo.BasicInfo{} // process response for in.Scan() { msg := in.Text() if msg == "\x00" { // end of list continue } msg = strings.TrimPrefix(msg, "addserver ") msg = strings.TrimSpace(msg) addr := strings.Replace(msg, " ", ":", -1) // keep old state if possible oldState, known := ms.ServerStates[addr] updatedList[addr] = oldState if !known { // subscribe to updates if the server is new updates, err := pubsub.Subscribe(addr, func(publisher pubsub.Publisher) error { return NewServerPoller( publisher, func(sp *ServerPoller) { sp.Address = addr }, ) }) if err != nil { log.Println("error subscribing to updates on "+addr+":", err) } ms.Subscriptions[addr] = updates go func(updates <-chan pubsub.Update) { for upd := range updates { ms.ServerUpdates <- upd } }(updates) } } // unsubscribe from updates about servers not on the list anymore for addr := range ms.ServerStates { if _, ok := updatedList[addr]; !ok { pubsub.Unsubscribe(ms.ServerUpdates, addr) delete(ms.Subscriptions, addr) } } ms.ServerStates = updatedList return in.Err() }