code.vegaprotocol.io/vega@v0.79.0/datanode/api/observe.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package api 17 18 import ( 19 "context" 20 "time" 21 22 "code.vegaprotocol.io/vega/datanode/metrics" 23 "code.vegaprotocol.io/vega/logging" 24 ) 25 26 func observe[T any](ctx context.Context, log *logging.Logger, eventType string, eventsInChan <-chan []T, 27 ref any, send func(T) error, 28 ) error { 29 defer metrics.StartActiveSubscriptionCountGRPC(eventType)() 30 31 publishedEventStatTicker := time.NewTicker(time.Second) 32 defer publishedEventStatTicker.Stop() 33 34 var ( 35 publishedEvents int64 36 err error 37 ) 38 for { 39 select { 40 case <-publishedEventStatTicker.C: 41 metrics.PublishedEventsAdd(eventType, float64(publishedEvents)) 42 publishedEvents = 0 43 case events, ok := <-eventsInChan: 44 if !ok { 45 err = ErrChannelClosed 46 log.Errorf("subscriber to %s, reference %v, error: %v", eventType, ref, err) 47 return formatE(ErrStreamInternal, err) 48 } 49 for _, event := range events { 50 if err = send(event); err != nil { 51 log.Errorf("rpc stream error, subscriber to %s, reference %v, error: %v", eventType, ref, err) 52 return formatE(ErrStreamInternal, err) 53 } 54 publishedEvents++ 55 } 56 case <-ctx.Done(): 57 err = ctx.Err() 58 if log.GetLevel() == logging.DebugLevel { 59 log.Debugf("rpc stream ctx error, subscriber to %s, reference %v, error: %v", eventType, ref, err) 60 } 61 return formatE(ErrStreamInternal, err) 62 } 63 64 if eventsInChan == nil { 65 if log.GetLevel() == logging.DebugLevel { 66 log.Debugf("rpc stream closed, subscriber to %s, reference %v, error: %v", eventType, ref, err) 67 } 68 return formatE(ErrStreamClosed) 69 } 70 } 71 } 72 73 func observeBatch[T any](ctx context.Context, log *logging.Logger, eventType string, 74 eventsInChan <-chan []T, ref any, 75 send func([]T) error, 76 ) error { 77 defer metrics.StartActiveSubscriptionCountGRPC(eventType)() 78 79 publishedEventStatTicker := time.NewTicker(time.Second) 80 defer publishedEventStatTicker.Stop() 81 82 var ( 83 publishedEvents int64 84 err error 85 ) 86 for { 87 select { 88 case <-publishedEventStatTicker.C: 89 metrics.PublishedEventsAdd(eventType, float64(publishedEvents)) 90 publishedEvents = 0 91 case events, ok := <-eventsInChan: 92 if !ok { 93 err = ErrChannelClosed 94 log.Errorf("subscriber to %s, reference %v, error: %v", eventType, ref, err) 95 return formatE(ErrStreamInternal, err) 96 } 97 err = send(events) 98 if err != nil { 99 log.Errorf("rpc stream error, subscriber to %s, reference %v, error: %v", eventType, ref, err) 100 return formatE(ErrStreamInternal, err) 101 } 102 publishedEvents = publishedEvents + int64(len(events)) 103 case <-ctx.Done(): 104 err = ctx.Err() 105 if log.GetLevel() == logging.DebugLevel { 106 log.Debugf("rpc stream ctx error, subscriber to %s, reference %v, error: %v", eventType, ref, err) 107 } 108 return formatE(ErrStreamInternal, err) 109 } 110 111 if eventsInChan == nil { 112 if log.GetLevel() == logging.DebugLevel { 113 log.Debugf("rpc stream closed, subscriber to %s, reference %v, error: %v", eventType, ref, err) 114 } 115 return formatE(ErrStreamClosed) 116 } 117 } 118 }