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 }