github.com/koko1123/flow-go-1@v0.29.6/storage/badger/seals.go (about) 1 // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED 2 3 package badger 4 5 import ( 6 "fmt" 7 8 "github.com/dgraph-io/badger/v3" 9 10 "github.com/koko1123/flow-go-1/model/flow" 11 "github.com/koko1123/flow-go-1/module" 12 "github.com/koko1123/flow-go-1/module/metrics" 13 "github.com/koko1123/flow-go-1/storage/badger/operation" 14 "github.com/koko1123/flow-go-1/storage/badger/transaction" 15 ) 16 17 type Seals struct { 18 db *badger.DB 19 cache *Cache 20 } 21 22 func NewSeals(collector module.CacheMetrics, db *badger.DB) *Seals { 23 24 store := func(key interface{}, val interface{}) func(*transaction.Tx) error { 25 sealID := key.(flow.Identifier) 26 seal := val.(*flow.Seal) 27 return transaction.WithTx(operation.SkipDuplicates(operation.InsertSeal(sealID, seal))) 28 } 29 30 retrieve := func(key interface{}) func(*badger.Txn) (interface{}, error) { 31 sealID := key.(flow.Identifier) 32 var seal flow.Seal 33 return func(tx *badger.Txn) (interface{}, error) { 34 err := operation.RetrieveSeal(sealID, &seal)(tx) 35 return &seal, err 36 } 37 } 38 39 s := &Seals{ 40 db: db, 41 cache: newCache(collector, metrics.ResourceSeal, 42 withLimit(flow.DefaultTransactionExpiry+100), 43 withStore(store), 44 withRetrieve(retrieve)), 45 } 46 47 return s 48 } 49 50 func (s *Seals) storeTx(seal *flow.Seal) func(*transaction.Tx) error { 51 return s.cache.PutTx(seal.ID(), seal) 52 } 53 54 func (s *Seals) retrieveTx(sealID flow.Identifier) func(*badger.Txn) (*flow.Seal, error) { 55 return func(tx *badger.Txn) (*flow.Seal, error) { 56 val, err := s.cache.Get(sealID)(tx) 57 if err != nil { 58 return nil, err 59 } 60 return val.(*flow.Seal), err 61 } 62 } 63 64 func (s *Seals) Store(seal *flow.Seal) error { 65 return operation.RetryOnConflictTx(s.db, transaction.Update, s.storeTx(seal)) 66 } 67 68 func (s *Seals) ByID(sealID flow.Identifier) (*flow.Seal, error) { 69 tx := s.db.NewTransaction(false) 70 defer tx.Discard() 71 return s.retrieveTx(sealID)(tx) 72 } 73 74 // HighestInFork retrieves the highest seal that was included in the 75 // fork up to (and including) blockID. This method should return a seal 76 // for any block known to the node. Returns storage.ErrNotFound if 77 // blockID is unknown. 78 func (s *Seals) HighestInFork(blockID flow.Identifier) (*flow.Seal, error) { 79 var sealID flow.Identifier 80 err := s.db.View(operation.LookupLatestSealAtBlock(blockID, &sealID)) 81 if err != nil { 82 return nil, fmt.Errorf("failed to retrieve seal for fork with head %x: %w", blockID, err) 83 } 84 return s.ByID(sealID) 85 } 86 87 // FinalizedSealForBlock returns the seal for the given block, only if that seal 88 // has been included in a finalized block. 89 // Returns storage.ErrNotFound if the block is unknown or unsealed. 90 func (s *Seals) FinalizedSealForBlock(blockID flow.Identifier) (*flow.Seal, error) { 91 var sealID flow.Identifier 92 err := s.db.View(operation.LookupBySealedBlockID(blockID, &sealID)) 93 if err != nil { 94 return nil, fmt.Errorf("failed to retrieve seal for fork with head %x: %w", blockID, err) 95 } 96 return s.ByID(sealID) 97 }