Skip to content

Fix corrupted Dynamic Contracts table on restart - #416

Merged
DZakh merged 3 commits into
mainfrom
dz/fix-corrupted-db-on-restart
Jan 14, 2025
Merged

Fix corrupted Dynamic Contracts table on restart#416
DZakh merged 3 commits into
mainfrom
dz/fix-corrupted-db-on-restart

Conversation

@DZakh

@DZakh DZakh commented Jan 13, 2025

Copy link
Copy Markdown
Member
image

Case:

  1. Let's say we have a chain with 100_000 blocks and reorg threshold 200
  2. We query range 90_000-100_000 and get two contract registrations at 95_000 and 99_900 blocks
  3. Indexer will process events between 90_000-95_000 blocks (until the first dc)
  4. Also, it'll register two dcs in the fetch state and store them in db, but the second dc is in the reorg threshold, so it saves with an entity history.
  5. The batch finishes processing and stores entities in the db
  6. For any reason indexer restarts and starts querying, let's say, from the block 99_000
  7. Since the dc at block 99_900 wasn't recovered during the restart (which's correct), we register it again and add to the in memory store
  8. And if it's still in the reorg threshold, we'll try to add the same dc history entity which will fail with a conflict.

Solution:
Clean up dcs after a restart point from db, two prevent the invalid state.

@DZakh
DZakh requested a review from JasoonS January 13, 2025 16:39
@DZakh

DZakh commented Jan 13, 2025

Copy link
Copy Markdown
Member Author

@JasoonS Ignore the failing test. The logic is correct

entity_history_block_number > ${restartBlockNumber}
OR entity_history_block_number = ${restartBlockNumber}
AND entity_history_log_index > ${restartLogIndex}
);`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool makes sense.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the other option is that instead of deleting them on restart, we upsert them, but agree that deleting makes things consistent between restart runs and runs without restarts and removes potential for strange behavior on edge cases. 👍

* This function allows a chain fetcher to be created from metadata, in particular this is useful for restarting an indexer and making sure it fetches blocks from the same place.
*/
let makeFromDbState = async (chainConfig: Config.chainConfig, ~maxAddrInPartition) => {
let makeFromDbState = async (chainConfig: Config.chainConfig, ~maxAddrInPartition, ~sql=Db.sql) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any significance in passing the sql as a parameter here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to pass a transaction context in tests, so I can rollback dynamic contracts after they are deleted

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it is to make it easier to test I assume - nice 👍

@DZakh
DZakh merged commit 3791202 into main Jan 14, 2025
@DZakh
DZakh deleted the dz/fix-corrupted-db-on-restart branch January 14, 2025 07:31
DZakh added a commit that referenced this pull request Jan 14, 2025
* Fix corrupted Dynamic Contracts table on restart

* Add a few more test cases

* Fix test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants