code.vegaprotocol.io/vega@v0.79.0/core/checkpoint/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 checkpoint 17 18 import ( 19 "context" 20 "time" 21 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/proto" 24 "code.vegaprotocol.io/vega/logging" 25 ) 26 27 func (e *Engine) Namespace() types.SnapshotNamespace { 28 return e.state.Namespace() 29 } 30 31 func (e *Engine) Keys() []string { 32 return []string{ 33 e.state.Key(), 34 } 35 } 36 37 func (e *Engine) Stopped() bool { 38 return false 39 } 40 41 func (e *Engine) setNextCP(t time.Time) { 42 e.nextCP = t 43 e.state.Checkpoint.NextCp = t.UnixNano() 44 e.data = []byte{} 45 e.updated = true 46 } 47 48 func (e *Engine) GetState(k string) ([]byte, []types.StateProvider, error) { 49 if k != e.state.Key() { 50 return nil, nil, types.ErrSnapshotKeyDoesNotExist 51 } 52 if len(e.data) == 0 { 53 if err := e.serialiseState(); err != nil { 54 return nil, nil, err 55 } 56 } 57 return e.data, nil, nil 58 } 59 60 func (e *Engine) serialiseState() error { 61 e.log.Debug("serialising checkpoint", logging.Int64("nextcp", e.state.Checkpoint.NextCp)) 62 pl := types.Payload{ 63 Data: e.state, 64 } 65 data, err := proto.Marshal(pl.IntoProto()) 66 if err != nil { 67 return err 68 } 69 70 e.data = data 71 return nil 72 } 73 74 func (e *Engine) LoadState(_ context.Context, snap *types.Payload) ([]types.StateProvider, error) { 75 if snap.Namespace() != e.state.Namespace() { 76 return nil, types.ErrInvalidSnapshotNamespace 77 } 78 if snap.Key() != e.state.Key() { 79 return nil, types.ErrSnapshotKeyDoesNotExist 80 } 81 state := snap.Data.(*types.PayloadCheckpoint) 82 e.state = state 83 e.setNextCP(time.Unix(0, state.Checkpoint.NextCp)) 84 e.log.Debug("loaded checkpoint snapshot", logging.Int64("nextcp", e.state.Checkpoint.NextCp)) 85 return nil, nil 86 } 87 88 func (e *Engine) PollChanges(ctx context.Context, k string, ch chan<- *types.Payload) { 89 e.poll = make(chan struct{}) 90 defer func() { 91 close(e.poll) 92 }() 93 if k != e.state.Key() { 94 e.snapErr = types.ErrSnapshotKeyDoesNotExist 95 ch <- nil 96 return 97 } 98 if !e.updated { 99 // nil on channel indicates no changes 100 ch <- nil 101 return 102 } 103 // create the payload object for snapshot 104 pl := types.Payload{ 105 Data: &types.PayloadCheckpoint{ 106 Checkpoint: &types.CPState{ 107 NextCp: e.nextCP.UnixNano(), 108 }, 109 }, 110 } 111 select { 112 case <-ctx.Done(): 113 e.snapErr = ctx.Err() 114 return 115 default: 116 // send new update, flag as done 117 ch <- &pl 118 e.updated = false 119 } 120 } 121 122 func (e *Engine) Sync() error { 123 <-e.poll 124 return e.Err() 125 } 126 127 func (e *Engine) Err() error { 128 err := e.snapErr 129 // remove error 130 e.snapErr = nil 131 return err 132 }