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

Crude implementation of context propagation to Updater #210

Closed
wants to merge 1 commit into from

Conversation

rusq
Copy link

@rusq rusq commented Dec 21, 2024

What

Propagate parent Context to updater to prevent it idling till the next update when Stop is called.

This is draft and crude, and is intended to be a starting point for discussion.

Impact

  • A new field is added to the PollingOpts - ParentCtx that allows passing the parent Context.
    • If it is nil, it is initialised with context.Background() to prevent nil pointer dereference.
  • Each Request originating from the poller is created with the ParentCtx, when it's cancelled, user may
    observe "Request Failed: context cancelled" in the logs.
  • I had to pull the <-bData.stopUpdates to be on the same level as ctx.Done() check, and I don't like it.
    • This happened because I noticed it is called in the handler, I could have used r.Context() instead,
      but wasn't sure of consequences. What if the request is terminated and that context is dead?

@@ -47,8 +47,10 @@ type botMapping struct {
errorLog *log.Logger
}

var ErrBotAlreadyExists = errors.New("bot already exists in bot mapping")
var ErrBotUrlPathAlreadyExists = errors.New("url path already exists in bot mapping")
var (
Copy link
Author

Choose a reason for hiding this comment

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

Excuse my formatter

bData.updateWriterControl.Add(1)
defer bData.updateWriterControl.Done()

for {
select {
case <-bData.stopUpdates:
Copy link
Author

Choose a reason for hiding this comment

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

This duplicates the check in shouldStopUpdates

Copy link
Owner

Choose a reason for hiding this comment

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

I don't think we need this; RequestWithContext would handle the exit for us if necessary

// sentinel, when the context is done, stop all bots.
<-ctx.Done()
updater.Stop()
updater.StopAllBots()
Copy link
Author

Choose a reason for hiding this comment

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

Initially just called StopAllBots, but that wasn't enough to stop updater from Idle()'ing.

Copy link
Owner

Choose a reason for hiding this comment

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

Hmm. that might be worth discussing in itself!

Copy link
Owner

@PaulSonOfLars PaulSonOfLars left a comment

Choose a reason for hiding this comment

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

Interesting approach!

Definitely helpful to handle os signals, but I think it misses the usecase of a bot being able to "stop" itself, which I expect is a common usecase (eg, see the multibot example). What do you think?

I've given it my shot in #211; let me know what you think!

@@ -163,24 +168,31 @@ func (u *Updater) StartPolling(b *gotgbot.Bot, opts *PollingOpts) error {
}

go u.Dispatcher.Start(b, bData.updateChan)
go u.pollingLoop(bData, reqOpts, v)
go u.pollingLoop(opts.ParentCtx, bData, reqOpts, v)
Copy link
Owner

Choose a reason for hiding this comment

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

note: this risks a nil pointer if opts is nil :)

Copy link
Author

Choose a reason for hiding this comment

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

Shoot!

bData.updateWriterControl.Add(1)
defer bData.updateWriterControl.Done()

for {
select {
case <-bData.stopUpdates:
Copy link
Owner

Choose a reason for hiding this comment

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

I don't think we need this; RequestWithContext would handle the exit for us if necessary

// sentinel, when the context is done, stop all bots.
<-ctx.Done()
updater.Stop()
updater.StopAllBots()
Copy link
Owner

Choose a reason for hiding this comment

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

Hmm. that might be worth discussing in itself!

@rusq
Copy link
Author

rusq commented Dec 22, 2024

Thanks for your comments! I think #211 nails it, so I'll close this PR.

@rusq rusq closed this Dec 22, 2024
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