Skip to content
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

fix(syncer): set timeout for head request #152

Merged
merged 4 commits into from
Feb 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions sync/sync_head.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import (
// Head returns the Network Head.
//
// Known subjective head is considered network head if it is recent enough(now-timestamp<=blocktime)
// Otherwise, head is requested from a trusted peer and
// Otherwise, we attempt to request recent network head from a trusted peer and
// set as the new subjective head, assuming that trusted peer is always fully synced.
//
// The request is limited with 2 seconds and otherwise potentially unrecent header is returned.
func (s *Syncer[H]) Head(ctx context.Context, _ ...header.HeadOption[H]) (H, error) {
sbjHead, err := s.subjectiveHead(ctx)
if err != nil {
Expand All @@ -23,12 +25,7 @@ func (s *Syncer[H]) Head(ctx context.Context, _ ...header.HeadOption[H]) (H, err
return sbjHead, nil
}
// otherwise, request head from the network
//
// TODO(@Wondertan): Here is another potential networking optimization:
// * From sbjHead's timestamp and current time predict the time to the next header(TNH)
// * If now >= TNH && now <= TNH + (THP) header propagation time
// * Wait for header to arrive instead of requesting it
// * This way we don't request as we know the new network header arrives exactly
// TODO: Besides requesting we should listen for new gossiped headers and cancel request if so
//
// single-flight protection
// ensure only one Head is requested at the time
Expand All @@ -38,7 +35,11 @@ func (s *Syncer[H]) Head(ctx context.Context, _ ...header.HeadOption[H]) (H, err
return s.Head(ctx)
}
defer s.getter.Unlock()
netHead, err := s.getter.Head(ctx, header.WithTrustedHead[H](sbjHead))
// limit time to get a recent header
// if we can't get it - give what we have
reqCtx, cancel := context.WithTimeout(ctx, time.Second*2) // TODO(@vgonkivs): make timeout configurable
defer cancel()
walldiss marked this conversation as resolved.
Show resolved Hide resolved
netHead, err := s.getter.Head(reqCtx, header.WithTrustedHead[H](sbjHead))
Wondertan marked this conversation as resolved.
Show resolved Hide resolved
Wondertan marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
log.Warnw("failed to get recent head, returning current subjective", "sbjHead", sbjHead.Height(), "err", err)
return s.subjectiveHead(ctx)
Expand Down
Loading