code.vegaprotocol.io/vega@v0.79.0/core/evtforward/snapshot.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 evtforward
    17  
    18  import (
    19  	"context"
    20  	"slices"
    21  
    22  	"code.vegaprotocol.io/vega/core/types"
    23  	vgcontext "code.vegaprotocol.io/vega/libs/context"
    24  	"code.vegaprotocol.io/vega/libs/proto"
    25  	snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    26  
    27  	"github.com/emirpasic/gods/sets/treeset"
    28  	"golang.org/x/exp/maps"
    29  )
    30  
    31  var (
    32  	key = (&types.PayloadEventForwarder{}).Key()
    33  
    34  	hashKeys = []string{
    35  		key,
    36  	}
    37  )
    38  
    39  func (f *Forwarder) Namespace() types.SnapshotNamespace {
    40  	return types.EventForwarderSnapshot
    41  }
    42  
    43  func (f *Forwarder) Keys() []string {
    44  	return hashKeys
    45  }
    46  
    47  func (f *Forwarder) Stopped() bool {
    48  	return false
    49  }
    50  
    51  func (f *Forwarder) serialise() ([]byte, error) {
    52  	slice := make([]*snapshotpb.EventForwarderBucket, 0, f.ackedEvts.Size())
    53  	iter := f.ackedEvts.events.Iterator()
    54  	for iter.Next() {
    55  		v := iter.Value().(*ackedEvtBucket)
    56  		hashes := maps.Keys(v.hashes)
    57  		slices.Sort(hashes)
    58  		slice = append(slice, &snapshotpb.EventForwarderBucket{
    59  			Ts:     v.ts,
    60  			Hashes: hashes,
    61  		})
    62  	}
    63  
    64  	payload := types.Payload{
    65  		Data: &types.PayloadEventForwarder{
    66  			Buckets: slice,
    67  		},
    68  	}
    69  	return proto.Marshal(payload.IntoProto())
    70  }
    71  
    72  // get the serialised form of the given key.
    73  func (f *Forwarder) getSerialised(k string) (data []byte, err error) {
    74  	if k != key {
    75  		return nil, types.ErrSnapshotKeyDoesNotExist
    76  	}
    77  
    78  	return f.serialise()
    79  }
    80  
    81  func (f *Forwarder) GetState(k string) ([]byte, []types.StateProvider, error) {
    82  	state, err := f.getSerialised(k)
    83  	return state, nil, err
    84  }
    85  
    86  func (f *Forwarder) LoadState(ctx context.Context, p *types.Payload) ([]types.StateProvider, error) {
    87  	if f.Namespace() != p.Data.Namespace() {
    88  		return nil, types.ErrInvalidSnapshotNamespace
    89  	}
    90  	// see what we're reloading
    91  	if pl, ok := p.Data.(*types.PayloadEventForwarder); ok {
    92  		f.restore(ctx, pl)
    93  		return nil, nil
    94  	}
    95  
    96  	return nil, types.ErrUnknownSnapshotType
    97  }
    98  
    99  func (f *Forwarder) restore(ctx context.Context, p *types.PayloadEventForwarder) {
   100  	f.ackedEvts = &ackedEvents{
   101  		timeService: f.timeService,
   102  		events:      treeset.NewWith(ackedEvtBucketComparator),
   103  	}
   104  
   105  	// if we are executing a protocol upgrade,
   106  	// let's force bucketing things. This will reduce
   107  	// increase performance at startup, and everyone is starting
   108  	// from the same snapshot, so that will keep state consistent
   109  	if vgcontext.InProgressUpgrade(ctx) {
   110  		for _, v := range p.Buckets {
   111  			f.ackedEvts.AddAt(v.Ts, v.Hashes...)
   112  		}
   113  		return
   114  	}
   115  
   116  	for _, v := range p.Buckets {
   117  		f.ackedEvts.RestoreExactAt(v.Ts, v.Hashes...)
   118  	}
   119  }