-
Notifications
You must be signed in to change notification settings - Fork 148
Fix BaseHeaderChainSyncer not following freshly created blocks #1790
Fix BaseHeaderChainSyncer not following freshly created blocks #1790
Conversation
| await asyncio.wait( | ||
| [task, syncer.manager.wait_finished()], | ||
| return_when=asyncio.FIRST_COMPLETED) | ||
| await self._full_skeleton_sync(syncer) |
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.
This doesn't look like the anti-pattern I described in ethereum/snake-charmers-tactical-manual#70. I haven't looked into how _full_skeleton_sync() is implemented, but I imagine it will crash somehow if syncer terminates
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.
Ah ok. I haven't fully groked yet why the code broke (could be a fall out from the migration to async-service).
What happens is that this loop of starting new skeleton syncs doesn't work anymore.
trinity/trinity/sync/common/headers.py
Lines 919 to 926 in 615d6bc
| async for peer in self._tip_monitor.wait_tip_info(): | |
| try: | |
| await self._validate_peer_is_ahead(peer) | |
| except _PeerBehind: | |
| self.logger.debug("At or behind peer %s, skipping skeleton sync", peer) | |
| else: | |
| async with self._get_skeleton_syncer(peer) as syncer: | |
| await self._full_skeleton_sync(syncer) |
Whenever the SkeletonSyncer cancels itself, we continue to hang on self._full_skeleton_sync(syncer) forever. The changes in this PR fixes it but it's probably not the right fix (hence the warnings). But I have an another idea to try out :)
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.
Ok, warnings are gone when I add task.cancel() but now it fails one of our tests 🙈 Investigating...
57b72e6 to
301f558
Compare
301f558 to
0f19bcb
Compare
| async def next_skeleton_segment(self) -> AsyncIterator[Tuple[BlockHeader, ...]]: | ||
| # @external_asyncio_api can not be used on `next_skeleton_segment` directly because | ||
| # it returns a generator. Maybe that could be fixed though? | ||
| @external_asyncio_api |
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.
If we can not use @external_asyncio_api directly on async def next_skeleton_segment then this feels like abusing the decorator I guess
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.
Yeah, agreed. It doesn't take too much work in async-service to expose the new API though, AFAICT.
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.
What was wrong?
As explained in #1788 our
BaseHeaderChainSyncercurrently fails to follow new blocks. It catches up to the tip and then stalls forever.How was it fixed?
It looks like this is a case of https://github.com/ethereum/snake-charmers-tactical-manual/pull/70/files (cc @gsalgado ) and I was able to get it to work with this fix.
However, this is breaking one of our tests and I'm beginning to think the proper fix would be to break out of this
yield awaitwhen theSkeletonSyncerwas canceled.trinity/trinity/sync/common/headers.py
Lines 119 to 122 in 615d6bc
Trying to figure out how to do that...
To-Do
Cute Animal Picture