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  }