-
Notifications
You must be signed in to change notification settings - Fork 120
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
updater.StopBot should close polling context #211
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,18 +157,20 @@ func (u *Updater) StartPolling(b *gotgbot.Bot, opts *PollingOpts) error { | |
} | ||
} | ||
|
||
bData, err := u.botMapping.addBot(b, "", "") | ||
ctx, closeFn := context.WithCancel(context.Background()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could reuse the opts logic to pass in an updater from #210 here - might be a good way to handle signals? Though the signals approach would only close the updater, not the dispatcher; so might be best to handle closure explitly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this approach is much better than in #210 - the library should not be concerned about any of the OS signals — it just needs to know one thing: "something wants the updater to stop". And technically it doesn't need the Context, as it's not going to use it for anything else but only to know when it's cancelled. Handing specific OS signals and termination is a caller's concern, for example, that's how the echoBot could handle the os.Interrupt signal and tell the bot to terminate — works great on this branch: diff --git a/samples/echoBot/main.go b/samples/echoBot/main.go
index bdffc88..2f390b1 100644
--- a/samples/echoBot/main.go
+++ b/samples/echoBot/main.go
@@ -1,10 +1,12 @@
package main
import (
+ "context"
"fmt"
"log"
"net/http"
"os"
+ "os/signal"
"time"
"github.com/PaulSonOfLars/gotgbot/v2"
@@ -34,6 +36,8 @@ func main() {
if err != nil {
panic("failed to create new bot: " + err.Error())
}
+ ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
+ defer cancel()
// Create updater and dispatcher.
dispatcher := ext.NewDispatcher(&ext.DispatcherOpts{
@@ -45,6 +49,11 @@ func main() {
MaxRoutines: ext.DefaultMaxRoutines,
})
updater := ext.NewUpdater(dispatcher, nil)
+ go func() {
+ <-ctx.Done()
+ log.Println("shutting down...")
+ updater.Stop()
+ }()
// Add echo handler to reply to all text messages.
dispatcher.AddHandler(handlers.NewMessage(message.Text, echo)) |
||
|
||
bData, err := u.botMapping.addPollingBot(b, closeFn) | ||
if err != nil { | ||
return fmt.Errorf("failed to add bot with long polling: %w", err) | ||
} | ||
|
||
go u.Dispatcher.Start(b, bData.updateChan) | ||
go u.pollingLoop(bData, reqOpts, v) | ||
go u.pollingLoop(ctx, bData, reqOpts, v) | ||
|
||
return nil | ||
} | ||
|
||
func (u *Updater) pollingLoop(bData *botData, opts *gotgbot.RequestOpts, v map[string]string) { | ||
func (u *Updater) pollingLoop(ctx context.Context, bData *botData, opts *gotgbot.RequestOpts, v map[string]string) { | ||
bData.updateWriterControl.Add(1) | ||
defer bData.updateWriterControl.Done() | ||
|
||
|
@@ -180,8 +182,13 @@ func (u *Updater) pollingLoop(bData *botData, opts *gotgbot.RequestOpts, v map[s | |
|
||
// Manually craft the getUpdate calls to improve memory management, reduce json parsing overheads, and | ||
// unnecessary reallocation of url.Values in the polling loop. | ||
r, err := bData.bot.Request("getUpdates", v, nil, opts) | ||
r, err := bData.bot.RequestWithContext(ctx, "getUpdates", v, nil, opts) | ||
if err != nil { | ||
if errors.Is(err, context.Canceled) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Beautiful |
||
// context cancelled; means the bot was stopped gracefully through Updater.StopBot | ||
return | ||
} | ||
|
||
if u.UnhandledErrFunc != nil { | ||
u.UnhandledErrFunc(err) | ||
} else { | ||
|
@@ -317,7 +324,7 @@ func (u *Updater) AddWebhook(b *gotgbot.Bot, urlPath string, opts *AddWebhookOpt | |
secretToken = opts.SecretToken | ||
} | ||
|
||
bData, err := u.botMapping.addBot(b, urlPath, secretToken) | ||
bData, err := u.botMapping.addWebhookBot(b, urlPath, secretToken) | ||
if err != nil { | ||
return fmt.Errorf("failed to add webhook for bot: %w", err) | ||
} | ||
|
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.
I was suspecting this test might fail if executed with
-race
, but the different one failed instead.Note: this possibly does not impact the bot's behaviour in real environment, just a quirk of how the test is accessing the data.
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 you're unable to get it to fail, so running like this helps:
takes a long time tho to run.
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.
Interesting - theres definitely something funky going on there, not sure what exactly. Will take a look. Might be a different PR, depending on how long it takes! Thanks for the review and the report <3