// StartMonitorFeed starts a goroutine which processes events published to the // supplied Subscription. The goroutine will continue running until the // Subscription's Events feed is closed. func (nsm *NodeStatusMonitor) StartMonitorFeed(feed *util.Feed) { sub := feed.Subscribe() go func() { for event := range sub.Events() { if syncEvent, ok := event.(*TestSyncEvent); ok { syncEvent.consume() } ProcessNodeEvent(nsm, event) storage.ProcessStoreEvent(nsm, event) } }() }
func TestNodeStatusMonitor(t *testing.T) { defer leaktest.AfterTest(t) desc1 := &proto.RangeDescriptor{ RaftID: 1, StartKey: proto.Key("a"), EndKey: proto.Key("b"), } desc2 := &proto.RangeDescriptor{ RaftID: 2, StartKey: proto.Key("b"), EndKey: proto.Key("c"), } stats := engine.MVCCStats{ LiveBytes: 1, KeyBytes: 2, ValBytes: 2, IntentBytes: 1, LiveCount: 1, KeyCount: 1, ValCount: 1, IntentCount: 1, IntentAge: 1, GCBytesAge: 1, LastUpdateNanos: 1 * 1E9, } monitorStopper := stop.NewStopper() storeStopper := stop.NewStopper() feed := &util.Feed{} monitor := NewNodeStatusMonitor() sub := feed.Subscribe() monitorStopper.RunWorker(func() { for event := range sub.Events() { storage.ProcessStoreEvent(monitor, event) ProcessNodeEvent(monitor, event) } }) for i := 0; i < 3; i++ { id := proto.StoreID(i + 1) eventList := []interface{}{ &storage.StartStoreEvent{ StoreID: id, }, &storage.BeginScanRangesEvent{ // Begin scan phase. StoreID: id, }, &storage.UpdateRangeEvent{ // Update during scan, expect it to be ignored. StoreID: id, Desc: desc1, Stats: stats, Delta: stats, }, &storage.RegisterRangeEvent{ StoreID: id, Desc: desc2, Stats: stats, Scan: false, // should lead to this being ignored }, &storage.RegisterRangeEvent{ StoreID: id, Desc: desc1, Stats: stats, Scan: true, // not ignored }, &storage.UpdateRangeEvent{ // Update during scan after register, should be picked up StoreID: id, Desc: desc1, Stats: stats, Delta: stats, }, &storage.EndScanRangesEvent{ // End Scan. StoreID: id, }, &storage.RegisterRangeEvent{ StoreID: id, Desc: desc2, Stats: stats, Scan: true, // ignored, not in ScanRanges mode }, &storage.UpdateRangeEvent{ StoreID: id, Desc: desc1, Stats: stats, Delta: stats, }, &storage.UpdateRangeEvent{ StoreID: id, Desc: desc1, Stats: stats, Delta: stats, }, &storage.SplitRangeEvent{ StoreID: id, Original: storage.UpdateRangeEvent{ StoreID: id, Desc: desc1, Stats: stats, Delta: stats, }, New: storage.RegisterRangeEvent{ StoreID: id, Desc: desc2, Stats: stats, Scan: false, }, }, &storage.UpdateRangeEvent{ StoreID: id, Desc: desc2, Stats: stats, Delta: stats, }, &storage.UpdateRangeEvent{ StoreID: id, Desc: desc2, Stats: stats, Delta: stats, }, &CallSuccessEvent{ NodeID: proto.NodeID(1), Method: proto.Get, }, &CallSuccessEvent{ NodeID: proto.NodeID(1), Method: proto.Put, }, &CallErrorEvent{ NodeID: proto.NodeID(1), Method: proto.Scan, }, } storeStopper.RunWorker(func() { for _, event := range eventList { feed.Publish(event) } }) } storeStopper.Stop() feed.Close() monitorStopper.Stop() expectedStats := engine.MVCCStats{ LiveBytes: 6, KeyBytes: 12, ValBytes: 12, IntentBytes: 6, LiveCount: 6, KeyCount: 6, ValCount: 6, IntentCount: 6, IntentAge: 6, GCBytesAge: 6, LastUpdateNanos: 1 * 1E9, } if a, e := len(monitor.stores), 3; a != e { t.Fatalf("unexpected number of stores recorded by monitor; expected %d, got %d", e, a) } for id, store := range monitor.stores { if a, e := store.stats, expectedStats; !reflect.DeepEqual(a, e) { t.Errorf("monitored stats for store %d did not match expectation: %v != %v", id, a, e) } if a, e := store.rangeCount, int64(2); a != e { t.Errorf("monitored range count for store %d did not match expectation: %d != %d", id, a, e) } } if a, e := monitor.callCount, int64(6); a != e { t.Errorf("monitored stats for node recorded wrong number of ops %d, expected %d", a, e) } if a, e := monitor.callErrors, int64(3); a != e { t.Errorf("monitored stats for node recorded wrong number of errors %d, expected %d", a, e) } }
// StartMonitorFeed starts a goroutine which processes events published to the // supplied Subscription. The goroutine will continue running until the // Subscription's Events feed is closed. func (nsm *NodeStatusMonitor) StartMonitorFeed(feed *util.Feed) { feed.Subscribe(func(event interface{}) { ProcessNodeEvent(nsm, event) storage.ProcessStoreEvent(nsm, event) }) }