code.vegaprotocol.io/vega@v0.79.0/core/broker/sequence_generator.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 broker 17 18 import ( 19 "sync" 20 21 "code.vegaprotocol.io/vega/core/events" 22 ) 23 24 type gen struct { 25 mu sync.Mutex 26 blockSeq map[string]uint64 27 blocks []string 28 } 29 30 func newGen() *gen { 31 return &gen{ 32 blockSeq: map[string]uint64{}, 33 blocks: make([]string, 0, 4), 34 } 35 } 36 37 // setSequence adds sequence ID to the event objects, returns the arguments because 38 // the events might be passed by value (interface values) 39 // returns the more restrictive event object - once seq ID is set, it should be treated as RO. 40 func (g *gen) setSequence(evts ...events.Event) []events.Event { 41 if len(evts) == 0 { 42 return nil 43 } 44 hash := evts[0].TraceID() 45 g.mu.Lock() 46 cur, ok := g.blockSeq[hash] 47 if !ok { 48 g.blocks = append(g.blocks, hash) 49 cur = 1 50 g.blockSeq[hash] = cur 51 // if we're adding a new hash, check if we're up to 3, and remove it if needed 52 defer g.cleanID() 53 } 54 // defer call stack is LIFO, cleanID acquires a lock, so ensure we release it here first 55 defer g.mu.Unlock() 56 // set sequence ID to the next sequence ID available 57 ret := make([]events.Event, 0, len(evts)) 58 // create slice of ids 59 for _, e := range evts { 60 e.SetSequenceID(cur) 61 // so if cur == 1 (new block), and we send 3 events with composite count of 1 -> cur == 4 (the next seq id to be set) 62 // if cur == 1, a composite count of 3 will send the event with seq ID 1, and set the next seq ID to be 1 + 3 == 4 63 // unpacking such an event leaves seq. ID 1, 2, and 3 available. 64 cur += e.CompositeCount() 65 ret = append(ret, e) 66 } 67 // update the mapk 68 g.blockSeq[hash] = cur 69 return ret 70 } 71 72 func (g *gen) cleanID() { 73 g.mu.Lock() 74 if len(g.blocks) == 4 { 75 delete(g.blockSeq, g.blocks[0]) 76 g.blocks = g.blocks[1:] 77 } 78 g.mu.Unlock() 79 }