code.vegaprotocol.io/vega@v0.79.0/datanode/api/utils.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  	"fmt"
    21  
    22  	"code.vegaprotocol.io/vega/datanode/entities"
    23  
    24  	"golang.org/x/sync/errgroup"
    25  	"google.golang.org/grpc/codes"
    26  	"google.golang.org/protobuf/proto"
    27  )
    28  
    29  func toProtos[T proto.Message, V entities.ProtoEntity[T]](inputs []V) []T {
    30  	protos := make([]T, 0, len(inputs))
    31  	for _, input := range inputs {
    32  		proto := input.ToProto()
    33  		protos = append(protos, proto)
    34  	}
    35  	return protos
    36  }
    37  
    38  func mapSlice[T proto.Message, V any](inputs []V, toProto func(V) (T, error)) ([]T, error) {
    39  	protos := make([]T, 0, len(inputs))
    40  	for _, input := range inputs {
    41  		proto, err := toProto(input)
    42  		if err != nil {
    43  			return nil, fmt.Errorf("failed to convert to proto: %w", err)
    44  		}
    45  		protos = append(protos, proto)
    46  	}
    47  	return protos, nil
    48  }
    49  
    50  // queryProtoEntities invokes queryFunc and converts the entity to protos.
    51  func queryProtoEntities[T proto.Message, E entities.ProtoEntity[T]](
    52  	ctx context.Context, eg *errgroup.Group, txHash entities.TxHash,
    53  	queryFunc func(ctx context.Context, txHash entities.TxHash) ([]E, error),
    54  	apiErr error,
    55  ) chan []T {
    56  	outChan := make(chan []T, 1)
    57  
    58  	eg.Go(func() error {
    59  		items, err := queryFunc(ctx, txHash)
    60  		if err != nil {
    61  			return apiError(codes.Internal, apiErr, err)
    62  		}
    63  
    64  		outChan <- toProtos[T](items)
    65  		return nil
    66  	})
    67  
    68  	return outChan
    69  }
    70  
    71  type mapableEntities interface {
    72  	entities.Entities | entities.LedgerEntry | entities.Transfer | entities.MarginLevels
    73  }
    74  
    75  // queryAndMapEntities invokes queryFunc and maps every single entity with mapFunc.
    76  func queryAndMapEntities[T proto.Message, E mapableEntities](
    77  	ctx context.Context, eg *errgroup.Group, txHash entities.TxHash,
    78  	queryFunc func(context.Context, entities.TxHash) ([]E, error),
    79  	mapFunc func(E) (T, error),
    80  	apiErr error,
    81  ) chan []T {
    82  	outChan := make(chan []T, 1)
    83  
    84  	eg.Go(func() error {
    85  		items, err := queryFunc(ctx, txHash)
    86  		if err != nil {
    87  			return apiError(codes.Internal, apiErr, err)
    88  		}
    89  
    90  		mapped, err := mapSlice(items, mapFunc)
    91  		if err != nil {
    92  			return apiError(codes.Internal, apiErr, err)
    93  		}
    94  
    95  		outChan <- mapped
    96  		return nil
    97  	})
    98  
    99  	return outChan
   100  }