github.com/onflow/flow-go@v0.33.17/module/execution/registers_async.go (about) 1 package execution 2 3 import ( 4 "fmt" 5 6 "go.uber.org/atomic" 7 8 "github.com/onflow/flow-go/model/flow" 9 "github.com/onflow/flow-go/module/state_synchronization/indexer" 10 "github.com/onflow/flow-go/storage" 11 ) 12 13 // RegistersAsyncStore wraps an underlying register store so it can be used before the index is 14 // initialized. 15 type RegistersAsyncStore struct { 16 registerIndex *atomic.Pointer[storage.RegisterIndex] 17 } 18 19 func NewRegistersAsyncStore() *RegistersAsyncStore { 20 return &RegistersAsyncStore{ 21 registerIndex: atomic.NewPointer[storage.RegisterIndex](nil), 22 } 23 } 24 25 // Initialize initializes the underlying storage.RegisterIndex 26 // This method can be called at any time after the RegisterStore object is created. and before RegisterValues is called 27 // since we can't disambiguate between the underlying store before bootstrapping or just simply being behind sync 28 func (r *RegistersAsyncStore) Initialize(registers storage.RegisterIndex) error { 29 if r.registerIndex.CompareAndSwap(nil, ®isters) { 30 return nil 31 } 32 return fmt.Errorf("registers already initialized") 33 } 34 35 // RegisterValues gets the register values from the underlying storage.RegisterIndex 36 // Expected errors: 37 // - indexer.ErrIndexNotInitialized if the store is still bootstrapping 38 // - storage.ErrHeightNotIndexed if the values at the height is not indexed yet 39 // - storage.ErrNotFound if the register does not exist at the height 40 func (r *RegistersAsyncStore) RegisterValues(ids flow.RegisterIDs, height uint64) ([]flow.RegisterValue, error) { 41 registerStore, err := r.getRegisterStore() 42 if err != nil { 43 return nil, err 44 } 45 46 if height > registerStore.LatestHeight() || height < registerStore.FirstHeight() { 47 return nil, storage.ErrHeightNotIndexed 48 } 49 50 result := make([]flow.RegisterValue, len(ids)) 51 for i, regID := range ids { 52 val, err := registerStore.Get(regID, height) 53 if err != nil { 54 return nil, fmt.Errorf("failed to get register value for id %d: %w", i, err) 55 } 56 result[i] = val 57 } 58 return result, nil 59 } 60 61 func (r *RegistersAsyncStore) getRegisterStore() (storage.RegisterIndex, error) { 62 registerStore := r.registerIndex.Load() 63 if registerStore == nil { 64 return nil, indexer.ErrIndexNotInitialized 65 } 66 67 return *registerStore, nil 68 }