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

Improve Pacer Error Handling #1938

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open

Improve Pacer Error Handling #1938

wants to merge 8 commits into from

Conversation

RodrigoVillar
Copy link
Contributor

@RodrigoVillar RodrigoVillar commented Feb 21, 2025

This PR improves the error handling of pacer with the following:

  • Add an setError() method to make sure errors are written exactly once.
    • Introduce error which allows for one write, multiple reads
  • Modify Run() to terminate if an error was produced in Add()
  • Modify Add() to terminate if an error was caught and to stop pacer if WS client produces an error.
  • Modify Wait() to wait for outstanding TXs to be processed and to set a nil error if no error was caught.

@RodrigoVillar RodrigoVillar marked this pull request as ready for review February 21, 2025 17:29
@RodrigoVillar RodrigoVillar self-assigned this Feb 24, 2025
}

func (p *pacer) Run(ctx context.Context, max int) {
p.inflight = make(chan struct{}, max)
p.done = make(chan error, 1)
p.done = make(chan struct{}, 1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this be empty? We only need to signal it's been closed, there's no need to initialize it to a length of 1

Comment on lines 39 to 41
if !ok {
return
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need this !ok check?

@@ -341,6 +341,7 @@ func (s *Spammer) distributeFunds(ctx context.Context, parser chain.Parser, feeP
return nil, nil, err
}
if err := p.Add(tx); err != nil {
_ = p.Wait()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need to call p.Wait() here? Same comment below.

Comment on lines +57 to +63
if p.err != nil {
return p.err
}

if err := p.ws.RegisterTx(tx); err != nil {
return err
p.setError(err)
return p.err
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to check p.err here or can we register the tx and read the err iff p.done has been closed?

Since this value is set at most once immediately before p.done is closed, we should technically check that the channel has been closed before reading this value.

Comment on lines +80 to +84
func (p *pacer) setError(err error) {
p.errOnce.Do(func() {
p.err = err
close(p.done)
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we make this even simpler by removing errOnce and using defer close(p.done) within Run ?

This way there's only one place where p.done can be closed and it's explicit that it will be called once from that function.

If we handle it this way, it means that we can write the error value once within that function and rely on the deferred call to make sure it's closed before any reader accesses it (assuming we also remove reads of p.err within Add.

Comment on lines +32 to +35
if !ok {
p.setError(nil)
return
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need this check?

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