github.com/diadata-org/diadata@v1.4.593/pkg/dia/helpers/substrate-helper/gsrpc/registry/retriever/event_retriever.go (about) 1 package retriever 2 3 import ( 4 "time" 5 6 "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry" 7 "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/exec" 8 "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/parser" 9 regState "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/registry/state" 10 "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/rpc/state" 11 "github.com/diadata-org/diadata/pkg/dia/helpers/substrate-helper/gsrpc/types" 12 ) 13 14 //nolint:lll 15 //go:generate mockery --name EventRetriever --structname EventRetrieverMock --filename event_retriever_mock.go --inpackage 16 17 // EventRetriever is the interface used for retrieving and decoding events. 18 type EventRetriever interface { 19 GetEvents(blockHash types.Hash) ([]*parser.Event, error) 20 } 21 22 // eventRetriever implements the EventRetriever interface. 23 type eventRetriever struct { 24 eventParser parser.EventParser 25 26 eventProvider regState.EventProvider 27 stateRPC state.State 28 29 registryFactory registry.Factory 30 31 eventStorageExecutor exec.RetryableExecutor[*types.StorageDataRaw] 32 eventParsingExecutor exec.RetryableExecutor[[]*parser.Event] 33 34 eventRegistry registry.EventRegistry 35 meta *types.Metadata 36 } 37 38 // NewEventRetriever creates a new EventRetriever. 39 func NewEventRetriever( 40 eventParser parser.EventParser, 41 eventProvider regState.EventProvider, 42 stateRPC state.State, 43 registryFactory registry.Factory, 44 eventStorageExecutor exec.RetryableExecutor[*types.StorageDataRaw], 45 eventParsingExecutor exec.RetryableExecutor[[]*parser.Event], 46 ) (EventRetriever, error) { 47 retriever := &eventRetriever{ 48 eventParser: eventParser, 49 eventProvider: eventProvider, 50 stateRPC: stateRPC, 51 registryFactory: registryFactory, 52 eventStorageExecutor: eventStorageExecutor, 53 eventParsingExecutor: eventParsingExecutor, 54 } 55 56 if err := retriever.updateInternalState(nil); err != nil { 57 return nil, ErrInternalStateUpdate.Wrap(err) 58 } 59 60 return retriever, nil 61 } 62 63 // NewDefaultEventRetriever creates a new EventRetriever using defaults for: 64 // 65 // - parser.EventParser 66 // - registry.Factory 67 // - exec.RetryableExecutor - used for retrieving event storage data. 68 // - exec.RetryableExecutor - used for parsing events. 69 func NewDefaultEventRetriever( 70 eventProvider regState.EventProvider, 71 stateRPC state.State, 72 fieldOverrides ...registry.FieldOverride, 73 ) (EventRetriever, error) { 74 eventParser := parser.NewEventParser() 75 registryFactory := registry.NewFactory(fieldOverrides...) 76 77 eventStorageExecutor := exec.NewRetryableExecutor[*types.StorageDataRaw](exec.WithRetryTimeout(1 * time.Second)) 78 eventParsingExecutor := exec.NewRetryableExecutor[[]*parser.Event](exec.WithMaxRetryCount(1)) 79 80 return NewEventRetriever( 81 eventParser, 82 eventProvider, 83 stateRPC, 84 registryFactory, 85 eventStorageExecutor, 86 eventParsingExecutor, 87 ) 88 } 89 90 // GetEvents retrieves the storage data for an Event and then parses it. 91 // 92 // Both the event storage data retrieval and the event parsing are handled via the exec.RetryableExecutor 93 // in order to ensure retries in case of network errors or parsing errors due to an outdated event registry. 94 func (e *eventRetriever) GetEvents(blockHash types.Hash) ([]*parser.Event, error) { 95 storageEvents, err := e.eventStorageExecutor.ExecWithFallback( 96 func() (*types.StorageDataRaw, error) { 97 return e.eventProvider.GetStorageEvents(e.meta, blockHash) 98 }, 99 func() error { 100 return e.updateInternalState(&blockHash) 101 }, 102 ) 103 104 if err != nil { 105 return nil, ErrStorageEventRetrieval.Wrap(err) 106 } 107 108 events, err := e.eventParsingExecutor.ExecWithFallback( 109 func() ([]*parser.Event, error) { 110 return e.eventParser.ParseEvents(e.eventRegistry, storageEvents) 111 }, 112 func() error { 113 return e.updateInternalState(&blockHash) 114 }, 115 ) 116 117 if err != nil { 118 return nil, ErrEventParsing.Wrap(err) 119 } 120 121 return events, nil 122 } 123 124 // updateInternalState will retrieve the metadata at the provided blockHash, if provided, 125 // create an event registry based on this metadata and store both. 126 func (e *eventRetriever) updateInternalState(blockHash *types.Hash) error { 127 var ( 128 meta *types.Metadata 129 err error 130 ) 131 132 if blockHash == nil { 133 meta, err = e.stateRPC.GetMetadataLatest() 134 } else { 135 meta, err = e.stateRPC.GetMetadata(*blockHash) 136 } 137 138 if err != nil { 139 return ErrMetadataRetrieval.Wrap(err) 140 } 141 142 eventRegistry, err := e.registryFactory.CreateEventRegistry(meta) 143 144 if err != nil { 145 return ErrEventRegistryCreation.Wrap(err) 146 } 147 148 e.meta = meta 149 e.eventRegistry = eventRegistry 150 151 return nil 152 }