func sendLoop(stream pb.Watch_WatchServer, watcher storage.Watcher, closec chan struct{}) { for { select { case e, ok := <-watcher.Chan(): if !ok { return } err := stream.Send(&pb.WatchResponse{Event: &e}) storage.ReportEventReceived() if err != nil { return } case <-closec: // drain the chan to clean up pending events for { _, ok := <-watcher.Chan() if !ok { return } storage.ReportEventReceived() } return } } }
func (sws *serverWatchStream) sendLoop() { for { select { case wresp, ok := <-sws.watchStream.Chan(): if !ok { return } // TODO: evs is []storagepb.Event type // either return []*storagepb.Event from storage package // or define protocol buffer with []storagepb.Event. evs := wresp.Events events := make([]*storagepb.Event, len(evs)) for i := range evs { events[i] = &evs[i] } err := sws.gRPCStream.Send(&pb.WatchResponse{ Header: sws.newResponseHeader(wresp.Revision), WatchId: int64(wresp.WatchID), Events: events, CompactRevision: wresp.CompactRevision, }) storage.ReportEventReceived() if err != nil { return } case c, ok := <-sws.ctrlStream: if !ok { return } if err := sws.gRPCStream.Send(c); err != nil { return } case <-sws.closec: // drain the chan to clean up pending events for { _, ok := <-sws.watchStream.Chan() if !ok { return } storage.ReportEventReceived() } } } }
func (sws *serverWatchStream) sendLoop() { // watch ids that are currently active ids := make(map[storage.WatchID]struct{}) // watch responses pending on a watch id creation message pending := make(map[storage.WatchID][]*pb.WatchResponse) progressTicker := time.NewTicker(ProgressReportInterval) defer progressTicker.Stop() for { select { case wresp, ok := <-sws.watchStream.Chan(): if !ok { return } // TODO: evs is []storagepb.Event type // either return []*storagepb.Event from storage package // or define protocol buffer with []storagepb.Event. evs := wresp.Events events := make([]*storagepb.Event, len(evs)) for i := range evs { events[i] = &evs[i] } wr := &pb.WatchResponse{ Header: sws.newResponseHeader(wresp.Revision), WatchId: int64(wresp.WatchID), Events: events, CompactRevision: wresp.CompactRevision, } if _, hasId := ids[wresp.WatchID]; !hasId { // buffer if id not yet announced wrs := append(pending[wresp.WatchID], wr) pending[wresp.WatchID] = wrs continue } storage.ReportEventReceived() if err := sws.gRPCStream.Send(wr); err != nil { return } if _, ok := sws.progress[wresp.WatchID]; ok { sws.progress[wresp.WatchID] = false } case c, ok := <-sws.ctrlStream: if !ok { return } if err := sws.gRPCStream.Send(c); err != nil { return } // track id creation wid := storage.WatchID(c.WatchId) if c.Canceled { delete(ids, wid) continue } if c.Created { // flush buffered events ids[wid] = struct{}{} for _, v := range pending[wid] { storage.ReportEventReceived() if err := sws.gRPCStream.Send(v); err != nil { return } } delete(pending, wid) } case <-progressTicker.C: for id, ok := range sws.progress { if ok { sws.watchStream.RequestProgress(id) } sws.progress[id] = true } case <-sws.closec: // drain the chan to clean up pending events for range sws.watchStream.Chan() { storage.ReportEventReceived() } for _, wrs := range pending { for range wrs { storage.ReportEventReceived() } } } } }