-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(VDB-955) Associate diffs with headers #6
Changes from 2 commits
48b6915
5c9a054
d73a988
e5973ea
b30c2cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,35 +18,54 @@ package watcher | |
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/makerdao/vulcanizedb/libraries/shared/fetcher" | ||
"github.com/makerdao/vulcanizedb/libraries/shared/storage" | ||
"github.com/makerdao/vulcanizedb/libraries/shared/storage/utils" | ||
"github.com/makerdao/vulcanizedb/libraries/shared/transformer" | ||
"github.com/makerdao/vulcanizedb/pkg/datastore" | ||
"github.com/makerdao/vulcanizedb/pkg/datastore/postgres" | ||
"github.com/makerdao/vulcanizedb/pkg/datastore/postgres/repositories" | ||
"github.com/sirupsen/logrus" | ||
"time" | ||
) | ||
|
||
type ErrHeaderMismatch struct { | ||
dbHash string | ||
diffHash string | ||
} | ||
|
||
func NewErrHeaderMismatch(DBHash, diffHash string) *ErrHeaderMismatch { | ||
return &ErrHeaderMismatch{dbHash: DBHash, diffHash: diffHash} | ||
} | ||
|
||
func (e ErrHeaderMismatch) Error() string { | ||
return fmt.Sprintf("db header hash (%s) doesn't match diff header hash (%s)", e.dbHash, e.diffHash) | ||
} | ||
|
||
type IStorageWatcher interface { | ||
AddTransformers(initializers []transformer.StorageTransformerInitializer) | ||
Execute(diffsChan chan utils.StorageDiff, errsChan chan error, queueRecheckInterval time.Duration) | ||
Execute(queueRecheckInterval time.Duration) error | ||
} | ||
|
||
type StorageWatcher struct { | ||
db *postgres.DB | ||
StorageFetcher fetcher.IStorageFetcher | ||
Queue storage.IStorageQueue | ||
HeaderRepository datastore.HeaderRepository | ||
KeccakAddressTransformers map[common.Hash]transformer.StorageTransformer // keccak hash of an address => transformer | ||
} | ||
|
||
func NewStorageWatcher(fetcher fetcher.IStorageFetcher, db *postgres.DB) StorageWatcher { | ||
queue := storage.NewStorageQueue(db) | ||
headerRepository := repositories.NewHeaderRepository(db) | ||
transformers := make(map[common.Hash]transformer.StorageTransformer) | ||
return StorageWatcher{ | ||
db: db, | ||
StorageFetcher: fetcher, | ||
Queue: queue, | ||
HeaderRepository: headerRepository, | ||
KeccakAddressTransformers: transformers, | ||
} | ||
} | ||
|
@@ -58,13 +77,21 @@ func (storageWatcher StorageWatcher) AddTransformers(initializers []transformer. | |
} | ||
} | ||
|
||
func (storageWatcher StorageWatcher) Execute(diffsChan chan utils.StorageDiff, errsChan chan error, queueRecheckInterval time.Duration) { | ||
func (storageWatcher StorageWatcher) Execute(queueRecheckInterval time.Duration) error { | ||
ticker := time.NewTicker(queueRecheckInterval) | ||
diffsChan := make(chan utils.StorageDiff) | ||
errsChan := make(chan error) | ||
|
||
defer close(diffsChan) | ||
defer close(errsChan) | ||
|
||
go storageWatcher.StorageFetcher.FetchStorageDiffs(diffsChan, errsChan) | ||
|
||
for { | ||
select { | ||
case fetchErr := <-errsChan: | ||
logrus.Warn(fmt.Sprintf("error fetching storage diffs: %s", fetchErr)) | ||
logrus.Warnf("error fetching storage diffs: %s", fetchErr.Error()) | ||
return fetchErr | ||
case diff := <-diffsChan: | ||
storageWatcher.processRow(diff) | ||
case <-ticker.C: | ||
|
@@ -79,43 +106,78 @@ func (storageWatcher StorageWatcher) getTransformer(diff utils.StorageDiff) (tra | |
} | ||
|
||
func (storageWatcher StorageWatcher) processRow(diff utils.StorageDiff) { | ||
storageTransformer, ok := storageWatcher.getTransformer(diff) | ||
if !ok { | ||
logrus.Debug("ignoring a diff from an unwatched contract") | ||
storageTransformer, isTransformerWatchingAddress := storageWatcher.getTransformer(diff) | ||
if !isTransformerWatchingAddress { | ||
logrus.Debug("ignoring diff from an unwatched contract") | ||
return | ||
} | ||
|
||
headerID, err := storageWatcher.getHeaderID(diff) | ||
if err != nil { | ||
logrus.Infof("error getting header for diff: %s", err.Error()) | ||
storageWatcher.queueDiff(diff) | ||
return | ||
} | ||
diff.HeaderID = headerID | ||
|
||
executeErr := storageTransformer.Execute(diff) | ||
if executeErr != nil { | ||
logrus.Warn(fmt.Sprintf("error executing storage transformer: %s", executeErr)) | ||
queueErr := storageWatcher.Queue.Add(diff) | ||
if queueErr != nil { | ||
logrus.Warn(fmt.Sprintf("error queueing storage diff: %s", queueErr)) | ||
} | ||
logrus.Infof("error executing storage transformer: %s", executeErr.Error()) | ||
storageWatcher.queueDiff(diff) | ||
} | ||
} | ||
|
||
func (storageWatcher StorageWatcher) processQueue() { | ||
diffs, fetchErr := storageWatcher.Queue.GetAll() | ||
if fetchErr != nil { | ||
logrus.Warn(fmt.Sprintf("error getting queued storage: %s", fetchErr)) | ||
logrus.Infof("error getting queued storage: %s", fetchErr.Error()) | ||
} | ||
|
||
for _, diff := range diffs { | ||
storageTransformer, ok := storageWatcher.getTransformer(diff) | ||
if !ok { | ||
// delete diff from queue if address no longer watched | ||
headerID, getHeaderErr := storageWatcher.getHeaderID(diff) | ||
if getHeaderErr != nil { | ||
logrus.Infof("error getting header for diff: %s", getHeaderErr.Error()) | ||
continue | ||
} | ||
diff.HeaderID = headerID | ||
|
||
storageTransformer, isTransformerWatchingAddress := storageWatcher.getTransformer(diff) | ||
if !isTransformerWatchingAddress { | ||
storageWatcher.deleteRow(diff.Id) | ||
continue | ||
} | ||
|
||
executeErr := storageTransformer.Execute(diff) | ||
if executeErr == nil { | ||
storageWatcher.deleteRow(diff.Id) | ||
if executeErr != nil { | ||
logrus.Infof("error executing storage transformer: %s", executeErr.Error()) | ||
continue | ||
} | ||
|
||
storageWatcher.deleteRow(diff.Id) | ||
} | ||
} | ||
|
||
func (storageWatcher StorageWatcher) deleteRow(id int) { | ||
deleteErr := storageWatcher.Queue.Delete(id) | ||
if deleteErr != nil { | ||
logrus.Warn(fmt.Sprintf("error deleting persisted diff from queue: %s", deleteErr)) | ||
logrus.Infof("error deleting persisted diff from queue: %s", deleteErr.Error()) | ||
} | ||
} | ||
|
||
func (storageWatcher StorageWatcher) queueDiff(diff utils.StorageDiff) { | ||
queueErr := storageWatcher.Queue.Add(diff) | ||
if queueErr != nil { | ||
logrus.Infof("error queueing storage diff: %s", queueErr.Error()) | ||
} | ||
} | ||
|
||
func (storageWatcher StorageWatcher) getHeaderID(diff utils.StorageDiff) (int64, error) { | ||
header, getHeaderErr := storageWatcher.HeaderRepository.GetHeader(int64(diff.BlockHeight)) | ||
if getHeaderErr != nil { | ||
return 0, getHeaderErr | ||
} | ||
if diff.BlockHash.Hex() != header.Hash { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thinking maybe this should convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done d73a988 |
||
return 0, NewErrHeaderMismatch(header.Hash, diff.BlockHash.Hex()) | ||
} | ||
return header.Id, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯