code.vegaprotocol.io/vega@v0.79.0/vegatools/events/events.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 events
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"os"
    22  	"time"
    23  
    24  	"code.vegaprotocol.io/vega/datanode/broker"
    25  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    26  
    27  	"github.com/golang/protobuf/jsonpb"
    28  	"github.com/golang/protobuf/proto"
    29  )
    30  
    31  func Run(in, out string) error {
    32  	marshaler := jsonpb.Marshaler{
    33  		EnumsAsInts: true,
    34  		OrigName:    true,
    35  		Indent:      "   ",
    36  	}
    37  
    38  	fmt.Println("parsing event bytes from", in, "into json:", out)
    39  	f, err := os.Create(out)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	defer f.Close()
    44  
    45  	eventFile, err := os.Open(in)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	defer eventFile.Close()
    50  
    51  	ctx, cfunc := context.WithCancel(context.Background())
    52  	defer cfunc()
    53  
    54  	ch, ech := startFileRead(ctx, eventFile)
    55  
    56  	for {
    57  		select {
    58  		case e, ok := <-ch:
    59  			if e == nil && !ok {
    60  				return nil
    61  			}
    62  			es, err := marshaler.MarshalToString(e)
    63  			if err != nil {
    64  				return err
    65  			}
    66  			if _, err := f.WriteString(es + "\n"); err != nil {
    67  				return err
    68  			}
    69  		case err, ok := <-ech:
    70  			if err == nil && !ok {
    71  				return nil
    72  			}
    73  			return err
    74  		}
    75  	}
    76  }
    77  
    78  func startFileRead(ctx context.Context, eventFile *os.File) (<-chan *eventspb.BusEvent, <-chan error) {
    79  	ch := make(chan *eventspb.BusEvent, 1)
    80  	ech := make(chan error, 1)
    81  	go func() {
    82  		defer func() {
    83  			eventFile.Close()
    84  			close(ch)
    85  			close(ech)
    86  		}()
    87  
    88  		var offset, nEvents int64
    89  		now := time.Now()
    90  		for {
    91  			select {
    92  			case <-ctx.Done():
    93  				return
    94  			default:
    95  				rawEvent, _, read, err := broker.ReadRawEvent(eventFile, offset)
    96  				if err != nil {
    97  					ech <- fmt.Errorf("failed to read raw event: %w", err)
    98  					return
    99  				}
   100  
   101  				if read == 0 {
   102  					return
   103  				}
   104  
   105  				offset += int64(read)
   106  				busEvent := &eventspb.BusEvent{}
   107  				if err := proto.Unmarshal(rawEvent, busEvent); err != nil {
   108  					ech <- fmt.Errorf("failed to unmarshal bus event: %w", err)
   109  					return
   110  				}
   111  				ch <- busEvent
   112  				// if can be quite slow so lets print something out every now and again so it doesn't look like its frozen
   113  				nEvents++
   114  				if time.Since(now) > time.Second {
   115  					fmt.Println("events parsed so far:", nEvents)
   116  					now = time.Now()
   117  				}
   118  			}
   119  		}
   120  	}()
   121  	return ch, ech
   122  }